From nicolas.geoffray at lip6.fr Mon Jul 6 00:59:27 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 06 Jul 2009 07:59:27 -0000 Subject: [vmkit-commits] [vmkit] r74818 - in /vmkit/trunk: include/mvm/JIT.h lib/JnJVM/Compiler/JnjvmModule.cpp lib/Mvm/Compiler/JIT.cpp lib/N3/VMCore/N3.cpp tools/vmjc/vmjc.cpp Message-ID: <200907060759.n667xSba010706@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 6 02:59:25 2009 New Revision: 74818 URL: http://llvm.org/viewvc/llvm-project?rev=74818&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/include/mvm/JIT.h vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp vmkit/trunk/lib/N3/VMCore/N3.cpp vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/include/mvm/JIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=74818&r1=74817&r2=74818&view=diff ============================================================================== --- vmkit/trunk/include/mvm/JIT.h (original) +++ vmkit/trunk/include/mvm/JIT.h Mon Jul 6 02:59:25 2009 @@ -26,6 +26,7 @@ class ExistingModuleProvider; class Function; class FunctionPassManager; + class LLVMContext; class Module; class ModuleProvider; class PointerType; @@ -167,6 +168,7 @@ static llvm::ExecutionEngine* executionEngine; static mvm::LockNormal protectEngine; static llvm::Module *globalModule; + static llvm::LLVMContext *globalContext; static llvm::ExistingModuleProvider *globalModuleProvider; static llvm::FunctionPassManager* globalFunctionPasses; static const llvm::TargetData* TheTargetData; Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=74818&r1=74817&r2=74818&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Mon Jul 6 02:59:25 2009 @@ -11,6 +11,7 @@ #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetData.h" @@ -81,7 +82,8 @@ JavaLLVMCompiler::JavaLLVMCompiler(const std::string& str) : - TheModule(new llvm::Module(str)), JavaIntrinsics(TheModule) { + TheModule(new llvm::Module(str, *(new llvm::LLVMContext()))), + JavaIntrinsics(TheModule) { enabledException = true; } Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=74818&r1=74817&r2=74818&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 6 02:59:25 2009 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -54,7 +55,8 @@ llvm::ExceptionHandling = false; #endif if (!M) { - globalModule = new llvm::Module("bootstrap module"); + globalContext = new llvm::LLVMContext(); + globalModule = new llvm::Module("bootstrap module", *globalContext); globalModuleProvider = new ExistingModuleProvider (globalModule); InitializeNativeTarget(); @@ -258,6 +260,7 @@ const llvm::TargetData* MvmModule::TheTargetData; llvm::Module *MvmModule::globalModule; +llvm::LLVMContext *MvmModule::globalContext; llvm::ExistingModuleProvider *MvmModule::globalModuleProvider; llvm::FunctionPassManager* MvmModule::globalFunctionPasses; llvm::ExecutionEngine* MvmModule::executionEngine; Modified: vmkit/trunk/lib/N3/VMCore/N3.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/N3.cpp?rev=74818&r1=74817&r2=74818&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/N3.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/N3.cpp Mon Jul 6 02:59:25 2009 @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Support/CommandLine.h" @@ -64,7 +65,7 @@ std::string str = mvm::MvmModule::executionEngine->getTargetData()->getStringRepresentation(); - vm->LLVMModule = new llvm::Module("Bootstrap N3"); + vm->LLVMModule = new llvm::Module("Bootstrap N3", *(new llvm::LLVMContext())); vm->module = new mvm::MvmModule(vm->LLVMModule); vm->getLLVMModule()->setDataLayout(str); vm->protectModule = new mvm::LockNormal(); @@ -88,7 +89,7 @@ std::string str = mvm::MvmModule::executionEngine->getTargetData()->getStringRepresentation(); - vm->LLVMModule = new llvm::Module("Bootstrap N3"); + vm->LLVMModule = new llvm::Module("Bootstrap N3", *(new llvm::LLVMContext())); vm->module = new mvm::MvmModule(vm->LLVMModule); vm->LLVMModule->setDataLayout(str); vm->protectModule = new mvm::LockNormal(); Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=74818&r1=74817&r2=74818&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Mon Jul 6 02:59:25 2009 @@ -177,7 +177,8 @@ JavaCompiler* Comp = 0; if (WithClinit.empty()) { - Module* TheModule = new Module("bootstrap module"); + Module* TheModule = new Module("bootstrap module", + *(new llvm::LLVMContext())); if (!TargetTriple.empty()) TheModule->setTargetTriple(TargetTriple); else From nicolas.geoffray at lip6.fr Mon Jul 6 02:00:23 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 06 Jul 2009 09:00:23 -0000 Subject: [vmkit-commits] [vmkit] r74820 - /vmkit/trunk/lib/Mvm/GCMmap2/gcinit.cpp Message-ID: <200907060900.n6690NEh012295@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 6 04:00:22 2009 New Revision: 74820 URL: http://llvm.org/viewvc/llvm-project?rev=74820&view=rev Log: Shrink the GC frequency. Modified: vmkit/trunk/lib/Mvm/GCMmap2/gcinit.cpp Modified: vmkit/trunk/lib/Mvm/GCMmap2/gcinit.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gcinit.cpp?rev=74820&r1=74819&r2=74820&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/gcinit.cpp (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/gcinit.cpp Mon Jul 6 04:00:22 2009 @@ -12,8 +12,8 @@ using namespace mvm; -static const size_t def_collect_freq_auto = 4*1024*1024; -static const size_t def_collect_freq_maybe = 512*1024; +static const size_t def_collect_freq_auto = 64*1024*1024; +static const size_t def_collect_freq_maybe = 64*1024*1024; #if defined(__MACH__) # define SIGGC SIGXCPU From nicolas.geoffray at lip6.fr Mon Jul 6 06:27:46 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 06 Jul 2009 13:27:46 -0000 Subject: [vmkit-commits] [vmkit] r74824 - in /vmkit/trunk/lib/N3/VMCore: MSCorlib.cpp MSCorlib.inc N3.cpp Message-ID: <200907061327.n66DRmUk021628@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 6 08:27:41 2009 New Revision: 74824 URL: http://llvm.org/viewvc/llvm-project?rev=74824&view=rev Log: Force linking of runtime functions in N3. Added: vmkit/trunk/lib/N3/VMCore/MSCorlib.inc - copied unchanged from r73947, vmkit/trunk/lib/N3/VMCore/MSCorlib.cpp Removed: vmkit/trunk/lib/N3/VMCore/MSCorlib.cpp Modified: vmkit/trunk/lib/N3/VMCore/N3.cpp Removed: vmkit/trunk/lib/N3/VMCore/MSCorlib.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/MSCorlib.cpp?rev=74823&view=auto ============================================================================== --- vmkit/trunk/lib/N3/VMCore/MSCorlib.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/MSCorlib.cpp (removed) @@ -1,236 +0,0 @@ -//===------------- MSCorlib.cpp - mscorlib interface ----------------------===// -// -// N3 -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include - -#include -#include - -#include "mvm/JIT.h" - -#include "Assembly.h" -#include "CLIAccess.h" -#include "CLIJit.h" -#include "NativeUtil.h" -#include "MSCorlib.h" -#include "N3.h" -#include "Reader.h" -#include "VMArray.h" -#include "VMClass.h" -#include "VMObject.h" -#include "VMThread.h" - -using namespace n3; - -extern "C" void System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray( - VMArray* array, VMField* field) { - if (!array || !field) return; - - VMClass* type = field->classDef; - VMClassArray* ts = (VMClassArray*)array->classOf; - VMCommonClass* bs = ts->baseClass; - Assembly* ass = type->assembly; - - uint32 rva = ass->getRVAFromField(field->token); - Section* inSection = 0; - - if (rva >= ass->rsrcSection->virtualAddress && rva < ass->rsrcSection->virtualAddress + ass->rsrcSection->virtualSize) - inSection = ass->rsrcSection; - if (rva >= ass->textSection->virtualAddress && rva < ass->textSection->virtualAddress + ass->textSection->virtualSize) - inSection = ass->textSection; - if (rva >= ass->relocSection->virtualAddress && rva < ass->relocSection->virtualAddress + ass->relocSection->virtualSize) - inSection = ass->relocSection; - - uint32 size = array->size; - uint32 offset = inSection->rawAddress + (rva - inSection->virtualAddress); - ArrayUInt8* bytes = ass->bytes; - - if (bs == MSCorlib::pChar) { - for (uint32 i = 0; i < size; ++i) { - ((ArrayUInt16*)array)->elements[i] = READ_U2(bytes, offset); - } - } else if (bs == MSCorlib::pSInt32) { - for (uint32 i = 0; i < size; ++i) { - ((ArraySInt32*)array)->elements[i] = READ_U4(bytes, offset); - } - } else if (bs == MSCorlib::pDouble) { - for (uint32 i = 0; i < size; ++i) { - ((ArrayDouble*)array)->elements[i] = READ_U8(bytes, offset); - } - } else { - VMThread::get()->vm->error("implement me"); - } -} - -extern "C" VMObject* System_Type_GetTypeFromHandle(VMCommonClass* cl) { - return cl->getClassDelegatee(); -} - - -extern "C" VMObject* System_Reflection_Assembly_GetCallingAssembly() { - // Call to this function. - void** cur = (void**)__builtin_frame_address(0); - - // Stub from CLI to native. - cur = (void**)cur[0]; - - // The CLI function. - cur = (void**)cur[0]; - - // The caller of the CLI function; - cur = (void**)cur[0]; - - VirtualMachine* vm = VMThread::get()->vm; - - VMMethod* meth = vm->IPToMethod(FRAME_IP(cur)); - - assert(meth && "Wrong stack"); - - return meth->classDef->assembly->getAssemblyDelegatee(); -} - -extern "C" VMObject* System_Reflection_Assembly_GetExecutingAssembly() { - // Call to this function. - void** cur = (void**)__builtin_frame_address(0); - - // Stub from CLI to native. - cur = (void**)cur[0]; - - // The CLI function. - cur = (void**)cur[0]; - - VirtualMachine* vm = VMThread::get()->vm; - - VMMethod* meth = vm->IPToMethod(FRAME_IP(cur)); - - assert(meth && "Wrong stack"); - - return meth->classDef->assembly->getAssemblyDelegatee(); -} - -extern "C" void System_Reflection_Assembly_LoadFromFile() { - VMThread::get()->vm->error("implement me"); -} - -extern "C" void System_Array_InternalCopy(VMArray* src, sint32 sstart, - VMArray* dst, sint32 dstart, - sint32 len) { - N3* vm = (N3*)(VMThread::get()->vm); - verifyNull(src); - verifyNull(dst); - - if (!(src->classOf->isArray && dst->classOf->isArray)) { - vm->arrayStoreException(); - } - - VMClassArray* ts = (VMClassArray*)src->classOf; - VMClassArray* td = (VMClassArray*)dst->classOf; - VMCommonClass* dstType = td->baseClass; - VMCommonClass* srcType = ts->baseClass; - - if (len > src->size) { - vm->indexOutOfBounds(src, len); - } else if (len > dst->size) { - vm->indexOutOfBounds(dst, len); - } else if (len + sstart > src->size) { - vm->indexOutOfBounds(src, len + sstart); - } else if (len + dstart > dst->size) { - vm->indexOutOfBounds(dst, len + dstart); - } else if (dstart < 0) { - vm->indexOutOfBounds(dst, dstart); - } else if (sstart < 0) { - vm->indexOutOfBounds(src, sstart); - } else if (len < 0) { - vm->indexOutOfBounds(src, len); - } - - bool doThrow = false; - - if (srcType->super == MSCorlib::pValue && srcType != dstType) { - vm->arrayStoreException(); - } else if (srcType->super != MSCorlib::pValue && srcType->super != MSCorlib::pEnum) { - sint32 i = sstart; - while (i < sstart + len && !doThrow) { - VMObject* cur = ((ArrayObject*)src)->at(i); - if (cur) { - if (!(cur->classOf->isAssignableFrom(dstType))) { - doThrow = true; - len = i; - } - } - ++i; - } - } - - - uint32 size = srcType->naturalType->getPrimitiveSizeInBits() / 8; - if (size == 0) size = sizeof(void*); - void* ptrDst = (void*)((int64_t)(dst->elements) + size * dstart); - void* ptrSrc = (void*)((int64_t)(src->elements) + size * sstart); - memmove(ptrDst, ptrSrc, size * len); - - if (doThrow) - vm->arrayStoreException(); - -} - -extern "C" sint32 System_Array_GetRank(VMObject* arr) { - verifyNull(arr); - if (arr->classOf->isArray) { - return ((VMClassArray*)(arr->classOf))->dims; - } else { - VMThread::get()->vm->error("implement me"); - return 0; - } -} - -extern "C" sint32 System_Array_GetLength(VMObject* arr) { - verifyNull(arr); - if (arr->classOf->isArray) { - return ((VMArray*)arr)->size; - } else { - VMThread::get()->vm->error("implement me"); - return 0; - } -} - -extern "C" sint32 System_Array_GetLowerBound(VMObject* arr, sint32 dim) { - return 0; -} - -extern "C" VMObject* System_Object_GetType(VMObject* obj) { - verifyNull(obj); - return obj->classOf->getClassDelegatee(); -} - -extern "C" double System_Decimal_ToDouble(void* ptr) { - VMThread::get()->vm->error("implement me"); - return 0.0; -} - -extern "C" double System_Math_Log10(double val) { - return log10(val); -} - -extern "C" double System_Math_Floor(double val) { - return floor(val); -} - -extern "C" void System_GC_Collect() { -#ifdef MULTIPLE_GC - VMThread::get()->GC->collect(); -#else - mvm::Collector::collect(); -#endif -} - -extern "C" void System_GC_SuppressFinalize(VMObject* obj) { - // TODO: implement me -} - Modified: vmkit/trunk/lib/N3/VMCore/N3.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/N3.cpp?rev=74824&r1=74823&r2=74824&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/N3.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/N3.cpp Mon Jul 6 08:27:41 2009 @@ -18,6 +18,7 @@ #include "Assembly.h" #include "CLIJit.h" #include "CLIString.h" +#include "LinkN3Runtime.h" #include "LockedMap.h" #include "MSCorlib.h" #include "N3.h" @@ -254,3 +255,5 @@ vm->threadSystem->nonDaemonVar->signal(); vm->threadSystem->nonDaemonLock->unlock(); } + +#include "MSCorlib.inc" From nicolas.geoffray at lip6.fr Mon Jul 6 07:47:35 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 06 Jul 2009 14:47:35 -0000 Subject: [vmkit-commits] [vmkit] r74826 - /vmkit/trunk/lib/N3/VMCore/LinkN3Runtime.h Message-ID: <200907061447.n66Elb7g024130@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 6 09:47:30 2009 New Revision: 74826 URL: http://llvm.org/viewvc/llvm-project?rev=74826&view=rev Log: Forgot that file from previous commit. Added: vmkit/trunk/lib/N3/VMCore/LinkN3Runtime.h Added: vmkit/trunk/lib/N3/VMCore/LinkN3Runtime.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/LinkN3Runtime.h?rev=74826&view=auto ============================================================================== --- vmkit/trunk/lib/N3/VMCore/LinkN3Runtime.h (added) +++ vmkit/trunk/lib/N3/VMCore/LinkN3Runtime.h Mon Jul 6 09:47:30 2009 @@ -0,0 +1,73 @@ +//===----------------------- LinkN3Runtime.h ------------------------------===// +//=== ------------- Reference all runtime functions -----------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef JNJVM_LINK_N3_RUNTIME_H +#define JNJVM_LINK_N3_RUNTIME_H + + +namespace n3 { + class CacheNode; + class UTF8; + class VMClass; + class VMClassArray; + class VMCommonClass; + class VMObject; +} + +using namespace n3; + + +extern "C" VMObject* initialiseClass(VMClass* cl); +extern "C" void n3ClassCastException(); +extern "C" void n3NullPointerException(); +extern "C" void indexOutOfBounds(); +extern "C" VMObject* newString(const UTF8* utf8); +extern "C" bool n3InstanceOf(VMObject* obj, VMCommonClass* cl); +extern "C" void* GetCppException(); +extern "C" void ThrowException(VMObject* obj); +extern "C" VMObject* GetCLIException(); +extern "C" bool CompareException(VMClass* cl); +extern "C" void ClearException(); +extern "C" VMObject* doMultiNew(VMClassArray* cl, ...); +extern "C" CacheNode* n3VirtualLookup(CacheNode* cache, VMObject *obj); +extern "C" VMObject* newObject(VMClass* cl); +extern "C" VMObject* newArray(VMClassArray* cl, sint32 nb); + +namespace { + struct ForceRuntimeLinking { + ForceRuntimeLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + (void) initialiseClass(0); + (void) n3ClassCastException(); + (void )n3NullPointerException(); + (void) indexOutOfBounds(); + (void) newString(0); + (void) n3InstanceOf(0, 0); + (void) GetCppException(); + (void) ThrowException(0); + (void) GetCLIException(); + (void) CompareException(0); + (void) ClearException(); + (void) doMultiNew(0); + (void) n3VirtualLookup(0, 0); + (void) newObject(0); + (void) newArray(0, 0); + } + } ForcePassLinking; // Force link by creating a global definition. +} + + + +#endif //JNJVM_LINK_N3_RUNTIME_H From sanxiyn at gmail.com Mon Jul 6 07:50:10 2009 From: sanxiyn at gmail.com (Seo Sanghyeon) Date: Mon, 06 Jul 2009 14:50:10 -0000 Subject: [vmkit-commits] [vmkit] r74827 - /vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Message-ID: <200907061450.n66EoAWa024244@zion.cs.uiuc.edu> Author: sanxiyn Date: Mon Jul 6 09:50:08 2009 New Revision: 74827 URL: http://llvm.org/viewvc/llvm-project?rev=74827&view=rev Log: Build fix Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc?rev=74827&r1=74826&r2=74827&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Mon Jul 6 09:50:08 2009 @@ -23,6 +23,7 @@ #include #include +#include using namespace jnjvm; From nicolas.geoffray at lip6.fr Mon Jul 6 08:31:17 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 06 Jul 2009 15:31:17 -0000 Subject: [vmkit-commits] [vmkit] r74828 - /vmkit/trunk/tools/llcj/llcj.cpp Message-ID: <200907061531.n66FVJ2r025859@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 6 10:31:04 2009 New Revision: 74828 URL: http://llvm.org/viewvc/llvm-project?rev=74828&view=rev Log: Fix exe generation. Modified: vmkit/trunk/tools/llcj/llcj.cpp Modified: vmkit/trunk/tools/llcj/llcj.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/llcj/llcj.cpp?rev=74828&r1=74827&r2=74828&view=diff ============================================================================== --- vmkit/trunk/tools/llcj/llcj.cpp (original) +++ vmkit/trunk/tools/llcj/llcj.cpp Mon Jul 6 10:31:04 2009 @@ -220,9 +220,15 @@ gccArgv[gccArgc++] = "-ldl"; gccArgv[gccArgc++] = "-lz"; gccArgv[gccArgc++] = "-lJnJVM"; + gccArgv[gccArgc++] = "-lClasspath"; if (withJIT) { gccArgv[gccArgc++] = "-lJnJVMCompiler"; } + gccArgv[gccArgc++] = "-lAllocator"; + gccArgv[gccArgc++] = "-lCommonThread"; + gccArgv[gccArgc++] = "-lMvm"; + gccArgv[gccArgc++] = "-lMvmCompiler"; + gccArgv[gccArgc++] = "-lGCMmap2"; gccArgv[gccArgc++] = "-lvmjc"; gccArgv[gccArgc++] = "-lLLVMSupport"; #if !defined(__MACH__) From nicolas.geoffray at lip6.fr Tue Jul 7 03:45:02 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 07 Jul 2009 10:45:02 -0000 Subject: [vmkit-commits] [vmkit] r74899 - /vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Message-ID: <200907071045.n67Aj4AV008131@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 7 05:44:55 2009 New Revision: 74899 URL: http://llvm.org/viewvc/llvm-project?rev=74899&view=rev Log: Fix wording. Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=74899&r1=74898&r2=74899&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Tue Jul 7 05:44:55 2009 @@ -563,7 +563,7 @@ } void Jnjvm::classFormatError(UserClass* cl, const UTF8* name) { - uint32 size = 33 + name->size + cl->name->size; + uint32 size = 35 + name->size + cl->name->size; ArrayUInt16* msg = (ArrayUInt16*)upcalls->ArrayOfChar->doNew(size, this); uint32 i = 0; @@ -586,12 +586,14 @@ else msg->elements[i++] = cl->name->elements[j]; } + msg->elements[i++] = ' '; msg->elements[i++] = 'a'; msg->elements[i++] = 'n'; msg->elements[i++] = 'd'; msg->elements[i++] = ' '; msg->elements[i++] = 'f'; msg->elements[i++] = 'o'; + msg->elements[i++] = 'u'; msg->elements[i++] = 'n'; msg->elements[i++] = 'd'; msg->elements[i++] = ' '; From nicolas.geoffray at lip6.fr Tue Jul 7 07:09:50 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 07 Jul 2009 14:09:50 -0000 Subject: [vmkit-commits] [vmkit] r74900 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907071409.n67E9ppH014680@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 7 09:09:41 2009 New Revision: 74900 URL: http://llvm.org/viewvc/llvm-project?rev=74900&view=rev Log: Add newlines. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=74900&r1=74899&r2=74900&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Tue Jul 7 09:09:41 2009 @@ -1549,7 +1549,7 @@ ArrayUInt8* bytes = Reader::openFile(bootstrapLoader, name); if (!bytes) { - fprintf(stderr, "Can't find zip file."); + fprintf(stderr, "Can't find zip file.\n"); goto end; } ZipArchive archive(bytes, bootstrapLoader->allocator); @@ -1566,7 +1566,7 @@ (ArrayUInt8*)array->doNew(file->ucsize, bootstrapLoader->allocator); int ok = archive.readFile(res, file); if (!ok) { - fprintf(stderr, "Wrong zip file."); + fprintf(stderr, "Wrong zip file.\n"); goto end; } From nicolas.geoffray at lip6.fr Tue Jul 7 08:20:40 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 07 Jul 2009 15:20:40 -0000 Subject: [vmkit-commits] [vmkit] r74902 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907071520.n67FKfrv017221@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 7 10:20:27 2009 New Revision: 74902 URL: http://llvm.org/viewvc/llvm-project?rev=74902&view=rev Log: Output better message error diagnostics. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=74902&r1=74901&r2=74902&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Tue Jul 7 10:20:27 2009 @@ -1495,8 +1495,17 @@ Function* JavaAOTCompiler::addCallback(Class* cl, uint16 index, Signdef* sign, bool stat) { - fprintf(stderr, "Warning: emitting a callback from %s (%d)\n", - UTF8Buffer(cl->name).cString(), index); + JavaConstantPool* ctpInfo = cl->ctpInfo; + Signdef* signature = 0; + const UTF8* name = 0; + const UTF8* methCl = 0; + ctpInfo->nameOfStaticOrSpecialMethod(index, methCl, name, signature); + + + fprintf(stderr, "Warning: emitting a callback from %s (%s.%s)\n", + UTF8Buffer(cl->name).cString(), UTF8Buffer(methCl).cString(), + UTF8Buffer(name).cString()); + Function* func = 0; LLVMSignatureInfo* LSI = getSignatureInfo(sign); From nicolas.geoffray at lip6.fr Tue Jul 7 10:19:20 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 07 Jul 2009 17:19:20 -0000 Subject: [vmkit-commits] [vmkit] r74921 - in /vmkit/trunk/lib/JnJVM: Compiler/JITInfo.cpp Compiler/JavaJIT.cpp VMCore/JavaClass.cpp VMCore/JnjvmClassLoader.cpp Message-ID: <200907071719.n67HJPc9021934@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 7 12:19:13 2009 New Revision: 74921 URL: http://llvm.org/viewvc/llvm-project?rev=74921&view=rev Log: Change '$' to its unicode value when translating a Java method name to a JNI name. Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=74921&r1=74920&r2=74921&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Tue Jul 7 12:19:13 2009 @@ -134,7 +134,7 @@ sint32 mtlen = jniConsType->size; char* buf = (char*)alloca(3 + JNI_NAME_PRE_LEN + 1 + - ((mnlen + clen + mtlen) << 1)); + ((mnlen + clen + mtlen) << 3)); bool jnjvm = false; if (isNative(methodDef->access)) { Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=74921&r1=74920&r2=74921&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 7 12:19:13 2009 @@ -245,7 +245,7 @@ sint32 mtlen = jniConsType->size; char* functionName = (char*)alloca(3 + JNI_NAME_PRE_LEN + - ((mnlen + clen + mtlen) << 1)); + ((mnlen + clen + mtlen) << 3)); if (!natPtr) natPtr = compilingClass->classLoader->nativeLookup(compilingMethod, jnjvm, @@ -269,7 +269,7 @@ Function* func = llvmFunction; - if (jnjvm) { + if (jnjvm) { compilingMethod->setCompiledPtr((void*)natPtr, functionName); return llvmFunction; } Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=74921&r1=74920&r2=74921&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Tue Jul 7 12:19:13 2009 @@ -1079,14 +1079,25 @@ for (sint32 i =0; i < clen; ++i) { cur = jniConsClName->elements[i]; - if (cur == '/') ptr[0] = '_'; - else if (cur == '_') { + if (cur == '/') { + ptr[0] = '_'; + ++ptr; + } else if (cur == '_') { ptr[0] = '_'; ptr[1] = '1'; + ptr += 2; + } else if (cur == '$') { + ptr[0] = '_'; + ptr[1] = '0'; + ptr[2] = '0'; + ptr[3] = '0'; + ptr[4] = '2'; + ptr[5] = '4'; + ptr += 6; + } else { + ptr[0] = (uint8)cur; ++ptr; } - else ptr[0] = (uint8)cur; - ++ptr; } ptr[0] = '_'; @@ -1118,6 +1129,14 @@ ptr[0] = '_'; ptr[1] = '1'; ptr += 2; + } else if (c == '$') { + ptr[0] = '_'; + ptr[1] = '0'; + ptr[2] = '0'; + ptr[3] = '0'; + ptr[4] = '2'; + ptr[5] = '4'; + ptr += 6; } else if (c == I_END_REF) { ptr[0] = '_'; ptr[1] = '2'; Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=74921&r1=74920&r2=74921&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Tue Jul 7 12:19:13 2009 @@ -1146,7 +1146,7 @@ sint32 mtlen = jniConsType->size; char* buf = (char*)alloca(3 + JNI_NAME_PRE_LEN + 1 + - ((mnlen + clen + mtlen) << 1)); + ((mnlen + clen + mtlen) << 3)); intptr_t res = meth->classDef->classLoader->nativeLookup(meth, jnjvm, buf); assert(res && "Could not find required native method"); return res; From nicolas.geoffray at lip6.fr Wed Jul 8 01:17:54 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 08:17:54 -0000 Subject: [vmkit-commits] [vmkit] r74994 - /vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Message-ID: <200907080817.n688Hs7H031922@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 03:17:54 2009 New Revision: 74994 URL: http://llvm.org/viewvc/llvm-project?rev=74994&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=74994&r1=74993&r2=74994&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Wed Jul 8 03:17:54 2009 @@ -840,7 +840,7 @@ case FADD : { Value* val2 = pop(); Value* val1 = pop(); - push(BinaryOperator::CreateAdd(val1, val2, "", currentBlock), + push(BinaryOperator::CreateFAdd(val1, val2, "", currentBlock), false); break; } @@ -850,7 +850,7 @@ llvm::Value* val2 = pop(); pop(); llvm::Value* val1 = pop(); - push(BinaryOperator::CreateAdd(val1, val2, "", currentBlock), + push(BinaryOperator::CreateFAdd(val1, val2, "", currentBlock), false); push(module->constantZero, false); break; @@ -877,7 +877,7 @@ case FSUB : { Value* val2 = pop(); Value* val1 = pop(); - push(BinaryOperator::CreateSub(val1, val2, "", currentBlock), + push(BinaryOperator::CreateFSub(val1, val2, "", currentBlock), false); break; } @@ -887,7 +887,7 @@ llvm::Value* val2 = pop(); pop(); llvm::Value* val1 = pop(); - push(BinaryOperator::CreateSub(val1, val2, "", currentBlock), + push(BinaryOperator::CreateFSub(val1, val2, "", currentBlock), false); push(module->constantZero, false); break; @@ -915,7 +915,7 @@ case FMUL : { Value* val2 = pop(); Value* val1 = pop(); - push(BinaryOperator::CreateMul(val1, val2, "", currentBlock), + push(BinaryOperator::CreateFMul(val1, val2, "", currentBlock), false); break; } @@ -925,7 +925,7 @@ llvm::Value* val2 = pop(); pop(); llvm::Value* val1 = pop(); - push(BinaryOperator::CreateMul(val1, val2, "", currentBlock), + push(BinaryOperator::CreateFMul(val1, val2, "", currentBlock), false); push(module->constantZero, false); break; From nicolas.geoffray at lip6.fr Wed Jul 8 02:06:17 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 09:06:17 -0000 Subject: [vmkit-commits] [vmkit] r74996 - /vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Message-ID: <200907080906.n6896Hom001088@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 04:06:17 2009 New Revision: 74996 URL: http://llvm.org/viewvc/llvm-project?rev=74996&view=rev Log: Remove wrong character. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=74996&r1=74995&r2=74996&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Wed Jul 8 04:06:17 2009 @@ -269,7 +269,7 @@ Function* func = llvmFunction; - if (jnjvm) { + if (jnjvm) { compilingMethod->setCompiledPtr((void*)natPtr, functionName); return llvmFunction; } From nicolas.geoffray at lip6.fr Wed Jul 8 03:08:21 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 10:08:21 -0000 Subject: [vmkit-commits] [vmkit] r74998 - /vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Message-ID: <200907081008.n68A8MgF003440@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 05:08:06 2009 New Revision: 74998 URL: http://llvm.org/viewvc/llvm-project?rev=74998&view=rev Log: Fix naming of LLVM types. Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=74998&r1=74997&r2=74998&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Wed Jul 8 05:08:06 2009 @@ -219,23 +219,26 @@ copyDefinitions(module, globalModule); } - module->addTypeName("JavaObject", JavaObjectType); - module->addTypeName("JavaArray", JavaArrayType); - module->addTypeName("JavaCommonClass", JavaCommonClassType); - module->addTypeName("JavaClass", JavaClassType); - module->addTypeName("JavaClassPrimitive", JavaClassPrimitiveType); - module->addTypeName("JavaClassArray", JavaClassArrayType); - module->addTypeName("ArrayUInt8", JavaArrayUInt8Type); - module->addTypeName("ArraySInt8", JavaArraySInt8Type); - module->addTypeName("ArrayUInt16", JavaArrayUInt16Type); - module->addTypeName("ArraySInt16", JavaArraySInt16Type); - module->addTypeName("ArraySInt32", JavaArraySInt32Type); - module->addTypeName("ArrayLong", JavaArrayLongType); - module->addTypeName("ArrayFloat", JavaArrayFloatType); - module->addTypeName("ArrayDouble", JavaArrayDoubleType); - module->addTypeName("ArrayObject", JavaArrayObjectType); - module->addTypeName("CacheNode", CacheNodeType); - module->addTypeName("Enveloppe", EnveloppeType); + module->addTypeName("JavaObject", JavaObjectType->getContainedType(0)); + module->addTypeName("JavaArray", JavaArrayType->getContainedType(0)); + module->addTypeName("JavaCommonClass", + JavaCommonClassType->getContainedType(0)); + module->addTypeName("JavaClass", JavaClassType->getContainedType(0)); + module->addTypeName("JavaClassPrimitive", + JavaClassPrimitiveType->getContainedType(0)); + module->addTypeName("JavaClassArray", + JavaClassArrayType->getContainedType(0)); + module->addTypeName("ArrayUInt8", JavaArrayUInt8Type->getContainedType(0)); + module->addTypeName("ArraySInt8", JavaArraySInt8Type->getContainedType(0)); + module->addTypeName("ArrayUInt16", JavaArrayUInt16Type->getContainedType(0)); + module->addTypeName("ArraySInt16", JavaArraySInt16Type->getContainedType(0)); + module->addTypeName("ArraySInt32", JavaArraySInt32Type->getContainedType(0)); + module->addTypeName("ArrayLong", JavaArrayLongType->getContainedType(0)); + module->addTypeName("ArrayFloat", JavaArrayFloatType->getContainedType(0)); + module->addTypeName("ArrayDouble", JavaArrayDoubleType->getContainedType(0)); + module->addTypeName("ArrayObject", JavaArrayObjectType->getContainedType(0)); + module->addTypeName("CacheNode", CacheNodeType->getContainedType(0)); + module->addTypeName("Enveloppe", EnveloppeType->getContainedType(0)); InterfaceLookupFunction = module->getFunction("jnjvmInterfaceLookup"); MultiCallNewFunction = module->getFunction("jnjvmMultiCallNew"); From nicolas.geoffray at lip6.fr Wed Jul 8 05:18:21 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 12:18:21 -0000 Subject: [vmkit-commits] [vmkit] r75002 - /vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Message-ID: <200907081218.n68CIWfl007392@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 07:17:44 2009 New Revision: 75002 URL: http://llvm.org/viewvc/llvm-project?rev=75002&view=rev Log: Create finalizer and reference threads during bootstrap. Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=75002&r1=75001&r2=75002&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Wed Jul 8 07:17:44 2009 @@ -953,6 +953,13 @@ void Jnjvm::loadBootstrap() { JnjvmClassLoader* loader = bootstrapLoader; + // First create system threads. + finalizerThread = new JavaThread(0, 0, this); + finalizerThread->start((void (*)(mvm::Thread*))finalizerStart); + + enqueueThread = new JavaThread(0, 0, this); + enqueueThread->start((void (*)(mvm::Thread*))enqueueStart); + // Initialise the bootstrap class loader if it's not // done already. if (!bootstrapLoader->upcalls->newString) @@ -1210,13 +1217,7 @@ mvm::Thread* th = new JavaThread(0, 0, this); th->start(serviceCPUMonitor); #endif - - finalizerThread = new JavaThread(0, 0, this); - finalizerThread->start((void (*)(mvm::Thread*))finalizerStart); - - enqueueThread = new JavaThread(0, 0, this); - enqueueThread->start((void (*)(mvm::Thread*))enqueueStart); - + mainThread = new JavaThread(0, 0, this); mainThread->start((void (*)(mvm::Thread*))mainJavaStart); } else { From nicolas.geoffray at lip6.fr Wed Jul 8 07:14:04 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 14:14:04 -0000 Subject: [vmkit-commits] [vmkit] r75004 - /vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Message-ID: <200907081414.n68EEG4N011717@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 09:13:04 2009 New Revision: 75004 URL: http://llvm.org/viewvc/llvm-project?rev=75004&view=rev Log: Make sure there is a classname before attempting to dlopen it. Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=75004&r1=75003&r2=75004&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Wed Jul 8 09:13:04 2009 @@ -945,7 +945,8 @@ if (argumentsInfo.jarFile) appClassLoader->loadLibFromJar(this, argumentsInfo.jarFile, argumentsInfo.className); - else appClassLoader->loadLibFromFile(this, argumentsInfo.className); + else if (argumentsInfo.className) + appClassLoader->loadLibFromFile(this, argumentsInfo.className); } return appClassLoader; } From nicolas.geoffray at lip6.fr Wed Jul 8 07:15:31 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 14:15:31 -0000 Subject: [vmkit-commits] [vmkit] r75005 - /vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h Message-ID: <200907081415.n68EFWEj011762@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 09:15:29 2009 New Revision: 75005 URL: http://llvm.org/viewvc/llvm-project?rev=75005&view=rev Log: Public'ize loadBootstrap. Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h?rev=75005&r1=75004&r2=75005&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h Wed Jul 8 09:15:29 2009 @@ -146,12 +146,6 @@ /// JnjvmClassLoader* loadAppClassLoader(); - /// loadBootstrap - Bootstraps the JVM, getting the class loader, initializing - /// bootstrap classes (e.g. java/lang/Class, java/lang/*Exception) and - /// mapping the initial thread. - /// - void loadBootstrap(); - /// executeClass - Executes in the given JVM this main class with the given /// Java args. /// @@ -359,6 +353,12 @@ /// class loader from the function map. /// void removeMethodsInFunctionMap(JnjvmClassLoader* loader); + + /// loadBootstrap - Bootstraps the JVM, getting the class loader, initializing + /// bootstrap classes (e.g. java/lang/Class, java/lang/*Exception) and + /// mapping the initial thread. + /// + void loadBootstrap(); #ifdef ISOLATE static Jnjvm* RunningIsolates[NR_ISOLATES]; From nicolas.geoffray at lip6.fr Wed Jul 8 07:17:31 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 14:17:31 -0000 Subject: [vmkit-commits] [vmkit] r75006 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h include/mvm/Allocator.h lib/JnJVM/VMCore/JavaClass.h lib/JnJVM/VMCore/JnjvmClassLoader.cpp lib/JnJVM/VMCore/JnjvmClassLoader.h Message-ID: <200907081417.n68EHtZI011848@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 09:17:23 2009 New Revision: 75006 URL: http://llvm.org/viewvc/llvm-project?rev=75006&view=rev Log: Clear the contents of JITInfos when changing compilers. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/include/mvm/Allocator.h vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=75006&r1=75005&r2=75006&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Wed Jul 8 09:17:23 2009 @@ -93,6 +93,12 @@ virtualSizeConstant(0), virtualType(0), staticType(0) {} + + virtual void clear() { + virtualType = 0; + staticType = 0; + virtualSizeConstant = 0; + } }; class LLVMMethodInfo : public mvm::JITInfo, private llvm::Annotation { @@ -111,6 +117,12 @@ LLVMMethodInfo(JavaMethod* M); static JavaMethod* get(const llvm::Function* F); + + virtual void clear() { + methodFunction = 0; + offsetConstant = 0; + functionType = 0; + } }; class LLVMFieldInfo : public mvm::JITInfo { @@ -125,6 +137,10 @@ LLVMFieldInfo(JavaField* F) : fieldDef(F), offsetConstant(0) {} + + virtual void clear() { + offsetConstant = 0; + } }; class LLVMSignatureInfo : public mvm::JITInfo { @@ -634,7 +650,7 @@ bool generateStubs; bool assumeCompiled; - + bool runClinit; bool compileRT; Modified: vmkit/trunk/include/mvm/Allocator.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Allocator.h?rev=75006&r1=75005&r2=75006&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Allocator.h (original) +++ vmkit/trunk/include/mvm/Allocator.h Wed Jul 8 09:17:23 2009 @@ -80,6 +80,7 @@ /// ::getInfo and destroyed when the object is destroyed. struct JITInfo : public mvm::PermanentObject { virtual ~JITInfo() {} + virtual void clear() {} }; } // end namespace mvm Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h?rev=75006&r1=75005&r2=75006&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h Wed Jul 8 09:17:23 2009 @@ -692,6 +692,10 @@ return static_cast(JInfo); } + void clearInfo() { + if (JInfo) JInfo->clear(); + } + /// resolveClass - If the class has not been resolved yet, resolve it. /// void resolveClass(); @@ -1170,6 +1174,10 @@ return static_cast(JInfo); } + void clearInfo() { + if (JInfo) JInfo->clear(); + } + #define JNI_NAME_PRE "Java_" #define JNI_NAME_PRE_LEN 5 @@ -1292,6 +1300,10 @@ "Invalid concrete type or multiple inheritence for getInfo"); return static_cast(JInfo); } + + void clearInfo() { + if (JInfo) JInfo->clear(); + } bool isReference() { Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=75006&r1=75005&r2=75006&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Wed Jul 8 09:17:23 2009 @@ -294,6 +294,37 @@ } +void JnjvmClassLoader::setCompiler(JavaCompiler* Comp) { + + // Set the new compiler. + TheCompiler = Comp; + + // Clean up JITInfo of all classes. + for (ClassMap::iterator i = classes->map.begin(), e = classes->map.end(); + i!= e; ++i) { + CommonClass* ccl = i->second; + if (ccl->isClass()) { + Class* cl = ccl->asClass(); + cl->clearInfo(); + + for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) { + cl->virtualMethods[i].clearInfo(); + } + + for (uint32 i = 0; i < cl->nbStaticMethods; ++i) { + cl->staticMethods[i].clearInfo(); + } + + for (uint32 i = 0; i < cl->nbVirtualFields; ++i) { + cl->virtualFields[i].clearInfo(); + } + for (uint32 i = 0; i < cl->nbStaticFields; ++i) { + cl->staticFields[i].clearInfo(); + } + } + } +} + ArrayUInt8* JnjvmBootstrapLoader::openName(const UTF8* utf8) { char* asciiz = (char*)alloca(utf8->size + 1); for (sint32 i = 0; i < utf8->size; ++i) Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h?rev=75006&r1=75005&r2=75006&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h Wed Jul 8 09:17:23 2009 @@ -127,7 +127,7 @@ /// setCompiler - Set the compiler of classes loaded by this class loader. /// - void setCompiler(JavaCompiler* Comp) { TheCompiler = Comp; } + void setCompiler(JavaCompiler* Comp); /// tracer - Traces a JnjvmClassLoader for GC. /// From nicolas.geoffray at lip6.fr Wed Jul 8 08:34:06 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 15:34:06 -0000 Subject: [vmkit-commits] [vmkit] r75009 - in /vmkit/trunk: include/jnjvm/JavaCompiler.h include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JITInfo.cpp lib/JnJVM/Compiler/JavaAOTCompiler.cpp lib/JnJVM/Compiler/JavaJITCompiler.cpp lib/JnJVM/VMCore/JavaClass.cpp tools/vmjc/vmjc.cpp Message-ID: <200907081534.n68FY9Rv014290@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 10:33:07 2009 New Revision: 75009 URL: http://llvm.org/viewvc/llvm-project?rev=75009&view=rev Log: Preliminary support for clinit'ing before AOT. Modified: vmkit/trunk/include/jnjvm/JavaCompiler.h vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/include/jnjvm/JavaCompiler.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JavaCompiler.h?rev=75009&r1=75008&r2=75009&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JavaCompiler.h (original) +++ vmkit/trunk/include/jnjvm/JavaCompiler.h Wed Jul 8 10:33:07 2009 @@ -37,15 +37,6 @@ virtual void setMethod(JavaMethod* meth, void* ptr, const char* name) { } - virtual void setTracer(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) { - } - - virtual void setDestructor(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) { - } - - virtual bool isStaticCompiling() { return false; } Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=75009&r1=75008&r2=75009&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Wed Jul 8 10:33:07 2009 @@ -428,10 +428,6 @@ virtual llvm::Constant* getNativeFunction(JavaMethod* meth, void* natPtr) = 0; virtual void setMethod(JavaMethod* meth, void* ptr, const char* name) = 0; - virtual void setTracer(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) = 0; - virtual void setDestructor(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) = 0; #ifdef SERVICE virtual llvm::Value* getIsolate(Jnjvm* vm, llvm::Value* Where) = 0; @@ -496,10 +492,6 @@ virtual llvm::Constant* getNativeFunction(JavaMethod* meth, void* natPtr); virtual void setMethod(JavaMethod* meth, void* ptr, const char* name); - virtual void setTracer(JavaVirtualTable* VT, uintptr_t ptr, - const char* name); - virtual void setDestructor(JavaVirtualTable* VT, uintptr_t ptr, - const char* name); #ifdef SERVICE @@ -550,10 +542,6 @@ virtual llvm::Constant* getNativeFunction(JavaMethod* meth, void* natPtr); virtual void setMethod(JavaMethod* meth, void* ptr, const char* name); - virtual void setTracer(JavaVirtualTable* VT, uintptr_t ptr, - const char* name); - virtual void setDestructor(JavaVirtualTable* VT, uintptr_t ptr, - const char* name); #ifdef SERVICE Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=75009&r1=75008&r2=75009&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Wed Jul 8 10:33:07 2009 @@ -40,10 +40,15 @@ if (!virtualType) { std::vector fields; - if (classDef->super && classDef->super->super) { - LLVMClassInfo* CLI = - JavaLLVMCompiler::getClassInfo((Class*)classDef->super); - fields.push_back(CLI->getVirtualType()->getContainedType(0)); + if (classDef->super) { + LLVMClassInfo* CLI = JavaLLVMCompiler::getClassInfo(classDef->super); + const llvm::Type* Ty = CLI->getVirtualType()->getContainedType(0); + + if (classDef->super->super) { + fields.push_back(Ty); + } else { + fields.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); + } } else { fields.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75009&r1=75008&r2=75009&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Wed Jul 8 10:33:07 2009 @@ -381,7 +381,7 @@ Constant* JavaAOTCompiler::CreateConstantFromJavaClass(CommonClass* cl) { Class* javaClass = cl->classLoader->bootstrapLoader->upcalls->newClass; - LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(javaClass); + LLVMClassInfo* LCI = getClassInfo(javaClass); const StructType* STy = dyn_cast(LCI->getVirtualType()->getContainedType(0)); @@ -1131,19 +1131,12 @@ // Destructor Function* Finalizer = 0; - if (RealVT->operatorDelete) { - char* name = (char*)(RealVT->destructor); - std::vector Args; - const FunctionType* Ty = FunctionType::get(Type::VoidTy, Args, false); - Finalizer = Function::Create(Ty, GlobalValue::ExternalLinkage, name, - getLLVMModule()); - } else { - JavaMethod* meth = (JavaMethod*)(RealVT->destructor); - if (meth) { - LLVMMethodInfo* LMI = getMethodInfo(meth); - Finalizer = LMI->getMethod(); - } + JavaMethod* meth = (JavaMethod*)(RealVT->destructor); + if (meth) { + LLVMMethodInfo* LMI = getMethodInfo(meth); + Finalizer = LMI->getMethod(); } + Elemts.push_back(Finalizer ? ConstantExpr::getCast(Instruction::BitCast, Finalizer, PTy) : N); @@ -1479,19 +1472,6 @@ func->setLinkage(GlobalValue::ExternalLinkage); } -void JavaAOTCompiler::setTracer(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) { - VT->tracer = (uintptr_t)name; -} - -void JavaAOTCompiler::setDestructor(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) { - // Set the name info into the operatorDelete directly, the compiler - // will use the name to create a LLVM function. - VT->destructor = (uintptr_t)name; - VT->operatorDelete = (uintptr_t)name; -} - Function* JavaAOTCompiler::addCallback(Class* cl, uint16 index, Signdef* sign, bool stat) { @@ -1544,9 +1524,15 @@ JnjvmBootstrapLoader* bootstrapLoader = vm->bootstrapLoader; JavaAOTCompiler* M = (JavaAOTCompiler*)bootstrapLoader->getCompiler(); try { - - bootstrapLoader->analyseClasspathEnv(vm->classpath); - bootstrapLoader->upcalls->initialiseClasspath(bootstrapLoader); + + if (M->runClinit) { + JavaJITCompiler* Comp = new JavaJITCompiler("JIT"); + bootstrapLoader->setCompiler(Comp); + bootstrapLoader->analyseClasspathEnv(vm->classpath); + } else { + bootstrapLoader->analyseClasspathEnv(vm->classpath); + bootstrapLoader->upcalls->initialiseClasspath(bootstrapLoader); + } uint32 size = strlen(name); @@ -1607,6 +1593,18 @@ } } + + if (M->runClinit) { + JavaJITCompiler* Comp = new JavaJITCompiler("JIT"); + bootstrapLoader->setCompiler(Comp); + + for (std::vector::iterator i = classes.begin(), e = classes.end(); + i != e; ++i) { + Class* cl = *i; + cl->initialiseClass(vm); + } + bootstrapLoader->setCompiler(M); + } for (std::vector::iterator i = classes.begin(), e = classes.end(); i != e; ++i) { @@ -1622,9 +1620,16 @@ } else { memcpy(realName, name, size + 1); } - + const UTF8* utf8 = bootstrapLoader->asciizConstructUTF8(realName); UserClass* cl = bootstrapLoader->loadName(utf8, true, true); + + if (M->runClinit) { + vm->loadBootstrap(); + cl->initialiseClass(vm); + bootstrapLoader->setCompiler(M); + } + cl->setOwnerClass(JavaThread::get()); M->compileClass(cl); } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=75009&r1=75008&r2=75009&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Wed Jul 8 10:33:07 2009 @@ -185,17 +185,6 @@ func->setLinkage(GlobalValue::ExternalLinkage); } -void JavaJITCompiler::setTracer(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) { - VT->tracer = ptr; -} - -void JavaJITCompiler::setDestructor(JavaVirtualTable* VT, uintptr_t ptr, - const char* name) { - VT->destructor = ptr; - VT->operatorDelete = ptr; -} - void* JavaJITCompiler::materializeFunction(JavaMethod* meth) { Function* func = parseFunction(meth); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=75009&r1=75008&r2=75009&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Wed Jul 8 10:33:07 2009 @@ -334,11 +334,12 @@ } void JavaVirtualTable::setNativeTracer(uintptr_t ptr, const char* name) { - cl->classLoader->getCompiler()->setTracer(this, ptr, name); + tracer = ptr; } void JavaVirtualTable::setNativeDestructor(uintptr_t ptr, const char* name) { - cl->classLoader->getCompiler()->setDestructor(this, ptr, name); + destructor = ptr; + operatorDelete = ptr; } JavaMethod* Class::lookupInterfaceMethodDontThrow(const UTF8* name, Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=75009&r1=75008&r2=75009&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Wed Jul 8 10:33:07 2009 @@ -106,7 +106,7 @@ AssumeCompiled("assume-compiled", cl::desc("Assume external Java classes are compiled")); -static cl::opt +static cl::opt WithClinit("with-clinit", cl::desc("Clinit the given file")); static cl::opt @@ -175,8 +175,7 @@ return 0; } - JavaCompiler* Comp = 0; - if (WithClinit.empty()) { + if (!WithClinit) { Module* TheModule = new Module("bootstrap module", *(new llvm::LLVMContext())); if (!TargetTriple.empty()) @@ -203,36 +202,30 @@ mvm::MvmModule::initialise(CodeGenOpt::Default, TheModule, TheTarget); - Comp = new JavaAOTCompiler("AOT"); } else { mvm::MvmModule::initialise(); - Comp = new JavaJITCompiler("JIT"); } + JavaAOTCompiler* Comp = new JavaAOTCompiler("AOT"); + mvm::Collector::initialise(); mvm::Collector::enable(0); JnjvmClassLoader* JCL = mvm::VirtualMachine::initialiseJVM(Comp, false); addCommandLinePass(argv); - if (!WithClinit.empty()) { - // TODO - Comp = new JavaAOTCompiler("AOT"); - JCL->setCompiler(Comp); - } - - JavaAOTCompiler* MAOT = (JavaAOTCompiler*)Comp; - if (DisableExceptions) MAOT->disableExceptions(); - if (DisableStubs) MAOT->generateStubs = false; - if (AssumeCompiled) MAOT->assumeCompiled = true; - MAOT->compileFile(JCL, InputFilename.c_str()); + if (DisableExceptions) Comp->disableExceptions(); + if (DisableStubs) Comp->generateStubs = false; + if (AssumeCompiled) Comp->assumeCompiled = true; + if (WithClinit) Comp->runClinit = true; + Comp->compileFile(JCL, InputFilename.c_str()); if (!MainClass.empty()) { - MAOT->generateMain(MainClass.c_str(), WithJIT); + Comp->generateMain(MainClass.c_str(), WithJIT); } if (PrintStats) - MAOT->printStats(); + Comp->printStats(); if (DontPrint) { // Just use stdout. We won't actually print anything on it. @@ -280,7 +273,7 @@ } if (Force || !CheckBitcodeOutputToConsole(Out,true)) - WriteBitcodeToFile(MAOT->getLLVMModule(), *Out); + WriteBitcodeToFile(Comp->getLLVMModule(), *Out); if (Out != &std::cout) { ((std::ofstream*)Out)->close(); From nicolas.geoffray at lip6.fr Wed Jul 8 14:43:11 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 21:43:11 -0000 Subject: [vmkit-commits] [vmkit] r75052 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907082143.n68LhBCd028071@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 16:43:11 2009 New Revision: 75052 URL: http://llvm.org/viewvc/llvm-project?rev=75052&view=rev Log: Emission of statically initialized fields. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75052&r1=75051&r2=75052&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Wed Jul 8 16:43:11 2009 @@ -210,11 +210,21 @@ Constant* JavaAOTCompiler::getFinalObject(JavaObject* obj) { + llvm::Constant* varGV = 0; final_object_iterator End = finalObjects.end(); final_object_iterator I = finalObjects.find(obj); if (I == End) { - abort(); - return 0; + Constant* CO = CreateConstantFromJavaObject(obj); + + varGV = new GlobalVariable(CO->getType(), true, + GlobalValue::InternalLinkage, + CO, "", getLLVMModule()); + + varGV = ConstantExpr::getCast(Instruction::BitCast, varGV, + JnjvmModule::JavaObjectType); + + finalObjects.insert(std::make_pair(obj, varGV)); + return varGV; } else { return I->second; } @@ -236,7 +246,49 @@ Attribut* attribut = field.lookupAttribut(Attribut::constantAttribut); if (!attribut) { - Elts.push_back(Constant::getNullValue(Ty)); + void* obj = cl->getStaticInstance(); + if (obj) { + if (type->isPrimitive()) { + const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; + if (prim->isBool() || prim->isByte()) { + ConstantInt* CI = ConstantInt::get(Type::Int8Ty, + field.getInt8Field(obj)); + Elts.push_back(CI); + } else if (prim->isShort() || prim->isChar()) { + ConstantInt* CI = ConstantInt::get(Type::Int16Ty, + field.getInt16Field(obj)); + Elts.push_back(CI); + } else if (prim->isInt()) { + ConstantInt* CI = ConstantInt::get(Type::Int32Ty, + field.getInt32Field(obj)); + Elts.push_back(CI); + } else if (prim->isLong()) { + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, + field.getLongField(obj)); + Elts.push_back(CI); + } else if (prim->isFloat()) { + Constant* CF = ConstantFP::get(Type::FloatTy, + field.getFloatField(obj)); + Elts.push_back(CF); + } else if (prim->isDouble()) { + Constant* CF = ConstantFP::get(Type::DoubleTy, + field.getDoubleField(obj)); + Elts.push_back(CF); + } else { + abort(); + } + } else { + JavaObject* val = field.getObjectField(obj); + if (val) { + Constant* CO = getFinalObject(val); + Elts.push_back(CO); + } else { + Elts.push_back(Constant::getNullValue(Ty)); + } + } + } else { + Elts.push_back(Constant::getNullValue(Ty)); + } } else { Reader reader(attribut, cl->bytes); JavaConstantPool * ctpInfo = cl->ctpInfo; @@ -453,7 +505,7 @@ // JavaObject Constant* CurConstant = CreateConstantForBaseObject(obj->getClass()); - for (uint32 j = 0; j <= cl->virtualVT->depth; ++j) { + for (uint32 j = 0; j < cl->virtualVT->depth; ++j) { std::vector TempElts; Elmts.push_back(CurConstant); TempElts.push_back(CurConstant); From nicolas.geoffray at lip6.fr Wed Jul 8 14:42:23 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 08 Jul 2009 21:42:23 -0000 Subject: [vmkit-commits] [vmkit] r75051 - /vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Message-ID: <200907082142.n68LgOKC028035@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 8 16:42:21 2009 New Revision: 75051 URL: http://llvm.org/viewvc/llvm-project?rev=75051&view=rev Log: Set correct virtualType of java.lang.Object. Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=75051&r1=75050&r2=75051&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Wed Jul 8 16:42:21 2009 @@ -39,35 +39,35 @@ const Type* LLVMClassInfo::getVirtualType() { if (!virtualType) { std::vector fields; + const TargetData* targetData = JnjvmModule::TheTargetData; + const StructLayout* sl = 0; + const StructType* structType = 0; if (classDef->super) { LLVMClassInfo* CLI = JavaLLVMCompiler::getClassInfo(classDef->super); const llvm::Type* Ty = CLI->getVirtualType()->getContainedType(0); - - if (classDef->super->super) { - fields.push_back(Ty); - } else { - fields.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); + fields.push_back(Ty); + + for (uint32 i = 0; i < classDef->nbVirtualFields; ++i) { + JavaField& field = classDef->virtualFields[i]; + field.num = i + 1; + Typedef* type = field.getSignature(); + LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(type); + fields.push_back(LAI.llvmType); } - } else { - fields.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); - } - for (uint32 i = 0; i < classDef->nbVirtualFields; ++i) { - JavaField& field = classDef->virtualFields[i]; - field.num = i + 1; - Typedef* type = field.getSignature(); - LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(type); - fields.push_back(LAI.llvmType); - } + structType = StructType::get(fields, false); + virtualType = PointerType::getUnqual(structType); + sl = targetData->getStructLayout(structType); + + } else { + virtualType = JnjvmModule::JavaObjectType; + structType = dyn_cast(virtualType->getContainedType(0)); + sl = targetData->getStructLayout(structType); + + } - JavaLLVMCompiler* Mod = - (JavaLLVMCompiler*)classDef->classLoader->getCompiler(); - StructType* structType = StructType::get(fields, false); - virtualType = PointerType::getUnqual(structType); - const TargetData* targetData = JnjvmModule::TheTargetData; - const StructLayout* sl = targetData->getStructLayout(structType); for (uint32 i = 0; i < classDef->nbVirtualFields; ++i) { JavaField& field = classDef->virtualFields[i]; @@ -78,6 +78,8 @@ classDef->virtualSize = (uint32)size; virtualSizeConstant = ConstantInt::get(Type::Int32Ty, size); + JavaLLVMCompiler* Mod = + (JavaLLVMCompiler*)classDef->classLoader->getCompiler(); Mod->makeVT(classDef); } From nicolas.geoffray at lip6.fr Thu Jul 9 02:19:59 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 09 Jul 2009 09:19:59 -0000 Subject: [vmkit-commits] [vmkit] r75128 - /vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc Message-ID: <200907090920.n699K0Po030655@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 9 04:19:47 2009 New Revision: 75128 URL: http://llvm.org/viewvc/llvm-project?rev=75128&view=rev Log: Catch null value. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc?rev=75128&r1=75127&r2=75128&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc Thu Jul 9 04:19:47 2009 @@ -52,6 +52,7 @@ BEGIN_NATIVE_EXCEPTION(0) + verifyNull(str); Jnjvm* vm = JavaThread::get()->getJVM(); JnjvmClassLoader* JCL = JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm); From nicolas.geoffray at lip6.fr Thu Jul 9 02:33:38 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 09 Jul 2009 09:33:38 -0000 Subject: [vmkit-commits] [vmkit] r75130 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907090933.n699XdUV031112@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 9 04:33:30 2009 New Revision: 75130 URL: http://llvm.org/viewvc/llvm-project?rev=75130&view=rev Log: Bugfix when cliniting .jar file. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75130&r1=75129&r2=75130&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Thu Jul 9 04:33:30 2009 @@ -1647,8 +1647,7 @@ } if (M->runClinit) { - JavaJITCompiler* Comp = new JavaJITCompiler("JIT"); - bootstrapLoader->setCompiler(Comp); + vm->loadBootstrap(); for (std::vector::iterator i = classes.begin(), e = classes.end(); i != e; ++i) { From nicolas.geoffray at lip6.fr Thu Jul 9 03:27:02 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 09 Jul 2009 10:27:02 -0000 Subject: [vmkit-commits] [vmkit] r75131 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JavaAOTCompiler.cpp tools/vmjc/vmjc.cpp Message-ID: <200907091027.n69AR2bL032645@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 9 05:27:00 2009 New Revision: 75131 URL: http://llvm.org/viewvc/llvm-project?rev=75131&view=rev Log: One can set properties to the VM (-Da=b) when static compiling. This may be useful for clinits. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=75131&r1=75130&r2=75131&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Thu Jul 9 05:27:00 2009 @@ -47,6 +47,7 @@ class JavaObject; class JavaString; class JavaVirtualTable; +class Jnjvm; class JnjvmClassLoader; class JnjvmModule; class Typedef; @@ -648,7 +649,7 @@ void printStats(); - void compileFile(JnjvmClassLoader* JCL, const char* name); + void compileFile(Jnjvm* vm, const char* name); void compileClass(Class* cl); void generateMain(const char* name, bool jit); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75131&r1=75130&r2=75131&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Thu Jul 9 05:27:00 2009 @@ -1733,10 +1733,8 @@ } -void JavaAOTCompiler::compileFile(JnjvmClassLoader* JCL, const char* n) { +void JavaAOTCompiler::compileFile(Jnjvm* vm, const char* n) { name = n; - mvm::BumpPtrAllocator A; - Jnjvm* vm = new(A, "Bootstrap loader") Jnjvm(A, (JnjvmBootstrapLoader*)JCL); JavaThread* th = new JavaThread(0, 0, vm); vm->setMainThread(th); th->start((void (*)(mvm::Thread*))mainCompilerStart); Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=75131&r1=75130&r2=75131&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Thu Jul 9 05:27:00 2009 @@ -47,6 +47,7 @@ #include "jnjvm/JnjvmModuleProvider.h" #include "../../lib/JnJVM/VMCore/JnjvmClassLoader.h" +#include "../../lib/JnJVM/VMCore/Jnjvm.h" #include #include @@ -114,6 +115,9 @@ cl::desc("Print stats by the AOT compiler")); +static cl::list +Properties("D", cl::desc("Set a property"), cl::Prefix, cl::ZeroOrMore); + inline void addPass(FunctionPassManager *PM, Pass *P) { @@ -218,7 +222,25 @@ if (DisableStubs) Comp->generateStubs = false; if (AssumeCompiled) Comp->assumeCompiled = true; if (WithClinit) Comp->runClinit = true; - Comp->compileFile(JCL, InputFilename.c_str()); + + mvm::BumpPtrAllocator A; + Jnjvm* vm = new(A, "Bootstrap loader") Jnjvm(A, (JnjvmBootstrapLoader*)JCL); + + for (std::vector::iterator i = Properties.begin(), + e = Properties.end(); i != e; ++i) { + + char* key = new char [(*i).size()+1]; + strcpy(key, (*i).c_str()); + char* value = strchr(key, '='); + if (!value) { + delete[] key; + } else { + value[0] = 0; + vm->addProperty(key, &value[1]); + } + } + + Comp->compileFile(vm, InputFilename.c_str()); if (!MainClass.empty()) { Comp->generateMain(MainClass.c_str(), WithJIT); From nicolas.geoffray at lip6.fr Thu Jul 9 06:32:14 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 09 Jul 2009 13:32:14 -0000 Subject: [vmkit-commits] [vmkit] r75133 - /vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Message-ID: <200907091332.n69DWFUQ005891@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 9 08:32:14 2009 New Revision: 75133 URL: http://llvm.org/viewvc/llvm-project?rev=75133&view=rev Log: Fix includes. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h?rev=75133&r1=75132&r2=75133&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Thu Jul 9 08:32:14 2009 @@ -11,6 +11,7 @@ #define JNJVM_JAVA_THREAD_H #include +#include #include "mvm/Object.h" #include "mvm/Threads/Cond.h" @@ -22,6 +23,7 @@ namespace jnjvm { class Class; +class JavaMethod; class JavaObject; class Jnjvm; class LockObj; From nicolas.geoffray at lip6.fr Thu Jul 9 23:28:01 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Fri, 10 Jul 2009 06:28:01 -0000 Subject: [vmkit-commits] [vmkit] r75235 - /vmkit/trunk/include/mvm/Threads/Thread.h Message-ID: <200907100628.n6A6S1HW008627@zion.cs.uiuc.edu> Author: geoffray Date: Fri Jul 10 01:28:01 2009 New Revision: 75235 URL: http://llvm.org/viewvc/llvm-project?rev=75235&view=rev Log: Fix macro for macosx/ppc32. Modified: vmkit/trunk/include/mvm/Threads/Thread.h Modified: vmkit/trunk/include/mvm/Threads/Thread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=75235&r1=75234&r2=75235&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Threads/Thread.h (original) +++ vmkit/trunk/include/mvm/Threads/Thread.h Fri Jul 10 01:28:01 2009 @@ -79,7 +79,7 @@ -#if defined(__MACH__) && defined(__PPC__) +#if defined(__MACH__) && (defined(__PPC__) || defined(__ppc__)) #define FRAME_IP(fp) (fp[2]) #else #define FRAME_IP(fp) (fp[1]) From nicolas.geoffray at lip6.fr Sun Jul 12 14:55:30 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Sun, 12 Jul 2009 21:55:30 -0000 Subject: [vmkit-commits] [vmkit] r75434 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JavaAOTCompiler.cpp tools/vmjc/vmjc.cpp Message-ID: <200907122155.n6CLtVZX001409@zion.cs.uiuc.edu> Author: geoffray Date: Sun Jul 12 16:55:30 2009 New Revision: 75434 URL: http://llvm.org/viewvc/llvm-project?rev=75434&view=rev Log: Change how to specify which classes must be clinited. Also a couple of bugfixes for emitting Java objects and magic objects. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=75434&r1=75433&r2=75434&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Sun Jul 12 16:55:30 2009 @@ -11,6 +11,7 @@ #define JNJVM_MODULE_H #include +#include #include "mvm/Allocator.h" #include "mvm/JIT.h" @@ -639,8 +640,9 @@ bool generateStubs; bool assumeCompiled; - bool runClinit; bool compileRT; + + std::vector* clinits; void CreateStaticInitializer(); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75434&r1=75433&r2=75434&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Sun Jul 12 16:55:30 2009 @@ -210,21 +210,31 @@ Constant* JavaAOTCompiler::getFinalObject(JavaObject* obj) { - llvm::Constant* varGV = 0; + llvm::GlobalVariable* varGV = 0; final_object_iterator End = finalObjects.end(); final_object_iterator I = finalObjects.find(obj); if (I == End) { - Constant* CO = CreateConstantFromJavaObject(obj); - - varGV = new GlobalVariable(CO->getType(), true, - GlobalValue::InternalLinkage, - CO, "", getLLVMModule()); + + if (mvm::Collector::begOf(obj)) { + + const Type* Ty = JnjvmModule::JavaObjectType->getContainedType(0); + varGV = new GlobalVariable(Ty, true, GlobalValue::InternalLinkage, + 0, "", getLLVMModule()); - varGV = ConstantExpr::getCast(Instruction::BitCast, varGV, - JnjvmModule::JavaObjectType); - finalObjects.insert(std::make_pair(obj, varGV)); - return varGV; + finalObjects.insert(std::make_pair(obj, varGV)); + + Constant* C = ConstantExpr::getBitCast(CreateConstantFromJavaObject(obj), + Ty); + + varGV->setInitializer(C); + return varGV; + } else { + Constant* CI = ConstantInt::get(Type::Int64Ty, uint64_t(obj)); + CI = ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); + finalObjects.insert(std::make_pair(obj, CI)); + return CI; + } } else { return I->second; } @@ -505,7 +515,7 @@ // JavaObject Constant* CurConstant = CreateConstantForBaseObject(obj->getClass()); - for (uint32 j = 0; j < cl->virtualVT->depth; ++j) { + for (uint32 j = 1; j <= cl->virtualVT->depth; ++j) { std::vector TempElts; Elmts.push_back(CurConstant); TempElts.push_back(CurConstant); @@ -547,8 +557,14 @@ abort(); } } else { - Constant* C = getFinalObject(field.getObjectField(obj)); - TempElts.push_back(C); + JavaObject* val = field.getObjectField(obj); + if (val) { + Constant* C = getFinalObject(field.getObjectField(obj)); + TempElts.push_back(C); + } else { + const llvm::Type* Ty = JnjvmModule::JavaObjectType; + TempElts.push_back(Constant::getNullValue(Ty)); + } } } CurConstant = ConstantStruct::get(STy, TempElts); @@ -1115,7 +1131,11 @@ } else if (Ty->isFloatingPoint()) { Vals.push_back(ConstantFP::get(Ty, (double)(size_t)val->elements[i])); } else { - Vals.push_back(getFinalObject((JavaObject*)(size_t)val->elements[i])); + if (val->elements[i]) { + Vals.push_back(getFinalObject((JavaObject*)(size_t)val->elements[i])); + } else { + Vals.push_back(Constant::getNullValue(JnjvmModule::JavaObjectType)); + } } } @@ -1575,10 +1595,11 @@ Jnjvm* vm = th->getJVM(); JnjvmBootstrapLoader* bootstrapLoader = vm->bootstrapLoader; JavaAOTCompiler* M = (JavaAOTCompiler*)bootstrapLoader->getCompiler(); + JavaJITCompiler* Comp = 0; try { - if (M->runClinit) { - JavaJITCompiler* Comp = new JavaJITCompiler("JIT"); + if (!M->clinits->empty()) { + Comp = new JavaJITCompiler("JIT"); bootstrapLoader->setCompiler(Comp); bootstrapLoader->analyseClasspathEnv(vm->classpath); } else { @@ -1646,13 +1667,44 @@ } - if (M->runClinit) { + if (!M->clinits->empty()) { vm->loadBootstrap(); - - for (std::vector::iterator i = classes.begin(), e = classes.end(); - i != e; ++i) { - Class* cl = *i; - cl->initialiseClass(vm); + + for (std::vector::iterator i = M->clinits->begin(), + e = M->clinits->end(); i != e; ++i) { + + if (i->at(i->length() - 1) == '*') { + for (std::vector::iterator ii = classes.begin(), + ee = classes.end(); ii != ee; ++ii) { + Class* cl = *ii; + if (!strncmp(UTF8Buffer(cl->name).cString(), i->c_str(), + i->length() - 1)) { + try { + cl->asClass()->initialiseClass(vm); + } catch (...) { + fprintf(stderr, "Error when initializing %s\n", + UTF8Buffer(cl->name).cString()); + abort(); + } + } + } + } else { + + const UTF8* name = bootstrapLoader->asciizConstructUTF8(i->c_str()); + CommonClass* cl = bootstrapLoader->lookupClass(name); + if (cl && cl->isClass()) { + try { + cl->asClass()->initialiseClass(vm); + } catch (...) { + fprintf(stderr, "Error when initializing %s\n", + UTF8Buffer(cl->name).cString()); + abort(); + } + } else { + fprintf(stderr, "Class %s does not exist or is an array class.\n", + i->c_str()); + } + } } bootstrapLoader->setCompiler(M); } @@ -1675,7 +1727,7 @@ const UTF8* utf8 = bootstrapLoader->asciizConstructUTF8(realName); UserClass* cl = bootstrapLoader->loadName(utf8, true, true); - if (M->runClinit) { + if (!M->clinits->empty()) { vm->loadBootstrap(); cl->initialiseClass(vm); bootstrapLoader->setCompiler(M); Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=75434&r1=75433&r2=75434&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Sun Jul 12 16:55:30 2009 @@ -107,9 +107,6 @@ AssumeCompiled("assume-compiled", cl::desc("Assume external Java classes are compiled")); -static cl::opt -WithClinit("with-clinit", cl::desc("Clinit the given file")); - static cl::opt PrintStats("print-aot-stats", cl::desc("Print stats by the AOT compiler")); @@ -118,6 +115,10 @@ static cl::list Properties("D", cl::desc("Set a property"), cl::Prefix, cl::ZeroOrMore); +static cl::list +WithClinit("with-clinit", cl::desc("Set a property"), cl::ZeroOrMore, + cl::CommaSeparated); + inline void addPass(FunctionPassManager *PM, Pass *P) { @@ -179,7 +180,7 @@ return 0; } - if (!WithClinit) { + if (WithClinit.empty()) { Module* TheModule = new Module("bootstrap module", *(new llvm::LLVMContext())); if (!TargetTriple.empty()) @@ -213,7 +214,6 @@ JavaAOTCompiler* Comp = new JavaAOTCompiler("AOT"); mvm::Collector::initialise(); - mvm::Collector::enable(0); JnjvmClassLoader* JCL = mvm::VirtualMachine::initialiseJVM(Comp, false); addCommandLinePass(argv); @@ -221,7 +221,6 @@ if (DisableExceptions) Comp->disableExceptions(); if (DisableStubs) Comp->generateStubs = false; if (AssumeCompiled) Comp->assumeCompiled = true; - if (WithClinit) Comp->runClinit = true; mvm::BumpPtrAllocator A; Jnjvm* vm = new(A, "Bootstrap loader") Jnjvm(A, (JnjvmBootstrapLoader*)JCL); @@ -240,6 +239,7 @@ } } + Comp->clinits = &WithClinit; Comp->compileFile(vm, InputFilename.c_str()); if (!MainClass.empty()) { From nicolas.geoffray at lip6.fr Mon Jul 13 01:22:29 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 08:22:29 -0000 Subject: [vmkit-commits] [vmkit] r75457 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907130822.n6D8MWEl001106@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 03:22:22 2009 New Revision: 75457 URL: http://llvm.org/viewvc/llvm-project?rev=75457&view=rev Log: Implement getFinalObject in AOT when emitting static fields. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=75457&r1=75456&r2=75457&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Mon Jul 13 03:22:22 2009 @@ -588,10 +588,14 @@ std::map utf8s; std::map virtualMethods; std::map finalObjects; + std::map reverseFinalObjects; typedef std::map::iterator final_object_iterator; + typedef std::map::iterator + reverse_final_object_iterator; + typedef std::map::iterator method_iterator; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75457&r1=75456&r2=75457&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 13 03:22:22 2009 @@ -204,6 +204,12 @@ } JavaObject* JavaAOTCompiler::getFinalObject(llvm::Value* obj) { + if (Constant* CI = dyn_cast(obj)) { + reverse_final_object_iterator End = reverseFinalObjects.end(); + reverse_final_object_iterator I = reverseFinalObjects.find(CI); + if (I != End) return I->second; + } + return 0; } @@ -218,11 +224,12 @@ if (mvm::Collector::begOf(obj)) { const Type* Ty = JnjvmModule::JavaObjectType->getContainedType(0); - varGV = new GlobalVariable(Ty, true, GlobalValue::InternalLinkage, + varGV = new GlobalVariable(Ty, false, GlobalValue::InternalLinkage, 0, "", getLLVMModule()); finalObjects.insert(std::make_pair(obj, varGV)); + reverseFinalObjects.insert(std::make_pair(varGV, obj)); Constant* C = ConstantExpr::getBitCast(CreateConstantFromJavaObject(obj), Ty); From nicolas.geoffray at lip6.fr Mon Jul 13 02:28:53 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 09:28:53 -0000 Subject: [vmkit-commits] [vmkit] r75458 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907130928.n6D9SsRd003821@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 04:28:52 2009 New Revision: 75458 URL: http://llvm.org/viewvc/llvm-project?rev=75458&view=rev Log: Bugfix when static emitting Java objects. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75458&r1=75457&r2=75458&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 13 04:28:52 2009 @@ -222,20 +222,59 @@ if (I == End) { if (mvm::Collector::begOf(obj)) { + const Type* Ty = 0; + CommonClass* cl = obj->getClass(); + + if (cl->isArray()) { + Classpath* upcalls = cl->classLoader->bootstrapLoader->upcalls; + CommonClass* subClass = cl->asArrayClass()->baseClass(); + if (subClass->isPrimitive()) { + if (subClass == upcalls->OfBool) { + Ty = Type::Int8Ty; + } else if (subClass == upcalls->OfByte) { + Ty = Type::Int8Ty; + } else if (subClass == upcalls->OfShort) { + Ty = Type::Int16Ty; + } else if (subClass == upcalls->OfChar) { + Ty = Type::Int16Ty; + } else if (subClass == upcalls->OfInt) { + Ty = Type::Int32Ty; + } else if (subClass == upcalls->OfFloat) { + Ty = Type::FloatTy; + } else if (subClass == upcalls->OfLong) { + Ty = Type::Int64Ty; + } else if (subClass == upcalls->OfDouble) { + Ty = Type::DoubleTy; + } else { + abort(); + } + } else { + Ty = JnjvmModule::JavaObjectType; + } + + std::vector Elemts; + const ArrayType* ATy = ArrayType::get(Ty, ((JavaArray*)obj)->size); + Elemts.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); + Elemts.push_back(JnjvmModule::pointerSizeType); + Elemts.push_back(ATy); + Ty = StructType::get(Elemts); + + } else { + LLVMClassInfo* LCI = getClassInfo(cl->asClass()); + Ty = LCI->getVirtualType()->getContainedType(0); + } - const Type* Ty = JnjvmModule::JavaObjectType->getContainedType(0); varGV = new GlobalVariable(Ty, false, GlobalValue::InternalLinkage, 0, "", getLLVMModule()); + Constant* C = ConstantExpr::getBitCast(varGV, + JnjvmModule::JavaObjectType); - finalObjects.insert(std::make_pair(obj, varGV)); - reverseFinalObjects.insert(std::make_pair(varGV, obj)); - - Constant* C = ConstantExpr::getBitCast(CreateConstantFromJavaObject(obj), - Ty); + finalObjects.insert(std::make_pair(obj, C)); + reverseFinalObjects.insert(std::make_pair(C, obj)); - varGV->setInitializer(C); - return varGV; + varGV->setInitializer(CreateConstantFromJavaObject(obj)); + return C; } else { Constant* CI = ConstantInt::get(Type::Int64Ty, uint64_t(obj)); CI = ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); From nicolas.geoffray at lip6.fr Mon Jul 13 02:42:18 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 09:42:18 -0000 Subject: [vmkit-commits] [vmkit] r75459 - in /vmkit/trunk: include/jnjvm/JavaCompiler.h include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JITInfo.cpp lib/JnJVM/Compiler/JavaAOTCompiler.cpp lib/JnJVM/Compiler/JavaJITCompiler.cpp Message-ID: <200907130942.n6D9gKTA004246@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 04:42:13 2009 New Revision: 75459 URL: http://llvm.org/viewvc/llvm-project?rev=75459&view=rev Log: New compiler function, emitFunctionName, to emit a function name in the LLVM IR. Modified: vmkit/trunk/include/jnjvm/JavaCompiler.h vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Modified: vmkit/trunk/include/jnjvm/JavaCompiler.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JavaCompiler.h?rev=75459&r1=75458&r2=75459&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JavaCompiler.h (original) +++ vmkit/trunk/include/jnjvm/JavaCompiler.h Mon Jul 13 04:42:13 2009 @@ -41,6 +41,10 @@ return false; } + virtual bool emitFunctionName() { + return false; + } + virtual void resolveVirtualClass(Class* cl) { fprintf(stderr, "Resolving a class in an empty compiler"); abort(); Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=75459&r1=75458&r2=75459&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Mon Jul 13 04:42:13 2009 @@ -384,6 +384,7 @@ JavaLLVMCompiler(const std::string &ModuleID); virtual bool isStaticCompiling() = 0; + virtual bool emitFunctionName() = 0; llvm::Module* getLLVMModule() { return TheModule; @@ -466,12 +467,19 @@ class JavaJITCompiler : public JavaLLVMCompiler { public: + + bool EmitFunctionName; + JavaJITCompiler(const std::string &ModuleID); virtual bool isStaticCompiling() { return false; } - + + virtual bool emitFunctionName() { + return EmitFunctionName; + } + virtual void makeVT(Class* cl); virtual JavaCompiler* Create(const std::string& ModuleID) { @@ -516,6 +524,10 @@ return true; } + virtual bool emitFunctionName() { + return true; + } + virtual JavaCompiler* Create(const std::string& ModuleID) { return new JavaAOTCompiler(ModuleID); } Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=75459&r1=75458&r2=75459&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Mon Jul 13 04:42:13 2009 @@ -131,7 +131,7 @@ if (!methodFunction) { JnjvmClassLoader* JCL = methodDef->classDef->classLoader; JavaLLVMCompiler* Mod = (JavaLLVMCompiler*)JCL->getCompiler(); - if (Mod->isStaticCompiling()) { + if (Mod->emitFunctionName()) { const UTF8* jniConsClName = methodDef->classDef->name; const UTF8* jniConsName = methodDef->name; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75459&r1=75458&r2=75459&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 13 04:42:13 2009 @@ -1646,6 +1646,7 @@ if (!M->clinits->empty()) { Comp = new JavaJITCompiler("JIT"); + Comp->EmitFunctionName = true; bootstrapLoader->setCompiler(Comp); bootstrapLoader->analyseClasspathEnv(vm->classpath); } else { Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=75459&r1=75458&r2=75459&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Mon Jul 13 04:42:13 2009 @@ -122,7 +122,12 @@ JavaJITCompiler::JavaJITCompiler(const std::string &ModuleID) : JavaLLVMCompiler(ModuleID) { - + +#if DEBUG + EmitFunctionName = true; +#else + EmitFunctionName = false; +#endif TheModuleProvider = new JnjvmModuleProvider(TheModule); addJavaPasses(); } From nicolas.geoffray at lip6.fr Mon Jul 13 04:22:24 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 11:22:24 -0000 Subject: [vmkit-commits] [vmkit] r75462 - in /vmkit/trunk/lib: JnJVM/Compiler/ExceptionsCheck.inc JnJVM/Compiler/ExceptionsDwarf.inc JnJVM/Compiler/JITInfo.cpp JnJVM/Compiler/JavaAOTCompiler.cpp JnJVM/Compiler/JavaJIT.cpp JnJVM/Compiler/JavaJIT.h JnJVM/Compiler/JavaJITOpcodes.cpp JnJVM/Compiler/JnjvmModule.cpp JnJVM/Compiler/LowerConstantCalls.cpp Mvm/Compiler/JIT.cpp N3/Mono/MonoString.cpp N3/PNetLib/PNetString.cpp N3/VMCore/CLIJit.cpp N3/VMCore/CLIJitMeta.cpp N3/VMCore/Opcodes.cpp N3/VMCore/VMCache.cpp Message-ID: <200907131122.n6DBMQl6007681@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 06:22:20 2009 New Revision: 75462 URL: http://llvm.org/viewvc/llvm-project?rev=75462&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp vmkit/trunk/lib/N3/Mono/MonoString.cpp vmkit/trunk/lib/N3/PNetLib/PNetString.cpp vmkit/trunk/lib/N3/VMCore/CLIJit.cpp vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp vmkit/trunk/lib/N3/VMCore/Opcodes.cpp vmkit/trunk/lib/N3/VMCore/VMCache.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc Mon Jul 13 06:22:20 2009 @@ -34,12 +34,12 @@ // the function is readnone. obj = new LoadInst(javaExceptionPtr, "", true, currentBlock); test = new BitCastInst(res, module->JavaObjectType, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_EQ, test, obj, "", currentBlock); - Value* T = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, obj, ""); + Value* T = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); test = BinaryOperator::CreateAnd(test, T, "", currentBlock); } else { obj = new LoadInst(javaExceptionPtr, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); } BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock); @@ -84,12 +84,12 @@ F == module->GetClassDelegateeFunction) { obj = new LoadInst(javaExceptionPtr, "", true, currentBlock); test = new BitCastInst(res, module->JavaObjectType, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_EQ, test, obj, "", currentBlock); - Value* T = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, obj, ""); + Value* T = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); test = BinaryOperator::CreateAnd(test, T, "", currentBlock); } else { obj = new LoadInst(javaExceptionPtr, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); } BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock); @@ -135,12 +135,12 @@ F == module->GetClassDelegateeFunction) { obj = new LoadInst(javaExceptionPtr, "", true, currentBlock); test = new BitCastInst(res, module->JavaObjectType, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_EQ, test, obj, "", currentBlock); - Value* T = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, obj, ""); + Value* T = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); test = BinaryOperator::CreateAnd(test, T, "", currentBlock); } else { obj = new LoadInst(javaExceptionPtr, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); } BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock); @@ -183,12 +183,12 @@ F == module->GetClassDelegateeFunction) { obj = new LoadInst(javaExceptionPtr, "", true, currentBlock); test = new BitCastInst(res, module->JavaObjectType, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_EQ, test, obj, "", currentBlock); - Value* T = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, obj, ""); + Value* T = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); test = BinaryOperator::CreateAnd(test, T, "", currentBlock); } else { obj = new LoadInst(javaExceptionPtr, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, obj, zero, ""); } BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock); @@ -214,7 +214,7 @@ BranchInst::Create(currentExceptionBlock, currentBlock); } else { if (endNode) { - endNode->addIncoming(Constant::getNullValue(endNode->getType()), + endNode->addIncoming(llvmContext->getNullValue(endNode->getType()), currentBlock); } BranchInst::Create(endBlock, currentBlock); @@ -237,7 +237,7 @@ BranchInst::Create(currentExceptionBlock, currentBlock); } else { if (endNode) { - endNode->addIncoming(Constant::getNullValue(endNode->getType()), + endNode->addIncoming(llvmContext->getNullValue(endNode->getType()), currentBlock); } BranchInst::Create(endBlock, currentBlock); @@ -254,7 +254,7 @@ BranchInst::Create(currentExceptionBlock, currentBlock); } else { if (endNode) { - endNode->addIncoming(Constant::getNullValue(endNode->getType()), + endNode->addIncoming(llvmContext->getNullValue(endNode->getType()), currentBlock); } BranchInst::Create(endBlock, currentBlock); @@ -411,8 +411,8 @@ Status = new LoadInst(Status, "", currentBlock); Status = new PtrToIntInst(Status, Type::Int32Ty, "", currentBlock); - Value* stopping = new ICmpInst(ICmpInst::ICMP_EQ, Status, - module->constantOne, "", currentBlock); + Value* stopping = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, Status, + module->constantOne, ""); BasicBlock* raiseBlock = createBasicBlock("raiseBlock"); BasicBlock* continueBlock = createBasicBlock("continueBlock"); @@ -451,8 +451,8 @@ displayArgs, displayArgs + 2, "", currentBlock); - cmp = new ICmpInst(ICmpInst::ICMP_EQ, VTInDisplay, VTVar, "", - currentBlock); + cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, VTInDisplay, VTVar, + ""); } // Add the Java exception in the phi node of the handler. @@ -533,7 +533,7 @@ endExceptionBlock->eraseFromParent(); } else { if (endNode) { - endNode->addIncoming(Constant::getNullValue(endNode->getType()), + endNode->addIncoming(llvmContext->getNullValue(endNode->getType()), endExceptionBlock); } BranchInst::Create(endBlock, endExceptionBlock); @@ -556,7 +556,7 @@ Instruction* insn = BI->begin(); PHINode* node = dyn_cast(insn); if (node) { - node->replaceAllUsesWith(Constant::getNullValue(node->getType())); + node->replaceAllUsesWith(llvmContext->getNullValue(node->getType())); node->eraseFromParent(); } } Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc Mon Jul 13 06:22:20 2009 @@ -399,8 +399,8 @@ Status = new LoadInst(Status, "", currentBlock); Status = new PtrToIntInst(Status, Type::Int32Ty, "", currentBlock); - Value* stopping = new ICmpInst(ICmpInst::ICMP_EQ, Status, - module->constantOne, "", currentBlock); + Value* stopping = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, Status, + module->constantOne, ""); BasicBlock* raiseBlock = createBasicBlock("raiseBlock"); BasicBlock* continueBlock = createBasicBlock("continueBlock"); @@ -431,8 +431,8 @@ currentBlock); // Compare the exception with the exception class we catch. - Value* cmp = new ICmpInst(ICmpInst::ICMP_ULE, depthCl, depthClObj, "", - currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_ULE, depthCl, + depthClObj, ""); BasicBlock* supDepth = createBasicBlock("superior depth"); @@ -450,8 +450,8 @@ displayArgs, displayArgs + 2, "", currentBlock); - cmp = new ICmpInst(ICmpInst::ICMP_EQ, clInDisplay, clVar, "", - currentBlock); + cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, clInDisplay, clVar, + ""); // If we are catching this exception, then jump to the nativeHandler, // otherwise jump to our next handler. Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Mon Jul 13 06:22:20 2009 @@ -543,56 +543,56 @@ AssessorInfo[I_BOOL].llvmType = Type::Int8Ty; AssessorInfo[I_BOOL].llvmTypePtr = PointerType::getUnqual(Type::Int8Ty); AssessorInfo[I_BOOL].llvmNullConstant = - Constant::getNullValue(Type::Int8Ty); + mvm::MvmModule::globalContext->getNullValue(Type::Int8Ty); AssessorInfo[I_BOOL].logSizeInBytesConstant = mvm::MvmModule::constantZero; AssessorInfo[I_BYTE].llvmType = Type::Int8Ty; AssessorInfo[I_BYTE].llvmTypePtr = PointerType::getUnqual(Type::Int8Ty); AssessorInfo[I_BYTE].llvmNullConstant = - Constant::getNullValue(Type::Int8Ty); + mvm::MvmModule::globalContext->getNullValue(Type::Int8Ty); AssessorInfo[I_BYTE].logSizeInBytesConstant = mvm::MvmModule::constantZero; AssessorInfo[I_SHORT].llvmType = Type::Int16Ty; AssessorInfo[I_SHORT].llvmTypePtr = PointerType::getUnqual(Type::Int16Ty); AssessorInfo[I_SHORT].llvmNullConstant = - Constant::getNullValue(Type::Int16Ty); + mvm::MvmModule::globalContext->getNullValue(Type::Int16Ty); AssessorInfo[I_SHORT].logSizeInBytesConstant = mvm::MvmModule::constantOne; AssessorInfo[I_CHAR].llvmType = Type::Int16Ty; AssessorInfo[I_CHAR].llvmTypePtr = PointerType::getUnqual(Type::Int16Ty); AssessorInfo[I_CHAR].llvmNullConstant = - Constant::getNullValue(Type::Int16Ty); + mvm::MvmModule::globalContext->getNullValue(Type::Int16Ty); AssessorInfo[I_CHAR].logSizeInBytesConstant = mvm::MvmModule::constantOne; AssessorInfo[I_INT].llvmType = Type::Int32Ty; AssessorInfo[I_INT].llvmTypePtr = PointerType::getUnqual(Type::Int32Ty); AssessorInfo[I_INT].llvmNullConstant = - Constant::getNullValue(Type::Int32Ty); + mvm::MvmModule::globalContext->getNullValue(Type::Int32Ty); AssessorInfo[I_INT].logSizeInBytesConstant = mvm::MvmModule::constantTwo; AssessorInfo[I_FLOAT].llvmType = Type::FloatTy; AssessorInfo[I_FLOAT].llvmTypePtr = PointerType::getUnqual(Type::FloatTy); AssessorInfo[I_FLOAT].llvmNullConstant = - Constant::getNullValue(Type::FloatTy); + mvm::MvmModule::globalContext->getNullValue(Type::FloatTy); AssessorInfo[I_FLOAT].logSizeInBytesConstant = mvm::MvmModule::constantTwo; AssessorInfo[I_LONG].llvmType = Type::Int64Ty; AssessorInfo[I_LONG].llvmTypePtr = PointerType::getUnqual(Type::Int64Ty); AssessorInfo[I_LONG].llvmNullConstant = - Constant::getNullValue(Type::Int64Ty); + mvm::MvmModule::globalContext->getNullValue(Type::Int64Ty); AssessorInfo[I_LONG].logSizeInBytesConstant = mvm::MvmModule::constantThree; AssessorInfo[I_DOUBLE].llvmType = Type::DoubleTy; AssessorInfo[I_DOUBLE].llvmTypePtr = PointerType::getUnqual(Type::DoubleTy); AssessorInfo[I_DOUBLE].llvmNullConstant = - Constant::getNullValue(Type::DoubleTy); + mvm::MvmModule::globalContext->getNullValue(Type::DoubleTy); AssessorInfo[I_DOUBLE].logSizeInBytesConstant = mvm::MvmModule::constantThree; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 13 06:22:20 2009 @@ -64,10 +64,10 @@ Ty = JnjvmModule::JavaClassType->getContainedType(0); } - GlobalVariable* varGV = - new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage, 0, - UTF8Buffer(classDef->name).toCompileName()->cString(), - getLLVMModule()); + const char* val = UTF8Buffer(classDef->name).toCompileName()->cString(); + GlobalVariable* varGV = + new GlobalVariable(*getLLVMModule(), Ty, false, + GlobalValue::ExternalLinkage, 0, val); nativeClasses.insert(std::make_pair(classDef, varGV)); @@ -92,13 +92,13 @@ array_class_iterator End = arrayClasses.end(); array_class_iterator I = arrayClasses.find(classDef->asArrayClass()); if (I == End) { - const llvm::Type* Ty = JnjvmModule::JavaClassArrayType; + const llvm::Type* Ty = JnjvmModule::JavaClassArrayType; + Module& Mod = *getLLVMModule(); + const char* name = UTF8Buffer(classDef->name).toCompileName()->cString(); GlobalVariable* varGV = - new GlobalVariable(Ty, false, GlobalValue::InternalLinkage, - Constant::getNullValue(Ty), - UTF8Buffer(classDef->name).toCompileName()->cString(), - getLLVMModule()); + new GlobalVariable(Mod, Ty, false, GlobalValue::InternalLinkage, + Mod.getContext().getNullValue(Ty), name); arrayClasses.insert(std::make_pair(classDef->asArrayClass(), varGV)); return varGV; @@ -117,9 +117,11 @@ constant_pool_iterator I = constantPools.find(ctp); if (I == End) { const Type* Ty = JnjvmModule::ConstantPoolType->getContainedType(0); - varGV = new GlobalVariable(Ty, false, + Module& Mod = *getLLVMModule(); + + varGV = new GlobalVariable(Mod, Ty, false, GlobalValue::InternalLinkage, - Constant::getNullValue(Ty), "", getLLVMModule()); + Mod.getContext().getNullValue(Ty), ""); constantPools.insert(std::make_pair(ctp, varGV)); return varGV; } else { @@ -151,10 +153,11 @@ assert(str && "No string given"); LLVMClassInfo* LCI = getClassInfo(str->getClass()->asClass()); const llvm::Type* Ty = LCI->getVirtualType(); + Module& Mod = *getLLVMModule(); + GlobalVariable* varGV = - new GlobalVariable(Ty->getContainedType(0), false, - GlobalValue::InternalLinkage, - 0, "", getLLVMModule()); + new GlobalVariable(Mod, Ty->getContainedType(0), false, + GlobalValue::InternalLinkage, 0, ""); Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, JnjvmModule::JavaObjectType); strings.insert(std::make_pair(str, res)); @@ -169,9 +172,10 @@ if (SI != enveloppes.end()) { return SI->second; } else { + Module& Mod = *getLLVMModule(); GlobalVariable* varGV = - new GlobalVariable(JnjvmModule::EnveloppeType->getContainedType(0), false, - GlobalValue::InternalLinkage, 0, "", getLLVMModule()); + new GlobalVariable(Mod, JnjvmModule::EnveloppeType->getContainedType(0), + false, GlobalValue::InternalLinkage, 0, ""); enveloppes.insert(std::make_pair(enveloppe, varGV)); Constant* C = CreateConstantFromEnveloppe(enveloppe); @@ -187,10 +191,11 @@ Class* javaClass = cl->classLoader->bootstrapLoader->upcalls->newClass; LLVMClassInfo* LCI = getClassInfo(javaClass); const llvm::Type* Ty = LCI->getVirtualType(); + Module& Mod = *getLLVMModule(); GlobalVariable* varGV = - new GlobalVariable(Ty->getContainedType(0), false, - GlobalValue::InternalLinkage, 0, "", getLLVMModule()); + new GlobalVariable(Mod, Ty->getContainedType(0), false, + GlobalValue::InternalLinkage, 0, ""); Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, JnjvmModule::JavaObjectType); @@ -264,8 +269,9 @@ Ty = LCI->getVirtualType()->getContainedType(0); } - varGV = new GlobalVariable(Ty, false, GlobalValue::InternalLinkage, - 0, "", getLLVMModule()); + Module& Mod = *getLLVMModule(); + varGV = new GlobalVariable(Mod, Ty, false, GlobalValue::InternalLinkage, + 0, ""); Constant* C = ConstantExpr::getBitCast(varGV, JnjvmModule::JavaObjectType); @@ -290,6 +296,7 @@ LLVMClassInfo* LCI = getClassInfo(cl); const Type* Ty = LCI->getStaticType(); const StructType* STy = dyn_cast(Ty->getContainedType(0)); + Module& Mod = *getLLVMModule(); std::vector Elts; @@ -339,11 +346,11 @@ Constant* CO = getFinalObject(val); Elts.push_back(CO); } else { - Elts.push_back(Constant::getNullValue(Ty)); + Elts.push_back(Mod.getContext().getNullValue(Ty)); } } } else { - Elts.push_back(Constant::getNullValue(Ty)); + Elts.push_back(Mod.getContext().getNullValue(Ty)); } } else { Reader reader(attribut, cl->bytes); @@ -389,9 +396,10 @@ Ty = Ty->getContainedType(0); std::string name(UTF8Buffer(classDef->name).toCompileName()->cString()); name += "_static"; + Module& Mod = *getLLVMModule(); GlobalVariable* varGV = - new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage, - 0, name, getLLVMModule()); + new GlobalVariable(Mod, Ty, false, GlobalValue::ExternalLinkage, + 0, name); Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, JnjvmModule::ptrType); @@ -431,9 +439,10 @@ name += "_VT"; // Do not set a virtual table as a constant, because the runtime may // modify it. - GlobalVariable* varGV = new GlobalVariable(ATy, false, + Module& Mod = *getLLVMModule(); + GlobalVariable* varGV = new GlobalVariable(Mod, ATy, false, GlobalValue::ExternalLinkage, - 0, name, getLLVMModule()); + 0, name); res = ConstantExpr::getCast(Instruction::BitCast, varGV, JnjvmModule::VTType); @@ -459,10 +468,10 @@ LLVMSignatureInfo* LSI = getSignatureInfo(meth->getSignature()); const llvm::Type* valPtrType = LSI->getNativePtrType(); - varGV = new GlobalVariable(valPtrType, true, + Module& Mod = *getLLVMModule(); + varGV = new GlobalVariable(Mod, valPtrType, true, GlobalValue::InternalLinkage, - Constant::getNullValue(valPtrType), "", - getLLVMModule()); + Mod.getContext().getNullValue(valPtrType), ""); nativeFunctions.insert(std::make_pair(meth, varGV)); return varGV; @@ -490,6 +499,7 @@ Constant* JavaAOTCompiler::CreateConstantFromJavaClass(CommonClass* cl) { Class* javaClass = cl->classLoader->bootstrapLoader->upcalls->newClass; LLVMClassInfo* LCI = getClassInfo(javaClass); + Module& Mod = *getLLVMModule(); const StructType* STy = dyn_cast(LCI->getVirtualType()->getContainedType(0)); @@ -499,10 +509,10 @@ Elmts.push_back(CreateConstantForBaseObject(javaClass)); // signers - Elmts.push_back(Constant::getNullValue(JnjvmModule::JavaObjectType)); + Elmts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaObjectType)); // pd - Elmts.push_back(Constant::getNullValue(JnjvmModule::JavaObjectType)); + Elmts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaObjectType)); // vmdata Constant* Cl = getNativeClass(cl); @@ -511,13 +521,14 @@ Elmts.push_back(Cl); // constructor - Elmts.push_back(Constant::getNullValue(JnjvmModule::JavaObjectType)); + Elmts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaObjectType)); return ConstantStruct::get(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromJavaObject(JavaObject* obj) { CommonClass* cl = obj->getClass(); + Module& Mod = *getLLVMModule(); if (cl->isArray()) { Classpath* upcalls = cl->classLoader->bootstrapLoader->upcalls; @@ -609,7 +620,7 @@ TempElts.push_back(C); } else { const llvm::Type* Ty = JnjvmModule::JavaObjectType; - TempElts.push_back(Constant::getNullValue(Ty)); + TempElts.push_back(Mod.getContext().getNullValue(Ty)); } } } @@ -634,9 +645,10 @@ CreateConstantFromArray(str->value, Type::Int16Ty); - GlobalVariable* varGV = new GlobalVariable(Array->getType(), false, + Module& Mod = *getLLVMModule(); + GlobalVariable* varGV = new GlobalVariable(Mod, Array->getType(), false, GlobalValue::InternalLinkage, - Array, "", getLLVMModule()); + Array, ""); Array = ConstantExpr::getBitCast(varGV, JnjvmModule::JavaObjectType); @@ -652,11 +664,12 @@ Constant* JavaAOTCompiler::CreateConstantFromCacheNode(CacheNode* CN) { const StructType* STy = dyn_cast(JnjvmModule::CacheNodeType->getContainedType(0)); + Module& Mod = *getLLVMModule(); std::vector Elmts; - Elmts.push_back(Constant::getNullValue(STy->getContainedType(0))); - Elmts.push_back(Constant::getNullValue(STy->getContainedType(1))); - Elmts.push_back(Constant::getNullValue(STy->getContainedType(2))); + Elmts.push_back(Mod.getContext().getNullValue(STy->getContainedType(0))); + Elmts.push_back(Mod.getContext().getNullValue(STy->getContainedType(1))); + Elmts.push_back(Mod.getContext().getNullValue(STy->getContainedType(2))); Elmts.push_back(getEnveloppe(CN->enveloppe)); return ConstantStruct::get(STy, Elmts); @@ -668,17 +681,18 @@ dyn_cast(JnjvmModule::EnveloppeType->getContainedType(0)); const StructType* CNTy = dyn_cast(JnjvmModule::CacheNodeType->getContainedType(0)); + Module& Mod = *getLLVMModule(); std::vector Elmts; Constant* firstCache = CreateConstantFromCacheNode(val->firstCache); - Elmts.push_back(new GlobalVariable(CNTy, false, + Elmts.push_back(new GlobalVariable(*getLLVMModule(), CNTy, false, GlobalValue::InternalLinkage, - firstCache, "", getLLVMModule())); + firstCache, "")); Elmts.push_back(getUTF8(val->methodName)); Elmts.push_back(getUTF8(val->methodSign)); - Elmts.push_back(Constant::getNullValue(Type::Int8Ty)); + Elmts.push_back(Mod.getContext().getNullValue(Type::Int8Ty)); Elmts.push_back(getNativeClass(val->classDef)); Elmts.push_back(firstCache); @@ -708,6 +722,7 @@ Constant* JavaAOTCompiler::CreateConstantFromCommonClass(CommonClass* cl) { const StructType* STy = dyn_cast(JnjvmModule::JavaCommonClassType->getContainedType(0)); + Module& Mod = *getLLVMModule(); const llvm::Type* TempTy = 0; @@ -732,15 +747,16 @@ ATy = ArrayType::get(JnjvmModule::JavaClassType, cl->nbInterfaces); Constant* interfaces = ConstantArray::get(ATy, TempElmts); - interfaces = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, - interfaces, "", getLLVMModule()); + interfaces = new GlobalVariable(*getLLVMModule(), ATy, true, + GlobalValue::InternalLinkage, + interfaces, ""); interfaces = ConstantExpr::getCast(Instruction::BitCast, interfaces, PointerType::getUnqual(JnjvmModule::JavaClassType)); CommonClassElts.push_back(interfaces); } else { const Type* Ty = PointerType::getUnqual(JnjvmModule::JavaClassType); - CommonClassElts.push_back(Constant::getNullValue(Ty)); + CommonClassElts.push_back(Mod.getContext().getNullValue(Ty)); } // nbInterfaces @@ -754,7 +770,7 @@ CommonClassElts.push_back(getNativeClass(cl->super)); } else { TempTy = JnjvmModule::JavaClassType; - CommonClassElts.push_back(Constant::getNullValue(TempTy)); + CommonClassElts.push_back(Mod.getContext().getNullValue(TempTy)); } // classLoader: store the static initializer, it will be overriden once @@ -768,7 +784,7 @@ CommonClassElts.push_back(getVirtualTable(cl->virtualVT)); } else { TempTy = JnjvmModule::VTType; - CommonClassElts.push_back(Constant::getNullValue(TempTy)); + CommonClassElts.push_back(Mod.getContext().getNullValue(TempTy)); } return ConstantStruct::get(STy, CommonClassElts); } @@ -776,12 +792,13 @@ Constant* JavaAOTCompiler::CreateConstantFromJavaField(JavaField& field) { const StructType* STy = dyn_cast(JnjvmModule::JavaFieldType->getContainedType(0)); + Module& Mod = *getLLVMModule(); std::vector FieldElts; std::vector TempElts; // signature - FieldElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); // access FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.access)); @@ -802,14 +819,15 @@ Constant* attributs = ConstantArray::get(ATy, TempElts); TempElts.clear(); - attributs = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, - attributs, "", getLLVMModule()); + attributs = new GlobalVariable(*getLLVMModule(), ATy, true, + GlobalValue::InternalLinkage, + attributs, ""); attributs = ConstantExpr::getCast(Instruction::BitCast, attributs, JnjvmModule::AttributType); FieldElts.push_back(attributs); } else { - FieldElts.push_back(Constant::getNullValue(JnjvmModule::AttributType)); + FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::AttributType)); } // nbAttributs @@ -825,7 +843,7 @@ FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.num)); //JInfo - FieldElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); return ConstantStruct::get(STy, FieldElts); } @@ -833,12 +851,13 @@ Constant* JavaAOTCompiler::CreateConstantFromJavaMethod(JavaMethod& method) { const StructType* STy = dyn_cast(JnjvmModule::JavaMethodType->getContainedType(0)); + Module& Mod = *getLLVMModule(); std::vector MethodElts; std::vector TempElts; // signature - MethodElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); // access MethodElts.push_back(ConstantInt::get(Type::Int16Ty, method.access)); @@ -853,14 +872,15 @@ Constant* attributs = ConstantArray::get(ATy, TempElts); TempElts.clear(); - attributs = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, - attributs, "", getLLVMModule()); + attributs = new GlobalVariable(*getLLVMModule(), ATy, true, + GlobalValue::InternalLinkage, + attributs, ""); attributs = ConstantExpr::getCast(Instruction::BitCast, attributs, JnjvmModule::AttributType); MethodElts.push_back(attributs); } else { - MethodElts.push_back(Constant::getNullValue(JnjvmModule::AttributType)); + MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::AttributType)); } // nbAttributs @@ -868,7 +888,7 @@ // enveloppes // already allocated by the JIT, don't reallocate them. - MethodElts.push_back(Constant::getNullValue(JnjvmModule::EnveloppeType)); + MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::EnveloppeType)); // nbEnveloppes // 0 because we're not allocating here. @@ -888,7 +908,7 @@ // code if (isAbstract(method.access)) { - MethodElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); } else { LLVMMethodInfo* LMI = getMethodInfo(&method); Function* func = LMI->getMethod(); @@ -900,7 +920,7 @@ MethodElts.push_back(ConstantInt::get(Type::Int32Ty, method.offset)); //JInfo - MethodElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); return ConstantStruct::get(STy, MethodElts); } @@ -945,6 +965,7 @@ Constant* JavaAOTCompiler::CreateConstantFromClass(Class* cl) { const StructType* STy = dyn_cast(JnjvmModule::JavaClassType->getContainedType(0)); + Module& Mod = *getLLVMModule(); std::vector ClassElts; std::vector TempElts; @@ -971,7 +992,7 @@ ClassElts.push_back(ConstantArray::get(ATy, CStr, 1)); // thinlock - ClassElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); if (cl->nbVirtualFields + cl->nbStaticFields) { ATy = ArrayType::get(JnjvmModule::JavaFieldType->getContainedType(0), @@ -1001,12 +1022,13 @@ fields = ConstantArray::get(ATy, TempElts); TempElts.clear(); - fields = new GlobalVariable(ATy, false, GlobalValue::InternalLinkage, - fields, "", getLLVMModule()); + fields = new GlobalVariable(*getLLVMModule(), ATy, false, + GlobalValue::InternalLinkage, + fields, ""); fields = ConstantExpr::getCast(Instruction::BitCast, fields, JnjvmModule::JavaFieldType); } else { - fields = Constant::getNullValue(JnjvmModule::JavaFieldType); + fields = Mod.getContext().getNullValue(JnjvmModule::JavaFieldType); } // virtualFields @@ -1020,7 +1042,7 @@ // staticFields // Output null, getLLVMModule() will be set in the initializer. Otherwise, the // assembly emitter of LLVM will try to align the data. - ClassElts.push_back(Constant::getNullValue(JnjvmModule::JavaFieldType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaFieldType)); // nbStaticFields ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticFields)); @@ -1047,14 +1069,14 @@ if (cl->nbVirtualMethods + cl->nbStaticMethods) { methods = ConstantArray::get(ATy, TempElts); TempElts.clear(); - GlobalVariable* GV = new GlobalVariable(ATy, false, + GlobalVariable* GV = new GlobalVariable(*getLLVMModule(), ATy, false, GlobalValue::InternalLinkage, - methods, "", getLLVMModule()); + methods, ""); virtualMethods.insert(std::make_pair(cl, GV)); methods = ConstantExpr::getCast(Instruction::BitCast, GV, JnjvmModule::JavaMethodType); } else { - methods = Constant::getNullValue(JnjvmModule::JavaMethodType); + methods = Mod.getContext().getNullValue(JnjvmModule::JavaMethodType); } // virtualMethods @@ -1067,19 +1089,19 @@ // staticMethods // Output null, getLLVMModule() will be set in the initializer. - ClassElts.push_back(Constant::getNullValue(JnjvmModule::JavaMethodType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaMethodType)); // nbStaticMethods ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticMethods)); // ownerClass - ClassElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); // bytes - ClassElts.push_back(Constant::getNullValue(JnjvmModule::JavaArrayUInt8Type)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaArrayUInt8Type)); // ctpInfo - ClassElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); // attributs if (cl->nbAttributs) { @@ -1092,13 +1114,14 @@ Constant* attributs = ConstantArray::get(ATy, TempElts); TempElts.clear(); - attributs = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, - attributs, "", getLLVMModule()); + attributs = new GlobalVariable(*getLLVMModule(), ATy, true, + GlobalValue::InternalLinkage, + attributs, ""); attributs = ConstantExpr::getCast(Instruction::BitCast, attributs, JnjvmModule::AttributType); ClassElts.push_back(attributs); } else { - ClassElts.push_back(Constant::getNullValue(JnjvmModule::AttributType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::AttributType)); } // nbAttributs @@ -1113,15 +1136,16 @@ const llvm::Type* TempTy = JnjvmModule::JavaClassType; ATy = ArrayType::get(TempTy, cl->nbInnerClasses); Constant* innerClasses = ConstantArray::get(ATy, TempElts); - innerClasses = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, - innerClasses, "", getLLVMModule()); + innerClasses = new GlobalVariable(*getLLVMModule(), ATy, true, + GlobalValue::InternalLinkage, + innerClasses, ""); innerClasses = ConstantExpr::getCast(Instruction::BitCast, innerClasses, PointerType::getUnqual(TempTy)); ClassElts.push_back(innerClasses); } else { const Type* Ty = PointerType::getUnqual(JnjvmModule::JavaClassType); - ClassElts.push_back(Constant::getNullValue(Ty)); + ClassElts.push_back(Mod.getContext().getNullValue(Ty)); } // nbInnerClasses @@ -1131,7 +1155,7 @@ if (cl->outerClass) { ClassElts.push_back(getNativeClass(cl->outerClass)); } else { - ClassElts.push_back(Constant::getNullValue(JnjvmModule::JavaClassType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaClassType)); } // innerAccess @@ -1150,13 +1174,14 @@ ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->staticSize)); // JInfo - ClassElts.push_back(Constant::getNullValue(JnjvmModule::ptrType)); + ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); return ConstantStruct::get(STy, ClassElts); } template Constant* JavaAOTCompiler::CreateConstantFromArray(const T* val, const Type* Ty) { + Module& Mod = *getLLVMModule(); std::vector Elemts; const ArrayType* ATy = ArrayType::get(Ty, val->size); Elemts.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); @@ -1180,7 +1205,7 @@ if (val->elements[i]) { Vals.push_back(getFinalObject((JavaObject*)(size_t)val->elements[i])); } else { - Vals.push_back(Constant::getNullValue(JnjvmModule::JavaObjectType)); + Vals.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaObjectType)); } } } @@ -1218,9 +1243,10 @@ utf8_iterator I = utf8s.find(val); if (I == End) { Constant* C = CreateConstantFromUTF8(val); - GlobalVariable* varGV = new GlobalVariable(C->getType(), true, + Module& Mod = *getLLVMModule(); + GlobalVariable* varGV = new GlobalVariable(Mod, C->getType(), true, GlobalValue::InternalLinkage, - C, "", getLLVMModule()); + C, ""); Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, JnjvmModule::UTF8Type); @@ -1233,6 +1259,7 @@ } Constant* JavaAOTCompiler::CreateConstantFromVT(JavaVirtualTable* VT) { + Module& Mod = *getLLVMModule(); CommonClass* classDef = VT->cl; uint32 size = classDef->isClass() ? classDef->asClass()->virtualTableSize : JavaVirtualTable::getBaseSize(); @@ -1298,7 +1325,7 @@ Temp = ConstantExpr::getBitCast(Temp, PTy); Elemts.push_back(Temp); } else { - Elemts.push_back(Constant::getNullValue(PTy)); + Elemts.push_back(Mod.getContext().getNullValue(PTy)); } } @@ -1319,8 +1346,9 @@ Constant* display = ConstantArray::get(DTy, TempElmts); TempElmts.clear(); - display = new GlobalVariable(DTy, true, GlobalValue::InternalLinkage, - display, "", getLLVMModule()); + display = new GlobalVariable(*getLLVMModule(), DTy, true, + GlobalValue::InternalLinkage, + display, ""); display = ConstantExpr::getCast(Instruction::BitCast, display, PTy); @@ -1332,7 +1360,7 @@ Temp = ConstantExpr::getBitCast(Temp, PTy); Elemts.push_back(Temp); } else { - Elemts.push_back(Constant::getNullValue(PTy)); + Elemts.push_back(Mod.getContext().getNullValue(PTy)); } @@ -1342,7 +1370,7 @@ LLVMMethodInfo* LMI = getMethodInfo(meth); Function* F = LMI->getMethod(); if (isAbstract(meth->access)) { - Elemts.push_back(Constant::getNullValue(PTy)); + Elemts.push_back(Mod.getContext().getNullValue(PTy)); } else { Elemts.push_back(ConstantExpr::getCast(Instruction::BitCast, F, PTy)); } @@ -1437,9 +1465,10 @@ uint64_t(isolate)), ptrType); - varGV = new GlobalVariable(ptrType, !staticCompilation, + Module& Mod = *getLLVMModule(); + varGV = new GlobalVariable(Mod, ptrType, !staticCompilation, GlobalValue::ExternalLinkage, - cons, "", getLLVMModule()); + cons, ""); isolates.insert(std::make_pair(isolate, varGV)); } else { @@ -1864,8 +1893,8 @@ BasicBlock* currentBlock = BasicBlock::Create("enter", MainFunc); GlobalVariable* GvarArrayStr = new GlobalVariable( - ArrayType::get(Type::Int8Ty, strlen(name) + 1), true, - GlobalValue::InternalLinkage, 0, "mainClass", TheModule); + *TheModule, ArrayType::get(Type::Int8Ty, strlen(name) + 1), true, + GlobalValue::InternalLinkage, 0, "mainClass"); Constant* NameArray = ConstantArray::get(name, true); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Mon Jul 13 06:22:20 2009 @@ -122,7 +122,7 @@ cl2 = new BitCastInst(cl2, module->JavaCommonClassType, "", currentBlock); } - Value* test = new ICmpInst(ICmpInst::ICMP_EQ, cl, cl2, "", currentBlock); + Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, cl, cl2, ""); BasicBlock* trueBlock = createBasicBlock("true virtual invoke"); BasicBlock* falseBlock = createBasicBlock("false virtual invoke"); @@ -255,7 +255,7 @@ currentBlock = createBasicBlock("start"); CallInst::Create(module->ThrowExceptionFromJITFunction, "", currentBlock); if (returnType != Type::VoidTy) - ReturnInst::Create(Constant::getNullValue(returnType), currentBlock); + ReturnInst::Create(llvmContext->getNullValue(returnType), currentBlock); else ReturnInst::Create(currentBlock); @@ -283,13 +283,13 @@ "", currentBlock); Value* test = llvm::CallInst::Create(module->setjmpLLVM, buf, "", currentBlock); - test = new ICmpInst(ICmpInst::ICMP_EQ, test, module->constantZero, "", - currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, + module->constantZero, ""); llvm::BranchInst::Create(executeBlock, endBlock, test, currentBlock); if (returnType != Type::VoidTy) { endNode = llvm::PHINode::Create(returnType, "", endBlock); - endNode->addIncoming(Constant::getNullValue(returnType), + endNode->addIncoming(llvmContext->getNullValue(returnType), currentBlock); } @@ -347,8 +347,8 @@ const llvm::Type* Ty = test->getType(); PHINode* node = PHINode::Create(Ty, "", endBlock); node->addIncoming(test, currentBlock); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, test, - Constant::getNullValue(Ty), "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, + llvmContext->getNullValue(Ty), ""); BranchInst::Create(unloadedBlock, endBlock, cmp, currentBlock); currentBlock = unloadedBlock; @@ -423,8 +423,8 @@ atomicArgs.begin(), atomicArgs.end(), "", currentBlock); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, atomic, module->constantPtrZero, - "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, atomic, + module->constantPtrZero, ""); BasicBlock* OK = createBasicBlock("synchronize passed"); BasicBlock* NotOK = createBasicBlock("synchronize did not pass"); @@ -438,8 +438,8 @@ // The compare and swap did not pass, look if it's a thin lock Value* isThin = BinaryOperator::CreateAnd(atomic, module->constantFatMask, "", currentBlock); - cmp = new ICmpInst(ICmpInst::ICMP_EQ, isThin, module->constantPtrZero, "", - currentBlock); + cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, isThin, + module->constantPtrZero, ""); BranchInst::Create(ThinLockBB, FatLockBB, cmp, currentBlock); @@ -448,8 +448,8 @@ Value* idMask = ConstantInt::get(module->pointerSizeType, 0x7FFFFF00); Value* cptMask = ConstantInt::get(module->pointerSizeType, 0xFF); Value* IdInLock = BinaryOperator::CreateAnd(atomic, idMask, "", currentBlock); - Value* owner = new ICmpInst(ICmpInst::ICMP_EQ, threadId, IdInLock, "", - currentBlock); + Value* owner = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, threadId, + IdInLock, ""); BasicBlock* OwnerBB = createBasicBlock("owner thread"); @@ -458,7 +458,7 @@ // OK, we are the owner, now check if the counter will overflow. Value* count = BinaryOperator::CreateAnd(atomic, cptMask, "", currentBlock); - cmp = new ICmpInst(ICmpInst::ICMP_ULT, count, cptMask, "", currentBlock); + cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_ULT, count, cptMask, ""); BasicBlock* IncCounterBB = createBasicBlock("Increment counter"); BasicBlock* OverflowCounterBB = createBasicBlock("Overflow counter"); @@ -503,8 +503,8 @@ threadId = new PtrToIntInst(threadId, module->pointerSizeType, "", currentBlock); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, lock, threadId, "", - currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, lock, threadId, + ""); BasicBlock* EndUnlock = createBasicBlock("end unlock"); @@ -525,8 +525,8 @@ // Look if the lock is thin. Value* isThin = BinaryOperator::CreateAnd(lock, module->constantFatMask, "", currentBlock); - cmp = new ICmpInst(ICmpInst::ICMP_EQ, isThin, module->constantPtrZero, "", - currentBlock); + cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, isThin, + module->constantPtrZero, ""); BranchInst::Create(ThinLockBB, FatLockBB, cmp, currentBlock); @@ -859,7 +859,8 @@ Value* MyID = ConstantInt::get(module->pointerSizeType, loader->getIsolate()->IsolateID); - Cmp = new ICmpInst(ICmpInst::ICMP_EQ, OldIsolateID, MyID, "", currentBlock); + Cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, OldIsolateID, MyID, + ""); BasicBlock* EndBB = createBasicBlock("After service check"); BasicBlock* ServiceBB = createBasicBlock("Begin service call"); @@ -918,8 +919,8 @@ BinaryOperator::CreateAnd(FrameAddr, module->constantStackOverflowMask, "", currentBlock); - stackCheck = new ICmpInst(ICmpInst::ICMP_EQ, stackCheck, - module->constantPtrZero, "", currentBlock); + stackCheck = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, stackCheck, + module->constantPtrZero, ""); BasicBlock* stackOverflow = createBasicBlock("stack overflow"); BasicBlock* noStackOverflow = createBasicBlock("no stack overflow"); BranchInst::Create(stackOverflow, noStackOverflow, stackCheck, @@ -942,11 +943,11 @@ if (isa(I)) { I->eraseFromParent(); BranchInst::Create(endBlock, currentBlock); - endNode->addIncoming(Constant::getNullValue(returnType), + endNode->addIncoming(llvmContext->getNullValue(returnType), currentBlock); } else if (InvokeInst* II = dyn_cast(I)) { II->setNormalDest(endBlock); - endNode->addIncoming(Constant::getNullValue(returnType), + endNode->addIncoming(llvmContext->getNullValue(returnType), currentBlock); } @@ -1019,11 +1020,11 @@ Value* zero = module->constantZero; Value* minus = module->constantMinusOne; - Value* c = new FCmpInst(FCmpInst::FCMP_UGT, val1, val2, "", currentBlock); + Value* c = new FCmpInst(*currentBlock, FCmpInst::FCMP_UGT, val1, val2, ""); Value* r = llvm::SelectInst::Create(c, one, zero, "", currentBlock); - c = new FCmpInst(FCmpInst::FCMP_ULT, val1, val2, "", currentBlock); + c = new FCmpInst(*currentBlock, FCmpInst::FCMP_ULT, val1, val2, ""); r = llvm::SelectInst::Create(c, minus, r, "", currentBlock); - c = new FCmpInst(FCmpInst::FCMP_UNO, val1, val2, "", currentBlock); + c = new FCmpInst(*currentBlock, FCmpInst::FCMP_UNO, val1, val2, ""); r = llvm::SelectInst::Create(c, l ? one : minus, r, "", currentBlock); push(r, false); @@ -1100,8 +1101,7 @@ if (TheCompiler->hasExceptionsEnabled()) { Constant* zero = module->JavaObjectNullConstant; - Value* test = new ICmpInst(ICmpInst::ICMP_EQ, obj, zero, "", - currentBlock); + Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, obj, zero, ""); BasicBlock* exit = createBasicBlock("verifyNullExit"); BasicBlock* cont = createBasicBlock("verifyNullCont"); @@ -1125,8 +1125,8 @@ if (TheCompiler->hasExceptionsEnabled()) { Value* size = arraySize(obj); - Value* cmp = new ICmpInst(ICmpInst::ICMP_ULT, index, size, "", - currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_ULT, index, size, + ""); BasicBlock* ifTrue = createBasicBlock("true verifyAndComputePtr"); BasicBlock* ifFalse = createBasicBlock("false verifyAndComputePtr"); @@ -1244,8 +1244,8 @@ BinaryOperator::Create(Instruction::Sub, const_int32_9, args[0], "tmpneg", currentBlock); ICmpInst* int1_abscond = - new ICmpInst(ICmpInst::ICMP_SGT, args[0], const_int32_10, "abscond", - currentBlock); + new ICmpInst(*currentBlock, ICmpInst::ICMP_SGT, args[0], const_int32_10, + "abscond"); return llvm::SelectInst::Create(int1_abscond, args[0], int32_tmpneg, "abs", currentBlock); } else if (Ty == Type::Int64Ty) { @@ -1256,9 +1256,8 @@ BinaryOperator::Create(Instruction::Sub, const_int64_9, args[0], "tmpneg", currentBlock); - ICmpInst* int1_abscond = new ICmpInst(ICmpInst::ICMP_SGT, args[0], - const_int64_10, "abscond", - currentBlock); + ICmpInst* int1_abscond = new ICmpInst(*currentBlock, ICmpInst::ICMP_SGT, + args[0], const_int64_10, "abscond"); return llvm::SelectInst::Create(int1_abscond, args[0], int64_tmpneg, "abs", currentBlock); @@ -1391,12 +1390,12 @@ #if defined(ISOLATE_SHARING) const Type* Ty = module->ConstantPoolType; - Constant* Nil = Constant::getNullValue(Ty); + Constant* Nil = llvmContext->getNullValue(Ty); GlobalVariable* GV = new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage, Nil, "", module); Value* res = new LoadInst(GV, "", false, currentBlock); - Value* test = new ICmpInst(ICmpInst::ICMP_EQ, res, Nil, "", currentBlock); + Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, res, Nil, ""); BasicBlock* trueCl = createBasicBlock("UserCtp OK"); BasicBlock* falseCl = createBasicBlock("UserCtp Not OK"); @@ -1943,7 +1942,8 @@ currentBlock); Value* lastCible = new LoadInst(lastCiblePtr, "", currentBlock); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, VT, lastCible, "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, VT, lastCible, + ""); BasicBlock* ifTrue = createBasicBlock("cache ok"); BasicBlock* ifFalse = createBasicBlock("cache not ok"); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Mon Jul 13 06:22:20 2009 @@ -16,6 +16,7 @@ #include "llvm/BasicBlock.h" #include "llvm/Function.h" #include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" #include "llvm/Type.h" #include "llvm/Value.h" @@ -62,6 +63,7 @@ TheCompiler = C; module = TheCompiler->getIntrinsics(); llvmFunction = func; + llvmContext = func->getContext(); inlining = false; callsStackWalker = false; endNode = 0; @@ -83,6 +85,9 @@ /// llvmFunction - The LLVM representation of the method. llvm::Function* llvmFunction; + + /// llvmContext - The current LLVM context of compilation. + llvm::LLVMContext* llvmContext; /// module - The LLVM module where lives the compiling LLVM function. JnjvmModule* module; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Mon Jul 13 06:22:20 2009 @@ -660,9 +660,8 @@ if (TheCompiler->hasExceptionsEnabled()) { - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, val, - module->JavaObjectNullConstant, - "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val, + module->JavaObjectNullConstant, ""); BasicBlock* endBlock = createBasicBlock("end array store check"); BasicBlock* checkBlock = createBasicBlock("array store check"); @@ -935,9 +934,8 @@ Value* val2 = popAsInt(); Value* val1 = popAsInt(); if (TheCompiler->hasExceptionsEnabled()) { - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, val2, - module->constantZero, - "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val2, + module->constantZero, ""); BasicBlock* ifFalse = createBasicBlock("non null div"); BasicBlock* ifTrue = createBasicBlock("null div"); @@ -957,9 +955,8 @@ pop(); llvm::Value* val1 = pop(); if (TheCompiler->hasExceptionsEnabled()) { - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, val2, - module->constantLongZero, - "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val2, + module->constantLongZero, ""); BasicBlock* ifFalse = createBasicBlock("non null div"); BasicBlock* ifTrue = createBasicBlock("null div"); @@ -1226,8 +1223,8 @@ case F2I : { llvm::Value* val = pop(); - llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", - currentBlock); + llvm::Value* test = new FCmpInst(*currentBlock, FCmpInst::FCMP_ONE, + val, val, ""); BasicBlock* res = createBasicBlock("F2I"); PHINode* node = PHINode::Create(llvm::Type::Int32Ty, "", res); @@ -1238,9 +1235,8 @@ currentBlock = cont; - test = new FCmpInst(FCmpInst::FCMP_OGE, val, - module->constantMaxIntFloat, - "", currentBlock); + test = new FCmpInst(*currentBlock, FCmpInst::FCMP_OGE, val, + module->constantMaxIntFloat, ""); cont = createBasicBlock("F2I"); @@ -1250,9 +1246,8 @@ currentBlock = cont; - test = new FCmpInst(FCmpInst::FCMP_OLE, val, - module->constantMinIntFloat, - "", currentBlock); + test = new FCmpInst(*currentBlock, FCmpInst::FCMP_OLE, val, + module->constantMinIntFloat, ""); cont = createBasicBlock("F2I"); @@ -1274,8 +1269,8 @@ case F2L : { llvm::Value* val = pop(); - llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", - currentBlock); + llvm::Value* test = new FCmpInst(*currentBlock, FCmpInst::FCMP_ONE, + val, val, ""); BasicBlock* res = createBasicBlock("F2L"); PHINode* node = PHINode::Create(llvm::Type::Int64Ty, "", res); @@ -1286,9 +1281,8 @@ currentBlock = cont; - test = new FCmpInst(FCmpInst::FCMP_OGE, val, - module->constantMaxLongFloat, - "", currentBlock); + test = new FCmpInst(*currentBlock, FCmpInst::FCMP_OGE, val, + module->constantMaxLongFloat, ""); cont = createBasicBlock("F2L"); @@ -1297,8 +1291,8 @@ currentBlock = cont; - test = new FCmpInst(FCmpInst::FCMP_OLE, val, - module->constantMinLongFloat, "", currentBlock); + test = new FCmpInst(*currentBlock, FCmpInst::FCMP_OLE, val, + module->constantMinLongFloat, ""); cont = createBasicBlock("F2L"); @@ -1328,8 +1322,8 @@ case D2I : { pop(); // remove the 0 on the stack llvm::Value* val = pop(); - llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", - currentBlock); + llvm::Value* test = new FCmpInst(*currentBlock, FCmpInst::FCMP_ONE, + val, val, ""); BasicBlock* res = createBasicBlock("D2I"); PHINode* node = PHINode::Create(llvm::Type::Int32Ty, "", res); @@ -1340,9 +1334,8 @@ currentBlock = cont; - test = new FCmpInst(FCmpInst::FCMP_OGE, val, - module->constantMaxIntDouble, - "", currentBlock); + test = new FCmpInst(*currentBlock, FCmpInst::FCMP_OGE, val, + module->constantMaxIntDouble, ""); cont = createBasicBlock("D2I"); @@ -1351,9 +1344,8 @@ currentBlock = cont; - test = new FCmpInst(FCmpInst::FCMP_OLE, val, - module->constantMinIntDouble, - "", currentBlock); + test = new FCmpInst(*currentBlock, FCmpInst::FCMP_OLE, val, + module->constantMinIntDouble, ""); cont = createBasicBlock("D2I"); @@ -1377,8 +1369,8 @@ case D2L : { pop(); // remove the 0 on the stack llvm::Value* val = pop(); - llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", - currentBlock); + llvm::Value* test = new FCmpInst(*currentBlock, FCmpInst::FCMP_ONE, + val, val, ""); BasicBlock* res = createBasicBlock("D2L"); PHINode* node = PHINode::Create(llvm::Type::Int64Ty, "", res); @@ -1389,9 +1381,8 @@ currentBlock = cont; - test = new FCmpInst(FCmpInst::FCMP_OGE, val, - module->constantMaxLongDouble, - "", currentBlock); + test = new FCmpInst(*currentBlock, FCmpInst::FCMP_OGE, val, + module->constantMaxLongDouble, ""); cont = createBasicBlock("D2L"); @@ -1401,8 +1392,8 @@ currentBlock = cont; test = - new FCmpInst(FCmpInst::FCMP_OLE, val, module->constantMinLongDouble, - "", currentBlock); + new FCmpInst(*currentBlock, FCmpInst::FCMP_OLE, val, + module->constantMinLongDouble, ""); cont = createBasicBlock("D2L"); @@ -1465,8 +1456,8 @@ pop(); llvm::Value* val1 = pop(); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val1, + val2, ""); BasicBlock* cont = createBasicBlock("LCMP"); BasicBlock* res = createBasicBlock("LCMP"); @@ -1476,7 +1467,7 @@ BranchInst::Create(res, cont, test, currentBlock); currentBlock = cont; - test = new ICmpInst(ICmpInst::ICMP_SLT, val1, val2, "", currentBlock); + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SLT, val1, val2, ""); node->addIncoming(module->constantMinusOne, currentBlock); cont = createBasicBlock("LCMP"); @@ -1530,9 +1521,9 @@ Value* op = pop(); const Type* type = op->getType(); - Constant* val = Constant::getNullValue(type); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, op, val, "", - currentBlock); + Constant* val = llvmContext->getNullValue(type); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, op, + val, ""); BasicBlock* ifFalse = createBasicBlock("false IFEQ"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1545,9 +1536,9 @@ Value* op = pop(); const Type* type = op->getType(); - Constant* val = Constant::getNullValue(type); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, op, val, "", - currentBlock); + Constant* val = llvmContext->getNullValue(type); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, op, + val, ""); BasicBlock* ifFalse = createBasicBlock("false IFNE"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1559,9 +1550,9 @@ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; Value* op = pop(); const Type* type = op->getType(); - Constant* val = Constant::getNullValue(type); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLT, op, val, "", - currentBlock); + Constant* val = llvmContext->getNullValue(type); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SLT, op, + val, ""); BasicBlock* ifFalse = createBasicBlock("false IFLT"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1573,9 +1564,9 @@ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; Value* op = pop(); const Type* type = op->getType(); - Constant* val = Constant::getNullValue(type); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGE, op, val, "", - currentBlock); + Constant* val = llvmContext->getNullValue(type); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SGE, op, + val, ""); BasicBlock* ifFalse = createBasicBlock("false IFGE"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1587,9 +1578,9 @@ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; Value* op = pop(); const Type* type = op->getType(); - Constant* val = Constant::getNullValue(type); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGT, op, val, "", - currentBlock); + Constant* val = llvmContext->getNullValue(type); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SGT, op, + val, ""); BasicBlock* ifFalse = createBasicBlock("false IFGT"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1601,9 +1592,9 @@ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; Value* op = pop(); const Type* type = op->getType(); - Constant* val = Constant::getNullValue(type); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLE, op, val, "", - currentBlock); + Constant* val = llvmContext->getNullValue(type); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SLE, op, + val, ""); BasicBlock* ifFalse = createBasicBlock("false IFLE"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1615,8 +1606,8 @@ Value *val1 = popAsInt(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val1, + val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_ICMPEQ"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1628,8 +1619,8 @@ Value *val1 = popAsInt(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, val1, + val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_ICMPNE"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1641,8 +1632,8 @@ Value *val1 = popAsInt(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLT, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SLT, + val1, val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_IFCMPLT"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1654,8 +1645,8 @@ Value *val1 = popAsInt(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGE, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SGE, + val1, val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_ICMPGE"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1667,8 +1658,8 @@ Value *val1 = popAsInt(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGT, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SGT, + val1, val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_ICMPGT"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1680,8 +1671,8 @@ Value *val1 = popAsInt(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLE, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_SLE, + val1, val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_ICMPLE"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1693,8 +1684,8 @@ Value *val1 = pop(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, + val1, val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_ACMPEQ"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1706,8 +1697,8 @@ Value *val1 = pop(); uint32 tmp = i; BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val1, val2, "", - currentBlock); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, + val1, val2, ""); BasicBlock* ifFalse = createBasicBlock("false IF_ACMPNE"); branch(test, ifTrue, ifFalse, currentBlock); currentBlock = ifFalse; @@ -1763,9 +1754,8 @@ const llvm::Type* type = index->getType(); for (sint32 cur = low; cur < high; ++cur) { - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, - ConstantInt::get(type, cur), index, - "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, + ConstantInt::get(type, cur), index, ""); BasicBlock* falseBlock = createBasicBlock("continue tableswitch"); branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock); @@ -1796,7 +1786,8 @@ } for (uint32 cur = 0; cur < nbs; ++cur) { Value* val = ConstantInt::get(Type::Int32Ty, readU4(bytecodes, i)); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, val, key, "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val, key, + ""); BasicBlock* falseBlock = createBasicBlock("continue lookupswitch"); branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock); @@ -1955,7 +1946,7 @@ } else { const llvm::Type* Ty = PointerType::getUnqual(module->JavaClassArrayType); - Value* args[2]= { valCl, Constant::getNullValue(Ty) }; + Value* args[2]= { valCl, llvmContext->getNullValue(Ty) }; valCl = CallInst::Create(module->GetArrayClassFunction, args, args + 2, "", currentBlock); TheVT = CallInst::Create(module->GetVTFromClassArrayFunction, valCl, "", @@ -1967,8 +1958,8 @@ Value* arg1 = popAsInt(); if (TheCompiler->hasExceptionsEnabled()) { - Value* cmp = new ICmpInst(ICmpInst::ICMP_SLT, arg1, - module->constantZero, "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_SLT, arg1, + module->constantZero, ""); BasicBlock* BB1 = createBasicBlock(""); BasicBlock* BB2 = createBasicBlock(""); @@ -1978,9 +1969,8 @@ throwException(module->NegativeArraySizeExceptionFunction, arg1); currentBlock = BB2; - cmp = new ICmpInst(ICmpInst::ICMP_SGT, arg1, - module->MaxArraySizeConstant, - "", currentBlock); + cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_SGT, arg1, + module->MaxArraySizeConstant, ""); BB1 = createBasicBlock(""); BB2 = createBasicBlock(""); @@ -2046,9 +2036,8 @@ Value* clVar = getResolvedCommonClass(index, true, &cl); Value* obj = top(); Value* args[2] = { obj, clVar }; - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj, - module->JavaObjectNullConstant, - "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, obj, + module->JavaObjectNullConstant, ""); BasicBlock* endBlock = createBasicBlock("end type compare"); PHINode* node = PHINode::Create(Type::Int1Ty, "", endBlock); @@ -2101,8 +2090,8 @@ displayArgs, displayArgs + 2, "", currentBlock); - res = new ICmpInst(ICmpInst::ICMP_EQ, VTInDisplay, TheVT, "", - currentBlock); + res = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, VTInDisplay, + TheVT, ""); } } else { res = CallInst::Create(module->IsAssignableFromFunction, @@ -2170,9 +2159,9 @@ case IFNULL : { uint32 tmp = i; llvm::Value* val = pop(); - Constant* nil = Constant::getNullValue(val->getType()); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val, nil, "", - currentBlock); + Constant* nil = llvmContext->getNullValue(val->getType()); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val, + nil, ""); BasicBlock* ifFalse = createBasicBlock("true IFNULL"); BasicBlock* ifTrue = opcodeInfos[readS2(bytecodes, i) + tmp].newBlock; branch(test, ifTrue, ifFalse, currentBlock); @@ -2183,9 +2172,9 @@ case IFNONNULL : { uint32 tmp = i; llvm::Value* val = pop(); - Constant* nil = Constant::getNullValue(val->getType()); - llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val, nil, "", - currentBlock); + Constant* nil = llvmContext->getNullValue(val->getType()); + llvm::Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, val, + nil, ""); BasicBlock* ifFalse = createBasicBlock("false IFNONNULL"); BasicBlock* ifTrue = opcodeInfos[readS2(bytecodes, i) + tmp].newBlock; branch(test, ifTrue, ifFalse, currentBlock); Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Mon Jul 13 06:22:20 2009 @@ -176,7 +176,8 @@ JavaThreadType = PointerType::getUnqual(module->getTypeByName("JavaThread")); - JavaObjectNullConstant = Constant::getNullValue(JnjvmModule::JavaObjectType); + JavaObjectNullConstant = + module->getContext().getNullValue(JnjvmModule::JavaObjectType); MaxArraySizeConstant = ConstantInt::get(Type::Int32Ty, JavaArray::MaxArraySize); JavaArraySizeConstant = Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Mon Jul 13 06:22:20 2009 @@ -296,8 +296,8 @@ BasicBlock* NBB = II->getParent()->splitBasicBlock(II); I->getParent()->getTerminator()->eraseFromParent(); Value* Del = getDelegatee(module, Call.getArgument(0), CI); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, Del, - module->JavaObjectNullConstant, "", CI); + Value* cmp = new ICmpInst(CI, ICmpInst::ICMP_EQ, Del, + module->JavaObjectNullConstant, ""); BasicBlock* NoDelegatee = BasicBlock::Create("No delegatee", &F); BasicBlock* DelegateeOK = BasicBlock::Create("Delegatee OK", &F); @@ -414,8 +414,8 @@ #endif Value* arg1 = GetElementPtrInst::Create(CTP, indexes, "", CI); arg1 = new LoadInst(arg1, "", false, CI); - Value* test = new ICmpInst(ICmpInst::ICMP_EQ, arg1, - mvm::MvmModule::constantPtrNull, "", CI); + Value* test = new ICmpInst(CI, ICmpInst::ICMP_EQ, arg1, + mvm::MvmModule::constantPtrNull, ""); BasicBlock* trueCl = BasicBlock::Create("Ctp OK", &F); BasicBlock* falseCl = BasicBlock::Create("Ctp Not OK", &F); @@ -471,22 +471,22 @@ } else if (V == module->GetArrayClassFunction) { const llvm::Type* Ty = PointerType::getUnqual(module->JavaCommonClassType); - Constant* nullValue = Constant::getNullValue(Ty); + Constant* nullValue = F.getContext()->getNullValue(Ty); // Check if we have already proceed this call. if (Call.getArgument(1) == nullValue) { BasicBlock* NBB = II->getParent()->splitBasicBlock(II); I->getParent()->getTerminator()->eraseFromParent(); Constant* init = - Constant::getNullValue(module->JavaClassArrayType); + F.getContext()->getNullValue(module->JavaClassArrayType); GlobalVariable* GV = - new GlobalVariable(module->JavaClassArrayType, false, - GlobalValue::ExternalLinkage, - init, "", TheCompiler->getLLVMModule()); + new GlobalVariable(*(F.getParent()), module->JavaClassArrayType, + false, GlobalValue::ExternalLinkage, + init, ""); Value* LoadedGV = new LoadInst(GV, "", CI); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, LoadedGV, init, - "", CI); + Value* cmp = new ICmpInst(CI, ICmpInst::ICMP_EQ, LoadedGV, init, + ""); BasicBlock* OKBlock = BasicBlock::Create("", &F); BasicBlock* NotOKBlock = BasicBlock::Create("", &F); @@ -548,7 +548,7 @@ CurVT = new LoadInst(CurVT, "", false, CI); CurVT = new BitCastInst(CurVT, module->VTType, "", CI); - Value* res = new ICmpInst(ICmpInst::ICMP_EQ, CurVT, VT2, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, CurVT, VT2, ""); node->addIncoming(ConstantInt::getTrue(), CI->getParent()); BranchInst::Create(CurEndBlock, FailedBlock, res, CI); @@ -599,8 +599,8 @@ GetElementPtrInst::Create(VT1, indices, indices + 2, "", CI); CachePtr = new BitCastInst(CachePtr, Ty, "", CI); Value* Cache = new LoadInst(CachePtr, "", false, CI); - ICmpInst* cmp1 = new ICmpInst(ICmpInst::ICMP_EQ, Cache, VT2, "", CI); - ICmpInst* cmp2 = new ICmpInst(ICmpInst::ICMP_EQ, VT1, VT2, "", CI); + ICmpInst* cmp1 = new ICmpInst(CI, ICmpInst::ICMP_EQ, Cache, VT2, ""); + ICmpInst* cmp2 = new ICmpInst(CI, ICmpInst::ICMP_EQ, VT1, VT2, ""); BinaryOperator* Or = BinaryOperator::Create(Instruction::Or, cmp1, cmp2, "", CI); BranchInst::Create(BB9, Preheader, Or, CI); @@ -637,7 +637,7 @@ Instruction* CurVT = GetElementPtrInst::Create(secondaryTypes, resFwd, "", BB4); CurVT = new LoadInst(CurVT, "", false, BB4); - cmp1 = new ICmpInst(ICmpInst::ICMP_EQ, CurVT, VT2, "", BB4); + cmp1 = new ICmpInst(*BB4, ICmpInst::ICMP_EQ, CurVT, VT2, ""); BranchInst::Create(BB5, BB6, cmp1, BB4); // Increment i if the previous test failed @@ -656,7 +656,7 @@ resFwd->addIncoming(module->constantZero, Preheader); resFwd->addIncoming(IndVar, BB6); - cmp1 = new ICmpInst(ICmpInst::ICMP_SGT, Size, resFwd, "", BB7); + cmp1 = new ICmpInst(*BB7, ICmpInst::ICMP_SGT, Size, resFwd, ""); BranchInst::Create(BB4, BB9, cmp1, BB7); // Update the cache if the result is found. Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 13 06:22:20 2009 @@ -133,7 +133,7 @@ constantPtrOne = ConstantInt::get(pointerSizeType, 1); constantPtrZero = ConstantInt::get(pointerSizeType, 0); - constantPtrNull = Constant::getNullValue(ptrType); + constantPtrNull = globalContext->getNullValue(ptrType); constantPtrLogSize = ConstantInt::get(Type::Int32Ty, sizeof(void*) == 8 ? 3 : 2); arrayPtrType = PointerType::getUnqual(ArrayType::get(Type::Int8Ty, 0)); Modified: vmkit/trunk/lib/N3/Mono/MonoString.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/Mono/MonoString.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/N3/Mono/MonoString.cpp (original) +++ vmkit/trunk/lib/N3/Mono/MonoString.cpp Mon Jul 13 06:22:20 2009 @@ -53,10 +53,9 @@ Constant* cons = ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); - str->_llvmVar = new GlobalVariable(pty, true, + str->_llvmVar = new GlobalVariable(*(vm->getLLVMModule()), pty, true, GlobalValue::ExternalLinkage, - cons, "", - vm->getLLVMModule()); + cons, ""); } } return str->_llvmVar; Modified: vmkit/trunk/lib/N3/PNetLib/PNetString.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/PNetLib/PNetString.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/N3/PNetLib/PNetString.cpp (original) +++ vmkit/trunk/lib/N3/PNetLib/PNetString.cpp Mon Jul 13 06:22:20 2009 @@ -54,10 +54,9 @@ Constant* cons = ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); - str->_llvmVar = new GlobalVariable(pty, true, + str->_llvmVar = new GlobalVariable(*(vm->getLLVMModule()), pty, true, GlobalValue::ExternalLinkage, - cons, "", - vm->getLLVMModule()); + cons, ""); } } return str->_llvmVar; Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Mon Jul 13 06:22:20 2009 @@ -184,9 +184,9 @@ LoadInst* int32_tmp1019 = new LoadInst(ptr_tmp918, "tmp1019", false, label_entry); - ICmpInst* int1_tmp1221 = new ICmpInst(ICmpInst::ICMP_SGT, int32_tmp1019, - const_int32_8, "tmp1221", - label_entry); + ICmpInst* int1_tmp1221 = new ICmpInst(*label_entry, ICmpInst::ICMP_SGT, + int32_tmp1019, + const_int32_8, "tmp1221"); BranchInst::Create(label_bb, label_return, int1_tmp1221, label_entry); @@ -225,8 +225,8 @@ BinaryOperator::Create(Instruction::Add, int32_i_015_0, const_int32_9, "tmp6", label_bb); LoadInst* int32_tmp10 = new LoadInst(ptr_tmp918, "tmp10", false, label_bb); - ICmpInst* int1_tmp12 = new ICmpInst(ICmpInst::ICMP_SGT, int32_tmp10, - int32_tmp6, "tmp12", label_bb); + ICmpInst* int1_tmp12 = new ICmpInst(*label_bb, ICmpInst::ICMP_SGT, + int32_tmp10, int32_tmp6, "tmp12"); BranchInst::Create(label_bb, label_return, int1_tmp12, label_bb); // Block return (label_return) @@ -535,8 +535,8 @@ } else if (meth->classDef->nameSpace == N3::system && meth->classDef->name == N3::doubleName) { if (meth->name == N3::isNan) { - push(new FCmpInst(FCmpInst::FCMP_UNO, Args[0], - module->constantDoubleZero, "tmp1", currentBlock)); + push(new FCmpInst(*currentBlock, FCmpInst::FCMP_UNO, Args[0], + module->constantDoubleZero, "tmp1")); return; } else if (meth->name == N3::testInfinity) { BasicBlock* endBlock = createBasicBlock("end test infinity"); @@ -546,13 +546,11 @@ node->addIncoming(module->constantOne, currentBlock); node->addIncoming(module->constantMinusOne, minusInfinity); node->addIncoming(module->constantZero, noInfinity); - Value* val1 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], - module->constantDoubleInfinity, "tmp1", - currentBlock); + Value* val1 = new FCmpInst(*currentBlock, FCmpInst::FCMP_OEQ, Args[0], + module->constantDoubleInfinity, "tmp1"); BranchInst::Create(endBlock, minusInfinity, val1, currentBlock); - Value* val2 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], - module->constantDoubleMinusInfinity, "tmp1", - minusInfinity); + Value* val2 = new FCmpInst(*minusInfinity, FCmpInst::FCMP_OEQ, Args[0], + module->constantDoubleMinusInfinity, "tmp1"); BranchInst::Create(endBlock, noInfinity, val2, minusInfinity); BranchInst::Create(endBlock, noInfinity); currentBlock = endBlock; @@ -562,8 +560,8 @@ } else if (meth->classDef->nameSpace == N3::system && meth->classDef->name == N3::floatName) { if (meth->name == N3::isNan) { - push(new FCmpInst(FCmpInst::FCMP_UNO, Args[0], - module->constantFloatZero, "tmp1", currentBlock)); + push(new FCmpInst(*currentBlock, FCmpInst::FCMP_UNO, Args[0], + module->constantFloatZero, "tmp1")); return; } else if (meth->name == N3::testInfinity) { BasicBlock* endBlock = createBasicBlock("end test infinity"); @@ -573,13 +571,11 @@ node->addIncoming(module->constantOne, currentBlock); node->addIncoming(module->constantMinusOne, minusInfinity); node->addIncoming(module->constantZero, noInfinity); - Value* val1 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], - module->constantFloatInfinity, "tmp1", - currentBlock); + Value* val1 = new FCmpInst(*currentBlock, FCmpInst::FCMP_OEQ, Args[0], + module->constantFloatInfinity, "tmp1"); BranchInst::Create(endBlock, minusInfinity, val1, currentBlock); - Value* val2 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], - module->constantFloatMinusInfinity, "tmp1", - minusInfinity); + Value* val2 = new FCmpInst(*minusInfinity, FCmpInst::FCMP_OEQ, Args[0], + module->constantFloatMinusInfinity, "tmp1"); BranchInst::Create(endBlock, noInfinity, val2, minusInfinity); BranchInst::Create(endBlock, noInfinity); currentBlock = endBlock; @@ -748,7 +744,7 @@ } else { type = field->signature->naturalType; if (val == constantVMObjectNull) { - val = Constant::getNullValue(type); + val = llvmFunction->getContext()->getNullValue(type); } else if (type != valType) { val = changeType(val, type); } @@ -774,7 +770,7 @@ const Type* type = field->signature->naturalType; const Type* valType = val->getType(); if (val == constantVMObjectNull) { - val = Constant::getNullValue(type); + val = llvmFunction->getContext()->getNullValue(type); } else if (type != valType) { val = changeType(val, type); } @@ -783,9 +779,9 @@ void CLIJit::JITVerifyNull(Value* obj) { CLIJit* jit = this; - Constant* zero = Constant::getNullValue(obj->getType()); - Value* test = new ICmpInst(ICmpInst::ICMP_EQ, obj, zero, "", - jit->currentBlock); + Constant* zero = llvmFunction->getContext()->getNullValue(obj->getType()); + Value* test = new ICmpInst(*jit->currentBlock, ICmpInst::ICMP_EQ, obj, + zero, ""); BasicBlock* exit = jit->createBasicBlock("verifyNullExit"); BasicBlock* cont = jit->createBasicBlock("verifyNullCont"); @@ -819,8 +815,8 @@ if (true) { Value* size = arraySize(obj); - Value* cmp = new ICmpInst(ICmpInst::ICMP_SLT, index, size, "", - currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_SLT, index, + size, ""); BasicBlock* ifTrue = createBasicBlock("true verifyAndComputePtr"); BasicBlock* ifFalse = createBasicBlock("false verifyAndComputePtr"); @@ -1228,7 +1224,7 @@ cl->resolveType(false, false, genMethod); AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { - new StoreInst(Constant::getNullValue(cl->naturalType), alloc, false, + new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, currentBlock); } else { uint64 size = module->getTypeSize(cl->naturalType); @@ -1405,7 +1401,7 @@ cl->resolveType(false, false, genMethod); AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { - new StoreInst(Constant::getNullValue(cl->naturalType), alloc, false, + new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, currentBlock); } else { uint64 size = module->getTypeSize(cl->naturalType); @@ -1606,7 +1602,7 @@ - constantVMObjectNull = Constant::getNullValue(VMObject::llvmType); + constantVMObjectNull = module->getContext().getNullValue(VMObject::llvmType); } Constant* CLIJit::constantVMObjectNull; Modified: vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp Mon Jul 13 06:22:20 2009 @@ -369,10 +369,9 @@ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); - _llvmVar = new GlobalVariable(pty, true, + _llvmVar = new GlobalVariable(*(vm->getLLVMModule()), pty, true, GlobalValue::ExternalLinkage, - cons, "", - vm->getLLVMModule()); + cons, ""); } release(); @@ -389,10 +388,9 @@ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); - _llvmVar = new GlobalVariable(pty, true, + _llvmVar = new GlobalVariable(*(classDef->vm->getLLVMModule()), pty, true, GlobalValue::ExternalLinkage, - cons, "", - classDef->vm->getLLVMModule()); + cons, ""); } classDef->release(); } @@ -408,10 +406,9 @@ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); - _llvmVar = new GlobalVariable(pty, true, + _llvmVar = new GlobalVariable(*(classDef->vm->getLLVMModule()), pty, true, GlobalValue::ExternalLinkage, - cons, "", - classDef->vm->getLLVMModule()); + cons, ""); } classDef->release(); Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Mon Jul 13 06:22:20 2009 @@ -284,9 +284,9 @@ Value* test = 0; \ verifyType(val1, val2, currentBlock); \ if (val1->getType()->isFloatingPoint()) { \ - test = new FCmpInst(FCmpInst::cmpf, val1, val2, "", currentBlock); \ + test = new FCmpInst(*currentBlock, FCmpInst::cmpf, val1, val2, ""); \ } else { \ - test = new ICmpInst(ICmpInst::cmpi, val1, val2, "", currentBlock); \ + test = new ICmpInst(*currentBlock, ICmpInst::cmpi, val1, val2, ""); \ } \ BasicBlock* ifFalse = createBasicBlock("false BEQ"); \ branch(test, ifTrue, ifFalse, currentBlock); \ @@ -341,13 +341,13 @@ #define TEST(name, read, cmpf, cmpi, offset) case name : { \ uint32 tmp = i; \ Value* val2 = pop(); \ - Value* val1 = Constant::getNullValue(val2->getType()); \ + Value* val1 = llvmFunction->getContext()->getNullValue(val2->getType()); \ BasicBlock* ifTrue = opcodeInfos[tmp + offset + read(bytecodes, i)].newBlock; \ Value* test = 0; \ if (val1->getType()->isFloatingPoint()) { \ - test = new FCmpInst(FCmpInst::cmpf, val1, val2, "", currentBlock); \ + test = new FCmpInst(*currentBlock, FCmpInst::cmpf, val1, val2, ""); \ } else { \ - test = new ICmpInst(ICmpInst::cmpi, val1, val2, "", currentBlock); \ + test = new ICmpInst(*currentBlock, ICmpInst::cmpi, val1, val2, ""); \ } \ BasicBlock* ifFalse = createBasicBlock("false BR"); \ branch(test, ifTrue, ifFalse, currentBlock); \ @@ -1020,7 +1020,7 @@ case NEG : { Value* val = pop(); push(BinaryOperator::CreateSub( - Constant::getNullValue(val->getType()), + llvmFunction->getContext()->getNullValue(val->getType()), val, "", currentBlock)); break; } @@ -1334,9 +1334,8 @@ false, true, genClass, genMethod); Value* obj = new BitCastInst(pop(), VMObject::llvmType, "", currentBlock); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj, - CLIJit::constantVMObjectNull, - "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, obj, + CLIJit::constantVMObjectNull, ""); BasicBlock* ifTrue = createBasicBlock("null checkcast"); BasicBlock* ifFalse = createBasicBlock("non null checkcast"); @@ -1350,8 +1349,8 @@ Value* call = CallInst::Create(instanceOfLLVM, args.begin(), args.end(), "", ifFalse); - cmp = new ICmpInst(ICmpInst::ICMP_EQ, call, - module->constantZero, "", ifFalse); + cmp = new ICmpInst(*ifFalse, ICmpInst::ICMP_EQ, call, + module->constantZero, ""); BasicBlock* ex = createBasicBlock("false checkcast"); branch(cmp, ex, ifTrue, ifFalse); @@ -1383,10 +1382,9 @@ false, true, genClass, genMethod); Value* obj = pop(); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj, - Constant::getNullValue(obj->getType()), - "", currentBlock); - Constant* nullVirtual = Constant::getNullValue(dcl->virtualType); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, obj, + llvmFunction->getContext()->getNullValue(obj->getType()), ""); + Constant* nullVirtual = llvmFunction->getContext()->getNullValue(dcl->virtualType); BasicBlock* isInstEndBlock = createBasicBlock("end isinst"); @@ -1407,8 +1405,8 @@ Value* call = CallInst::Create(instanceOfLLVM, args.begin(), args.end(), "", ifFalse); - cmp = new ICmpInst(ICmpInst::ICMP_EQ, call, - module->constantZero, "", ifFalse); + cmp = new ICmpInst(*ifFalse, ICmpInst::ICMP_EQ, call, + module->constantZero, ""); BasicBlock* falseInst = createBasicBlock("false isinst"); BasicBlock* trueInst = createBasicBlock("true isinst"); @@ -1840,10 +1838,10 @@ Value* val1 = pop(); \ Value* test = 0; \ if (val1->getType()->isFloatingPoint()) { \ - test = new FCmpInst(FCmpInst::cmpf, val1, val2, "", currentBlock); \ + test = new FCmpInst(*currentBlock, FCmpInst::cmpf, val1, val2, ""); \ } else { \ convertValue(val2, val1->getType(), currentBlock); \ - test = new ICmpInst(ICmpInst::cmpi, val1, val2, "", currentBlock); \ + test = new ICmpInst(*currentBlock, ICmpInst::cmpi, val1, val2, ""); \ } \ push(test); \ break; \ Modified: vmkit/trunk/lib/N3/VMCore/VMCache.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMCache.cpp?rev=75462&r1=75461&r2=75462&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMCache.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMCache.cpp Mon Jul 13 06:22:20 2009 @@ -117,7 +117,7 @@ "", currentBlock); Value* lastCible = new LoadInst(lastCiblePtr, "", currentBlock); - Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, cl, lastCible, "", currentBlock); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, cl, lastCible, ""); BasicBlock* ifFalse = createBasicBlock("cache not ok"); BranchInst::Create(callBlock, ifFalse, cmp, currentBlock); From nicolas.geoffray at lip6.fr Mon Jul 13 06:23:48 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 13:23:48 -0000 Subject: [vmkit-commits] [vmkit] r75464 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907131323.n6DDNmVp011708@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 08:23:46 2009 New Revision: 75464 URL: http://llvm.org/viewvc/llvm-project?rev=75464&view=rev Log: Bugfix with UTF8Buffer. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75464&r1=75463&r2=75464&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 13 08:23:46 2009 @@ -64,10 +64,10 @@ Ty = JnjvmModule::JavaClassType->getContainedType(0); } - const char* val = UTF8Buffer(classDef->name).toCompileName()->cString(); GlobalVariable* varGV = new GlobalVariable(*getLLVMModule(), Ty, false, - GlobalValue::ExternalLinkage, 0, val); + GlobalValue::ExternalLinkage, 0, + UTF8Buffer(classDef->name).toCompileName()->cString()); nativeClasses.insert(std::make_pair(classDef, varGV)); @@ -95,10 +95,10 @@ const llvm::Type* Ty = JnjvmModule::JavaClassArrayType; Module& Mod = *getLLVMModule(); - const char* name = UTF8Buffer(classDef->name).toCompileName()->cString(); GlobalVariable* varGV = new GlobalVariable(Mod, Ty, false, GlobalValue::InternalLinkage, - Mod.getContext().getNullValue(Ty), name); + Mod.getContext().getNullValue(Ty), + UTF8Buffer(classDef->name).toCompileName()->cString()); arrayClasses.insert(std::make_pair(classDef->asArrayClass(), varGV)); return varGV; From nicolas.geoffray at lip6.fr Mon Jul 13 06:28:16 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 13:28:16 -0000 Subject: [vmkit-commits] [vmkit] r75465 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907131328.n6DDSGwf011854@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 08:28:15 2009 New Revision: 75465 URL: http://llvm.org/viewvc/llvm-project?rev=75465&view=rev Log: Put back the fact that the AOT owns the class, which may have been removed from the clinit-ialization process. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75465&r1=75464&r2=75465&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 13 08:28:15 2009 @@ -1788,6 +1788,7 @@ for (std::vector::iterator i = classes.begin(), e = classes.end(); i != e; ++i) { Class* cl = *i; + cl->setOwnerClass(JavaThread::get()); M->compileClass(cl); } From nicolas.geoffray at lip6.fr Mon Jul 13 08:28:05 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 15:28:05 -0000 Subject: [vmkit-commits] [vmkit] r75468 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaArray.h JavaClass.cpp Message-ID: <200907131528.n6DFS6re016728@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 10:28:05 2009 New Revision: 75468 URL: http://llvm.org/viewvc/llvm-project?rev=75468&view=rev Log: Replace '$', '<', and '>' during AOT. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h?rev=75468&r1=75467&r2=75468&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h Mon Jul 13 10:28:05 2009 @@ -184,6 +184,9 @@ } else if (buffer[i] == '[') { newBuffer[j++] = '_'; newBuffer[j++] = '3'; + } else if (buffer[i] == '$') { + newBuffer[j++] = '_'; + newBuffer[j++] = '4'; } else { newBuffer[j++] = buffer[i]; } Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=75468&r1=75467&r2=75468&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Mon Jul 13 10:28:05 2009 @@ -1110,10 +1110,27 @@ else if (cur == '_') { ptr[0] = '_'; ptr[1] = '1'; + ptr += 2; + } else if (cur == '<') { + ptr[0] = '_'; + ptr[1] = '0'; + ptr[2] = '0'; + ptr[3] = '0'; + ptr[4] = '3'; + ptr[5] = 'C'; + ptr += 6; + } else if (cur == '>') { + ptr[0] = '_'; + ptr[1] = '0'; + ptr[2] = '0'; + ptr[3] = '0'; + ptr[4] = '3'; + ptr[5] = 'E'; + ptr += 6; + } else { + ptr[0] = (uint8)cur; ++ptr; } - else ptr[0] = (uint8)cur; - ++ptr; } sint32 i = 0; From nicolas.geoffray at lip6.fr Mon Jul 13 10:09:00 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 13 Jul 2009 17:09:00 -0000 Subject: [vmkit-commits] [vmkit] r75474 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907131709.n6DH90w5023567@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 13 12:09:00 2009 New Revision: 75474 URL: http://llvm.org/viewvc/llvm-project?rev=75474&view=rev Log: Really set owner class. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75474&r1=75473&r2=75474&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 13 12:09:00 2009 @@ -1789,6 +1789,11 @@ i != e; ++i) { Class* cl = *i; cl->setOwnerClass(JavaThread::get()); + } + + for (std::vector::iterator i = classes.begin(), e = classes.end(); + i != e; ++i) { + Class* cl = *i; M->compileClass(cl); } From nicolas.geoffray at lip6.fr Wed Jul 15 03:57:30 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 15 Jul 2009 10:57:30 -0000 Subject: [vmkit-commits] [vmkit] r75771 - /vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Message-ID: <200907151057.n6FAvWVL009955@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 15 05:57:10 2009 New Revision: 75771 URL: http://llvm.org/viewvc/llvm-project?rev=75771&view=rev Log: Don't set the destructor in case of AOT. The compiler thinks there is a JavaMethod there. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=75771&r1=75770&r2=75771&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Wed Jul 15 05:57:10 2009 @@ -338,8 +338,10 @@ } void JavaVirtualTable::setNativeDestructor(uintptr_t ptr, const char* name) { - destructor = ptr; - operatorDelete = ptr; + if (!cl->classLoader->getCompiler()->isStaticCompiling()) { + destructor = ptr; + operatorDelete = ptr; + } } JavaMethod* Class::lookupInterfaceMethodDontThrow(const UTF8* name, From nicolas.geoffray at lip6.fr Wed Jul 15 06:31:36 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 15 Jul 2009 13:31:36 -0000 Subject: [vmkit-commits] [vmkit] r75784 - in /vmkit/trunk: lib/JnJVM/Compiler/ lib/Mvm/Compiler/ lib/N3/Mono/ lib/N3/VMCore/ tools/vmjc/ Message-ID: <200907151331.n6FDVc6F015854@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 15 08:31:22 2009 New Revision: 75784 URL: http://llvm.org/viewvc/llvm-project?rev=75784&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp vmkit/trunk/lib/N3/Mono/MonoString.cpp vmkit/trunk/lib/N3/VMCore/CLIJit.cpp vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp vmkit/trunk/lib/N3/VMCore/Opcodes.cpp vmkit/trunk/lib/N3/VMCore/VMCache.cpp vmkit/trunk/lib/N3/VMCore/VMClass.cpp vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc Wed Jul 15 08:31:22 2009 @@ -431,7 +431,7 @@ currentBlock); uint32 depth = cur->catchClass->virtualVT->depth; - Value* depthCl = ConstantInt::get(Type::Int32Ty, depth); + Value* depthCl = llvmContext->getConstantInt(Type::Int32Ty, depth); Value* cmp = 0; if (depth >= JavaVirtualTable::getDisplayLength()) { Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc Wed Jul 15 08:31:22 2009 @@ -426,7 +426,7 @@ Value* objCl = CallInst::Create(module->GetClassFunction, obj, "", currentBlock); - Value* depthCl = ConstantInt::get(Type::Int32Ty, cur->catchClass->depth); + Value* depthCl = llvmContext->getConstantInt(Type::Int32Ty, cur->catchClass->depth); Value* depthClObj = CallInst::Create(module->GetDepthFunction, objCl, "", currentBlock); @@ -529,7 +529,7 @@ cur->javaHandler); OldIsolateID = new LoadInst(IsolateIDPtr, "", cur->javaHandler); - Value* MyID = ConstantInt::get(module->pointerSizeType, + Value* MyID = llvmContext->getConstantInt(module->pointerSizeType, loader->getIsolate()->IsolateID); new StoreInst(MyID, IsolateIDPtr, cur->javaHandler); Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Wed Jul 15 08:31:22 2009 @@ -42,6 +42,10 @@ const TargetData* targetData = JnjvmModule::TheTargetData; const StructLayout* sl = 0; const StructType* structType = 0; + JavaLLVMCompiler* Mod = + (JavaLLVMCompiler*)classDef->classLoader->getCompiler(); + Module* LMod = Mod->getLLVMModule(); + LLVMContext& Context = LMod->getContext(); if (classDef->super) { LLVMClassInfo* CLI = JavaLLVMCompiler::getClassInfo(classDef->super); @@ -76,10 +80,8 @@ uint64 size = JnjvmModule::getTypeSize(structType); classDef->virtualSize = (uint32)size; - virtualSizeConstant = ConstantInt::get(Type::Int32Ty, size); + virtualSizeConstant = Context.getConstantInt(Type::Int32Ty, size); - JavaLLVMCompiler* Mod = - (JavaLLVMCompiler*)classDef->classLoader->getCompiler(); Mod->makeVT(classDef); } @@ -119,10 +121,15 @@ Value* LLVMClassInfo::getVirtualSize() { if (!virtualSizeConstant) { + JavaLLVMCompiler* Mod = + (JavaLLVMCompiler*)classDef->classLoader->getCompiler(); + Module* LMod = Mod->getLLVMModule(); + LLVMContext& Context = LMod->getContext(); + getVirtualType(); assert(classDef->virtualSize && "Zero size for a class?"); virtualSizeConstant = - ConstantInt::get(Type::Int32Ty, classDef->virtualSize); + Context.getConstantInt(Type::Int32Ty, classDef->virtualSize); } return virtualSizeConstant; } @@ -187,9 +194,12 @@ Constant* LLVMMethodInfo::getOffset() { if (!offsetConstant) { JnjvmClassLoader* JCL = methodDef->classDef->classLoader; - JavaCompiler* Mod = JCL->getCompiler(); + JavaLLVMCompiler* Mod = (JavaLLVMCompiler*)JCL->getCompiler(); + Module* LMod = Mod->getLLVMModule(); + LLVMContext& Context = LMod->getContext(); + Mod->resolveVirtualClass(methodDef->classDef); - offsetConstant = ConstantInt::get(Type::Int32Ty, methodDef->offset); + offsetConstant = Context.getConstantInt(Type::Int32Ty, methodDef->offset); } return offsetConstant; } @@ -197,14 +207,17 @@ Constant* LLVMFieldInfo::getOffset() { if (!offsetConstant) { JnjvmClassLoader* JCL = fieldDef->classDef->classLoader; - JavaCompiler* Mod = JCL->getCompiler(); + JavaLLVMCompiler* Mod = (JavaLLVMCompiler*)JCL->getCompiler(); + Module* LMod = Mod->getLLVMModule(); + LLVMContext& Context = LMod->getContext(); + if (isStatic(fieldDef->access)) { Mod->resolveStaticClass(fieldDef->classDef); } else { Mod->resolveVirtualClass(fieldDef->classDef); } - offsetConstant = ConstantInt::get(Type::Int32Ty, fieldDef->num); + offsetConstant = Context.getConstantInt(Type::Int32Ty, fieldDef->num); } return offsetConstant; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Wed Jul 15 08:31:22 2009 @@ -130,13 +130,14 @@ } Constant* JavaAOTCompiler::getMethodInClass(JavaMethod* meth) { + LLVMContext& Context = getLLVMModule()->getContext(); Class* cl = meth->classDef; Constant* MOffset = 0; Constant* Array = 0; method_iterator SI = virtualMethods.find(cl); for (uint32 i = 0; i < cl->nbVirtualMethods + cl->nbStaticMethods; ++i) { if (&cl->virtualMethods[i] == meth) { - MOffset = ConstantInt::get(Type::Int32Ty, i); + MOffset = Context.getConstantInt(Type::Int32Ty, i); break; } } @@ -282,7 +283,8 @@ varGV->setInitializer(CreateConstantFromJavaObject(obj)); return C; } else { - Constant* CI = ConstantInt::get(Type::Int64Ty, uint64_t(obj)); + LLVMContext& Context = getLLVMModule()->getContext(); + Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(obj)); CI = ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); finalObjects.insert(std::make_pair(obj, CI)); return CI; @@ -297,6 +299,7 @@ const Type* Ty = LCI->getStaticType(); const StructType* STy = dyn_cast(Ty->getContainedType(0)); Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); std::vector Elts; @@ -314,27 +317,27 @@ if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool() || prim->isByte()) { - ConstantInt* CI = ConstantInt::get(Type::Int8Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int8Ty, field.getInt8Field(obj)); Elts.push_back(CI); } else if (prim->isShort() || prim->isChar()) { - ConstantInt* CI = ConstantInt::get(Type::Int16Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int16Ty, field.getInt16Field(obj)); Elts.push_back(CI); } else if (prim->isInt()) { - ConstantInt* CI = ConstantInt::get(Type::Int32Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int32Ty, field.getInt32Field(obj)); Elts.push_back(CI); } else if (prim->isLong()) { - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, field.getLongField(obj)); Elts.push_back(CI); } else if (prim->isFloat()) { - Constant* CF = ConstantFP::get(Type::FloatTy, + Constant* CF = Context.getConstantFP(Type::FloatTy, field.getFloatField(obj)); Elts.push_back(CF); } else if (prim->isDouble()) { - Constant* CF = ConstantFP::get(Type::DoubleTy, + Constant* CF = Context.getConstantFP(Type::DoubleTy, field.getDoubleField(obj)); Elts.push_back(CF); } else { @@ -358,13 +361,13 @@ uint16 idx = reader.readU2(); if (type->isPrimitive()) { if (Ty == Type::Int64Ty) { - Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->LongAt(idx))); + Elts.push_back(Context.getConstantInt(Ty, (uint64)ctpInfo->LongAt(idx))); } else if (Ty == Type::DoubleTy) { - Elts.push_back(ConstantFP::get(Ty, ctpInfo->DoubleAt(idx))); + Elts.push_back(Context.getConstantFP(Ty, ctpInfo->DoubleAt(idx))); } else if (Ty == Type::FloatTy) { - Elts.push_back(ConstantFP::get(Ty, ctpInfo->FloatAt(idx))); + Elts.push_back(Context.getConstantFP(Ty, ctpInfo->FloatAt(idx))); } else { - Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->IntegerAt(idx))); + Elts.push_back(Context.getConstantInt(Ty, (uint64)ctpInfo->IntegerAt(idx))); } } else if (type->isReference()){ const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[idx]); @@ -485,12 +488,13 @@ dyn_cast(JnjvmModule::JavaObjectType->getContainedType(0)); std::vector Elmts; + LLVMContext& Context = getLLVMModule()->getContext(); // VT Elmts.push_back(getVirtualTable(cl->virtualVT)); // lock - Constant* L = ConstantInt::get(Type::Int64Ty, 0); + Constant* L = Context.getConstantInt(Type::Int64Ty, 0); Elmts.push_back(ConstantExpr::getIntToPtr(L, JnjvmModule::ptrType)); return ConstantStruct::get(STy, Elmts); @@ -529,6 +533,7 @@ Constant* JavaAOTCompiler::CreateConstantFromJavaObject(JavaObject* obj) { CommonClass* cl = obj->getClass(); Module& Mod = *getLLVMModule(); + LLVMContext& Context = getLLVMModule()->getContext(); if (cl->isArray()) { Classpath* upcalls = cl->classLoader->bootstrapLoader->upcalls; @@ -587,27 +592,27 @@ if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool() || prim->isByte()) { - ConstantInt* CI = ConstantInt::get(Type::Int8Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int8Ty, field.getInt8Field(obj)); TempElts.push_back(CI); } else if (prim->isShort() || prim->isChar()) { - ConstantInt* CI = ConstantInt::get(Type::Int16Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int16Ty, field.getInt16Field(obj)); TempElts.push_back(CI); } else if (prim->isInt()) { - ConstantInt* CI = ConstantInt::get(Type::Int32Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int32Ty, field.getInt32Field(obj)); TempElts.push_back(CI); } else if (prim->isLong()) { - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, field.getLongField(obj)); TempElts.push_back(CI); } else if (prim->isFloat()) { - Constant* CF = ConstantFP::get(Type::FloatTy, + Constant* CF = Context.getConstantFP(Type::FloatTy, field.getFloatField(obj)); TempElts.push_back(CF); } else if (prim->isDouble()) { - Constant* CF = ConstantFP::get(Type::DoubleTy, + Constant* CF = Context.getConstantFP(Type::DoubleTy, field.getDoubleField(obj)); TempElts.push_back(CF); } else { @@ -636,6 +641,7 @@ LLVMClassInfo* LCI = getClassInfo(cl); const StructType* STy = dyn_cast(LCI->getVirtualType()->getContainedType(0)); + LLVMContext& Context = getLLVMModule()->getContext(); std::vector Elmts; @@ -653,9 +659,9 @@ Array = ConstantExpr::getBitCast(varGV, JnjvmModule::JavaObjectType); Elmts.push_back(Array); - Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->count)); - Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->cachedHashCode)); - Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->offset)); + Elmts.push_back(Context.getConstantInt(Type::Int32Ty, str->count)); + Elmts.push_back(Context.getConstantInt(Type::Int32Ty, str->cachedHashCode)); + Elmts.push_back(Context.getConstantInt(Type::Int32Ty, str->offset)); return ConstantStruct::get(STy, Elmts); } @@ -664,12 +670,12 @@ Constant* JavaAOTCompiler::CreateConstantFromCacheNode(CacheNode* CN) { const StructType* STy = dyn_cast(JnjvmModule::CacheNodeType->getContainedType(0)); - Module& Mod = *getLLVMModule(); + LLVMContext& Context = getLLVMModule()->getContext(); std::vector Elmts; - Elmts.push_back(Mod.getContext().getNullValue(STy->getContainedType(0))); - Elmts.push_back(Mod.getContext().getNullValue(STy->getContainedType(1))); - Elmts.push_back(Mod.getContext().getNullValue(STy->getContainedType(2))); + Elmts.push_back(Context.getNullValue(STy->getContainedType(0))); + Elmts.push_back(Context.getNullValue(STy->getContainedType(1))); + Elmts.push_back(Context.getNullValue(STy->getContainedType(2))); Elmts.push_back(getEnveloppe(CN->enveloppe)); return ConstantStruct::get(STy, Elmts); @@ -703,6 +709,7 @@ Constant* JavaAOTCompiler::CreateConstantFromAttribut(Attribut& attribut) { const StructType* STy = dyn_cast(JnjvmModule::AttributType->getContainedType(0)); + LLVMContext& Context = getLLVMModule()->getContext(); std::vector Elmts; @@ -711,10 +718,10 @@ Elmts.push_back(getUTF8(attribut.name)); // start - Elmts.push_back(ConstantInt::get(Type::Int32Ty, attribut.start)); + Elmts.push_back(Context.getConstantInt(Type::Int32Ty, attribut.start)); // nbb - Elmts.push_back(ConstantInt::get(Type::Int32Ty, attribut.nbb)); + Elmts.push_back(Context.getConstantInt(Type::Int32Ty, attribut.nbb)); return ConstantStruct::get(STy, Elmts); } @@ -723,6 +730,7 @@ const StructType* STy = dyn_cast(JnjvmModule::JavaCommonClassType->getContainedType(0)); Module& Mod = *getLLVMModule(); + LLVMContext& Context = getLLVMModule()->getContext(); const llvm::Type* TempTy = 0; @@ -737,7 +745,7 @@ CommonClassElts.push_back(ConstantArray::get(ATy, TCM, 1)); // access - CommonClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->access)); + CommonClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->access)); // interfaces if (cl->nbInterfaces) { @@ -747,7 +755,7 @@ ATy = ArrayType::get(JnjvmModule::JavaClassType, cl->nbInterfaces); Constant* interfaces = ConstantArray::get(ATy, TempElmts); - interfaces = new GlobalVariable(*getLLVMModule(), ATy, true, + interfaces = new GlobalVariable(Mod, ATy, true, GlobalValue::InternalLinkage, interfaces, ""); interfaces = ConstantExpr::getCast(Instruction::BitCast, interfaces, @@ -756,11 +764,11 @@ CommonClassElts.push_back(interfaces); } else { const Type* Ty = PointerType::getUnqual(JnjvmModule::JavaClassType); - CommonClassElts.push_back(Mod.getContext().getNullValue(Ty)); + CommonClassElts.push_back(Context.getNullValue(Ty)); } // nbInterfaces - CommonClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbInterfaces)); + CommonClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbInterfaces)); // name CommonClassElts.push_back(getUTF8(cl->name)); @@ -793,6 +801,7 @@ const StructType* STy = dyn_cast(JnjvmModule::JavaFieldType->getContainedType(0)); Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); std::vector FieldElts; std::vector TempElts; @@ -801,7 +810,7 @@ FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); // access - FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.access)); + FieldElts.push_back(Context.getConstantInt(Type::Int16Ty, field.access)); // name FieldElts.push_back(getUTF8(field.name)); @@ -831,16 +840,16 @@ } // nbAttributs - FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.nbAttributs)); + FieldElts.push_back(Context.getConstantInt(Type::Int16Ty, field.nbAttributs)); // classDef FieldElts.push_back(getNativeClass(field.classDef)); // ptrOffset - FieldElts.push_back(ConstantInt::get(Type::Int32Ty, field.ptrOffset)); + FieldElts.push_back(Context.getConstantInt(Type::Int32Ty, field.ptrOffset)); // num - FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.num)); + FieldElts.push_back(Context.getConstantInt(Type::Int16Ty, field.num)); //JInfo FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); @@ -852,15 +861,16 @@ const StructType* STy = dyn_cast(JnjvmModule::JavaMethodType->getContainedType(0)); Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); std::vector MethodElts; std::vector TempElts; // signature - MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); + MethodElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); // access - MethodElts.push_back(ConstantInt::get(Type::Int16Ty, method.access)); + MethodElts.push_back(Context.getConstantInt(Type::Int16Ty, method.access)); // attributs if (method.nbAttributs) { @@ -872,7 +882,7 @@ Constant* attributs = ConstantArray::get(ATy, TempElts); TempElts.clear(); - attributs = new GlobalVariable(*getLLVMModule(), ATy, true, + attributs = new GlobalVariable(Mod, ATy, true, GlobalValue::InternalLinkage, attributs, ""); attributs = ConstantExpr::getCast(Instruction::BitCast, attributs, @@ -880,19 +890,19 @@ MethodElts.push_back(attributs); } else { - MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::AttributType)); + MethodElts.push_back(Context.getNullValue(JnjvmModule::AttributType)); } // nbAttributs - MethodElts.push_back(ConstantInt::get(Type::Int16Ty, method.nbAttributs)); + MethodElts.push_back(Context.getConstantInt(Type::Int16Ty, method.nbAttributs)); // enveloppes // already allocated by the JIT, don't reallocate them. - MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::EnveloppeType)); + MethodElts.push_back(Context.getNullValue(JnjvmModule::EnveloppeType)); // nbEnveloppes // 0 because we're not allocating here. - MethodElts.push_back(ConstantInt::get(Type::Int16Ty, 0)); + MethodElts.push_back(Context.getConstantInt(Type::Int16Ty, 0)); // classDef MethodElts.push_back(getNativeClass(method.classDef)); @@ -904,11 +914,11 @@ MethodElts.push_back(getUTF8(method.type)); // canBeInlined - MethodElts.push_back(ConstantInt::get(Type::Int8Ty, method.canBeInlined)); + MethodElts.push_back(Context.getConstantInt(Type::Int8Ty, method.canBeInlined)); // code if (isAbstract(method.access)) { - MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); + MethodElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); } else { LLVMMethodInfo* LMI = getMethodInfo(&method); Function* func = LMI->getMethod(); @@ -917,10 +927,10 @@ } // offset - MethodElts.push_back(ConstantInt::get(Type::Int32Ty, method.offset)); + MethodElts.push_back(Context.getConstantInt(Type::Int32Ty, method.offset)); //JInfo - MethodElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); + MethodElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); return ConstantStruct::get(STy, MethodElts); } @@ -929,6 +939,7 @@ const llvm::Type* JCPTy = JnjvmModule::JavaClassPrimitiveType->getContainedType(0); const StructType* STy = dyn_cast(JCPTy); + LLVMContext& Context = getLLVMModule()->getContext(); std::vector ClassElts; @@ -936,7 +947,7 @@ ClassElts.push_back(CreateConstantFromCommonClass(cl)); // primSize - ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->logSize)); + ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->logSize)); return ConstantStruct::get(STy, ClassElts); } @@ -966,6 +977,7 @@ const StructType* STy = dyn_cast(JnjvmModule::JavaClassType->getContainedType(0)); Module& Mod = *getLLVMModule(); + LLVMContext& Context = getLLVMModule()->getContext(); std::vector ClassElts; std::vector TempElts; @@ -974,7 +986,7 @@ ClassElts.push_back(CreateConstantFromCommonClass(cl)); // virtualSize - ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->virtualSize)); + ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->virtualSize)); // IsolateInfo const ArrayType* ATy = dyn_cast(STy->getContainedType(2)); @@ -984,15 +996,15 @@ assert(TCMTy && "Malformed type"); uint32 status = cl->needsInitialisationCheck() ? vmjc : ready; - TempElts.push_back(ConstantInt::get(Type::Int8Ty, status)); - TempElts.push_back(ConstantInt::get(Type::Int1Ty, status == ready ? 1 : 0)); + TempElts.push_back(Context.getConstantInt(Type::Int8Ty, status)); + TempElts.push_back(Context.getConstantInt(Type::Int1Ty, status == ready ? 1 : 0)); TempElts.push_back(getStaticInstance(cl)); Constant* CStr[1] = { ConstantStruct::get(TCMTy, TempElts) }; TempElts.clear(); ClassElts.push_back(ConstantArray::get(ATy, CStr, 1)); // thinlock - ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); + ClassElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); if (cl->nbVirtualFields + cl->nbStaticFields) { ATy = ArrayType::get(JnjvmModule::JavaFieldType->getContainedType(0), @@ -1022,30 +1034,30 @@ fields = ConstantArray::get(ATy, TempElts); TempElts.clear(); - fields = new GlobalVariable(*getLLVMModule(), ATy, false, + fields = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, fields, ""); fields = ConstantExpr::getCast(Instruction::BitCast, fields, JnjvmModule::JavaFieldType); } else { - fields = Mod.getContext().getNullValue(JnjvmModule::JavaFieldType); + fields = Context.getNullValue(JnjvmModule::JavaFieldType); } // virtualFields ClassElts.push_back(fields); ConstantInt* nbVirtualFields = - ConstantInt::get(Type::Int16Ty, cl->nbVirtualFields); + Context.getConstantInt(Type::Int16Ty, cl->nbVirtualFields); // nbVirtualFields ClassElts.push_back(nbVirtualFields); // staticFields // Output null, getLLVMModule() will be set in the initializer. Otherwise, the // assembly emitter of LLVM will try to align the data. - ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaFieldType)); + ClassElts.push_back(Context.getNullValue(JnjvmModule::JavaFieldType)); // nbStaticFields - ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticFields)); + ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbStaticFields)); // virtualMethods if (cl->nbVirtualMethods + cl->nbStaticMethods) { @@ -1069,21 +1081,21 @@ if (cl->nbVirtualMethods + cl->nbStaticMethods) { methods = ConstantArray::get(ATy, TempElts); TempElts.clear(); - GlobalVariable* GV = new GlobalVariable(*getLLVMModule(), ATy, false, + GlobalVariable* GV = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, methods, ""); virtualMethods.insert(std::make_pair(cl, GV)); methods = ConstantExpr::getCast(Instruction::BitCast, GV, JnjvmModule::JavaMethodType); } else { - methods = Mod.getContext().getNullValue(JnjvmModule::JavaMethodType); + methods = Context.getNullValue(JnjvmModule::JavaMethodType); } // virtualMethods ClassElts.push_back(methods); ConstantInt* nbVirtualMethods = - ConstantInt::get(Type::Int16Ty, cl->nbVirtualMethods); + Context.getConstantInt(Type::Int16Ty, cl->nbVirtualMethods); // nbVirtualMethods ClassElts.push_back(nbVirtualMethods); @@ -1092,7 +1104,7 @@ ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaMethodType)); // nbStaticMethods - ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticMethods)); + ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbStaticMethods)); // ownerClass ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); @@ -1125,7 +1137,7 @@ } // nbAttributs - ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbAttributs)); + ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbAttributs)); // innerClasses if (cl->nbInnerClasses) { @@ -1149,7 +1161,7 @@ } // nbInnerClasses - ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbInnerClasses)); + ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbInnerClasses)); // outerClass if (cl->outerClass) { @@ -1159,19 +1171,19 @@ } // innerAccess - ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->innerAccess)); + ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->innerAccess)); // innerOuterResolved - ClassElts.push_back(ConstantInt::get(Type::Int8Ty, cl->innerOuterResolved)); + ClassElts.push_back(Context.getConstantInt(Type::Int8Ty, cl->innerOuterResolved)); // isAnonymous - ClassElts.push_back(ConstantInt::get(Type::Int8Ty, cl->isAnonymous)); + ClassElts.push_back(Context.getConstantInt(Type::Int8Ty, cl->isAnonymous)); // virtualTableSize - ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->virtualTableSize)); + ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->virtualTableSize)); // staticSize - ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->staticSize)); + ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->staticSize)); // JInfo ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); @@ -1182,10 +1194,12 @@ template Constant* JavaAOTCompiler::CreateConstantFromArray(const T* val, const Type* Ty) { Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); std::vector Elemts; const ArrayType* ATy = ArrayType::get(Ty, val->size); Elemts.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); Elemts.push_back(JnjvmModule::pointerSizeType); + Elemts.push_back(ATy); @@ -1193,14 +1207,14 @@ std::vector Cts; Cts.push_back(CreateConstantForBaseObject(val->getClass())); - Cts.push_back(ConstantInt::get(JnjvmModule::pointerSizeType, val->size)); + Cts.push_back(Context.getConstantInt(JnjvmModule::pointerSizeType, val->size)); std::vector Vals; for (sint32 i = 0; i < val->size; ++i) { if (Ty->isInteger()) { - Vals.push_back(ConstantInt::get(Ty, (uint64)val->elements[i])); + Vals.push_back(Context.getConstantInt(Ty, (uint64)val->elements[i])); } else if (Ty->isFloatingPoint()) { - Vals.push_back(ConstantFP::get(Ty, (double)(size_t)val->elements[i])); + Vals.push_back(Context.getConstantFP(Ty, (double)(size_t)val->elements[i])); } else { if (val->elements[i]) { Vals.push_back(getFinalObject((JavaObject*)(size_t)val->elements[i])); @@ -1216,6 +1230,8 @@ } Constant* JavaAOTCompiler::CreateConstantFromUTF8(const UTF8* val) { + Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); std::vector Elemts; const ArrayType* ATy = ArrayType::get(Type::Int16Ty, val->size); Elemts.push_back(JnjvmModule::pointerSizeType); @@ -1225,11 +1241,11 @@ const StructType* STy = StructType::get(Elemts); std::vector Cts; - Cts.push_back(ConstantInt::get(JnjvmModule::pointerSizeType, val->size)); + Cts.push_back(Context.getConstantInt(JnjvmModule::pointerSizeType, val->size)); std::vector Vals; for (sint32 i = 0; i < val->size; ++i) { - Vals.push_back(ConstantInt::get(Type::Int16Ty, val->elements[i])); + Vals.push_back(Context.getConstantInt(Type::Int16Ty, val->elements[i])); } Cts.push_back(ConstantArray::get(ATy, Vals)); @@ -1260,6 +1276,7 @@ Constant* JavaAOTCompiler::CreateConstantFromVT(JavaVirtualTable* VT) { Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); CommonClass* classDef = VT->cl; uint32 size = classDef->isClass() ? classDef->asClass()->virtualTableSize : JavaVirtualTable::getBaseSize(); @@ -1309,11 +1326,11 @@ // depth Elemts.push_back(ConstantExpr::getIntToPtr( - ConstantInt::get(Type::Int64Ty, VT->depth), PTy)); + Context.getConstantInt(Type::Int64Ty, VT->depth), PTy)); // offset Elemts.push_back(ConstantExpr::getIntToPtr( - ConstantInt::get(Type::Int64Ty, VT->offset), PTy)); + Context.getConstantInt(Type::Int64Ty, VT->offset), PTy)); // cache Elemts.push_back(N); @@ -1331,7 +1348,7 @@ // nbSecondaryTypes Elemts.push_back(ConstantExpr::getIntToPtr( - ConstantInt::get(Type::Int64Ty, VT->nbSecondaryTypes), PTy)); + Context.getConstantInt(Type::Int64Ty, VT->nbSecondaryTypes), PTy)); // secondaryTypes const ArrayType* DTy = ArrayType::get(JnjvmModule::VTType, @@ -1461,7 +1478,7 @@ Constant* cons = - ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, + ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t(isolate)), ptrType); @@ -1886,6 +1903,8 @@ } void JavaAOTCompiler::generateMain(const char* name, bool jit) { + Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); // Type Definitions std::vector FuncArgs; @@ -1903,7 +1922,7 @@ GlobalValue::InternalLinkage, 0, "mainClass"); - Constant* NameArray = ConstantArray::get(name, true); + Constant* NameArray = Context.getConstantArray(name, true); GvarArrayStr->setInitializer(NameArray); Value* Indices[2] = { JavaIntrinsics.constantZero, JavaIntrinsics.constantZero }; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Wed Jul 15 08:31:22 2009 @@ -158,7 +158,7 @@ Constant* Offset = LMI->getOffset(); indexes2[1] = Offset; #ifdef ISOLATE_SHARING - indexesCtp = ConstantInt::get(Type::Int32Ty, + indexesCtp = llvmContext->getConstantInt(Type::Int32Ty, Offset->getZExtValue() * -1); #endif } else { @@ -371,7 +371,7 @@ // this problem because it passes first arguments in registers. // Therefore, it was overwriting the frame pointer when entering the // native method. - Value* Temp = new AllocaInst(module->ptrType, "", currentBlock); + Value* Temp = new AllocaInst(*llvmContext, module->ptrType, "", currentBlock); new StoreInst(FrameAddr, Temp, currentBlock); Value* result = llvm::CallInst::Create(nativeFunc, nativeArgs.begin(), nativeArgs.end(), "", currentBlock); @@ -445,8 +445,8 @@ // It's a thin lock. Look if we're the owner of this lock. currentBlock = ThinLockBB; - Value* idMask = ConstantInt::get(module->pointerSizeType, 0x7FFFFF00); - Value* cptMask = ConstantInt::get(module->pointerSizeType, 0xFF); + Value* idMask = llvmContext->getConstantInt(module->pointerSizeType, 0x7FFFFF00); + Value* cptMask = llvmContext->getConstantInt(module->pointerSizeType, 0xFF); Value* IdInLock = BinaryOperator::CreateAnd(atomic, idMask, "", currentBlock); Value* owner = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, threadId, IdInLock, ""); @@ -637,21 +637,21 @@ Instruction* firstInstruction = firstBB->begin(); for (int i = 0; i < maxLocals; i++) { - intLocals.push_back(new AllocaInst(Type::Int32Ty, "", firstInstruction)); - doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", + intLocals.push_back(new AllocaInst(*llvmContext, Type::Int32Ty, "", firstInstruction)); + doubleLocals.push_back(new AllocaInst(*llvmContext, Type::DoubleTy, "", firstInstruction)); - longLocals.push_back(new AllocaInst(Type::Int64Ty, "", firstInstruction)); - floatLocals.push_back(new AllocaInst(Type::FloatTy, "", firstInstruction)); - objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", + longLocals.push_back(new AllocaInst(*llvmContext, Type::Int64Ty, "", firstInstruction)); + floatLocals.push_back(new AllocaInst(*llvmContext, Type::FloatTy, "", firstInstruction)); + objectLocals.push_back(new AllocaInst(*llvmContext, module->JavaObjectType, "", firstInstruction)); } } else { for (int i = 0; i < maxLocals; i++) { - intLocals.push_back(new AllocaInst(Type::Int32Ty, "", firstBB)); - doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", firstBB)); - longLocals.push_back(new AllocaInst(Type::Int64Ty, "", firstBB)); - floatLocals.push_back(new AllocaInst(Type::FloatTy, "", firstBB)); - objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", + intLocals.push_back(new AllocaInst(*llvmContext, Type::Int32Ty, "", firstBB)); + doubleLocals.push_back(new AllocaInst(*llvmContext, Type::DoubleTy, "", firstBB)); + longLocals.push_back(new AllocaInst(*llvmContext, Type::Int64Ty, "", firstBB)); + floatLocals.push_back(new AllocaInst(*llvmContext, Type::FloatTy, "", firstBB)); + objectLocals.push_back(new AllocaInst(*llvmContext, module->JavaObjectType, "", firstBB)); } } @@ -775,11 +775,11 @@ for (int i = 0; i < maxLocals; i++) { - intLocals.push_back(new AllocaInst(Type::Int32Ty, "", currentBlock)); - doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", currentBlock)); - longLocals.push_back(new AllocaInst(Type::Int64Ty, "", currentBlock)); - floatLocals.push_back(new AllocaInst(Type::FloatTy, "", currentBlock)); - objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", + intLocals.push_back(new AllocaInst(*llvmContext, Type::Int32Ty, "", currentBlock)); + doubleLocals.push_back(new AllocaInst(*llvmContext, Type::DoubleTy, "", currentBlock)); + longLocals.push_back(new AllocaInst(*llvmContext, Type::Int64Ty, "", currentBlock)); + floatLocals.push_back(new AllocaInst(*llvmContext, Type::FloatTy, "", currentBlock)); + objectLocals.push_back(new AllocaInst(*llvmContext, module->JavaObjectType, "", currentBlock)); } @@ -831,7 +831,7 @@ #if defined(ISOLATE_SHARING) ctpCache = i; - Value* addrCtpCache = new AllocaInst(module->ConstantPoolType, "", + Value* addrCtpCache = new AllocaInst(*llvmContext, module->ConstantPoolType, "", currentBlock); /// make it volatile to be sure it's on the stack new StoreInst(ctpCache, addrCtpCache, true, currentBlock); @@ -857,7 +857,7 @@ currentBlock); OldIsolateID = new LoadInst(IsolateIDPtr, "", currentBlock); - Value* MyID = ConstantInt::get(module->pointerSizeType, + Value* MyID = llvmContext->getConstantInt(module->pointerSizeType, loader->getIsolate()->IsolateID); Cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, OldIsolateID, MyID, ""); @@ -1065,16 +1065,16 @@ #endif } else if (type == JavaConstantPool::ConstantLong) { - push(ConstantInt::get(Type::Int64Ty, ctpInfo->LongAt(index)), + push(llvmContext->getConstantInt(Type::Int64Ty, ctpInfo->LongAt(index)), false); } else if (type == JavaConstantPool::ConstantDouble) { - push(ConstantFP::get(Type::DoubleTy, ctpInfo->DoubleAt(index)), + push(llvmContext->getConstantFP(Type::DoubleTy, ctpInfo->DoubleAt(index)), false); } else if (type == JavaConstantPool::ConstantInteger) { - push(ConstantInt::get(Type::Int32Ty, ctpInfo->IntegerAt(index)), + push(llvmContext->getConstantInt(Type::Int32Ty, ctpInfo->IntegerAt(index)), false); } else if (type == JavaConstantPool::ConstantFloat) { - push(ConstantFP::get(Type::FloatTy, ctpInfo->FloatAt(index)), + push(llvmContext->getConstantFP(Type::FloatTy, ctpInfo->FloatAt(index)), false); } else if (type == JavaConstantPool::ConstantClass) { UserCommonClass* cl = 0; @@ -1404,7 +1404,7 @@ BranchInst::Create(falseCl, trueCl, test, currentBlock); std::vector Args; Args.push_back(ctpCache); - Args.push_back(ConstantInt::get(Type::Int32Ty, index)); + Args.push_back(llvmContext->getConstantInt(Type::Int32Ty, index)); Args.push_back(GV); res = CallInst::Create(module->SpecialCtpLookupFunction, Args.begin(), Args.end(), "", falseCl); @@ -1532,7 +1532,7 @@ Args.push_back(resolver); Args.push_back(CTP); Args.push_back(Cl); - Args.push_back(ConstantInt::get(Type::Int32Ty, index)); + Args.push_back(llvmContext->getConstantInt(Type::Int32Ty, index)); if (additionalArg) Args.push_back(additionalArg); Value* res = 0; @@ -1774,28 +1774,28 @@ const PrimitiveTypedef* prim = (PrimitiveTypedef*)sign; if (prim->isInt()) { sint32 val = field->getInt32Field(Obj); - push(ConstantInt::get(Type::Int32Ty, val), false); + push(llvmContext->getConstantInt(Type::Int32Ty, val), false); } else if (prim->isByte()) { sint8 val = (sint8)field->getInt8Field(Obj); - push(ConstantInt::get(Type::Int8Ty, val), false); + push(llvmContext->getConstantInt(Type::Int8Ty, val), false); } else if (prim->isBool()) { uint8 val = (uint8)field->getInt8Field(Obj); - push(ConstantInt::get(Type::Int8Ty, val), true); + push(llvmContext->getConstantInt(Type::Int8Ty, val), true); } else if (prim->isShort()) { sint16 val = (sint16)field->getInt16Field(Obj); - push(ConstantInt::get(Type::Int16Ty, val), false); + push(llvmContext->getConstantInt(Type::Int16Ty, val), false); } else if (prim->isChar()) { uint16 val = (uint16)field->getInt16Field(Obj); - push(ConstantInt::get(Type::Int16Ty, val), true); + push(llvmContext->getConstantInt(Type::Int16Ty, val), true); } else if (prim->isLong()) { sint64 val = (sint64)field->getLongField(Obj); - push(ConstantInt::get(Type::Int64Ty, val), false); + push(llvmContext->getConstantInt(Type::Int64Ty, val), false); } else if (prim->isFloat()) { float val = (float)field->getFloatField(Obj); - push(ConstantFP::get(Type::FloatTy, val), false); + push(llvmContext->getConstantFP(Type::FloatTy, val), false); } else if (prim->isDouble()) { double val = (double)field->getDoubleField(Obj); - push(ConstantFP::get(Type::DoubleTy, val), false); + push(llvmContext->getConstantFP(Type::DoubleTy, val), false); } else { abort(); } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Wed Jul 15 08:31:22 2009 @@ -29,41 +29,47 @@ using namespace llvm; Constant* JavaJITCompiler::getNativeClass(CommonClass* classDef) { + LLVMContext& Context = getLLVMModule()->getContext(); const llvm::Type* Ty = classDef->isClass() ? JnjvmModule::JavaClassType : JnjvmModule::JavaCommonClassType; - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(classDef)); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(classDef)); return ConstantExpr::getIntToPtr(CI, Ty); } Constant* JavaJITCompiler::getConstantPool(JavaConstantPool* ctp) { void* ptr = ctp->ctpRes; assert(ptr && "No constant pool found"); - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(ptr)); + LLVMContext& Context = getLLVMModule()->getContext(); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(ptr)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::ConstantPoolType); } Constant* JavaJITCompiler::getMethodInClass(JavaMethod* meth) { - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, (int64_t)meth); + LLVMContext& Context = getLLVMModule()->getContext(); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, (int64_t)meth); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaMethodType); } Constant* JavaJITCompiler::getString(JavaString* str) { assert(str && "No string given"); - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64(str)); + LLVMContext& Context = getLLVMModule()->getContext(); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64(str)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } Constant* JavaJITCompiler::getEnveloppe(Enveloppe* enveloppe) { assert(enveloppe && "No enveloppe given"); - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64(enveloppe)); + LLVMContext& Context = getLLVMModule()->getContext(); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64(enveloppe)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::EnveloppeType); } Constant* JavaJITCompiler::getJavaClass(CommonClass* cl) { JavaObject* obj = cl->getClassDelegatee(JavaThread::get()->getJVM()); assert(obj && "Delegatee not created"); - Constant* CI = ConstantInt::get(Type::Int64Ty, uint64(obj)); + LLVMContext& Context = getLLVMModule()->getContext(); + Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64(obj)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } @@ -77,11 +83,13 @@ } Constant* JavaJITCompiler::getFinalObject(JavaObject* obj) { - Constant* CI = ConstantInt::get(Type::Int64Ty, uint64(obj)); + LLVMContext& Context = getLLVMModule()->getContext(); + Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64(obj)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } Constant* JavaJITCompiler::getStaticInstance(Class* classDef) { + LLVMContext& Context = getLLVMModule()->getContext(); #ifdef ISOLATE assert(0 && "Should not be here"); abort(); @@ -96,27 +104,29 @@ } classDef->release(); } - Constant* CI = ConstantInt::get(Type::Int64Ty, (uint64_t(obj))); + Constant* CI = Context.getConstantInt(Type::Int64Ty, (uint64_t(obj))); return ConstantExpr::getIntToPtr(CI, JnjvmModule::ptrType); } Constant* JavaJITCompiler::getVirtualTable(JavaVirtualTable* VT) { + LLVMContext& Context = getLLVMModule()->getContext(); if (VT->cl->isClass()) { LLVMClassInfo* LCI = getClassInfo(VT->cl->asClass()); LCI->getVirtualType(); } - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(VT)); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(VT)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::VTType); } Constant* JavaJITCompiler::getNativeFunction(JavaMethod* meth, void* ptr) { + LLVMContext& Context = getLLVMModule()->getContext(); LLVMSignatureInfo* LSI = getSignatureInfo(meth->getSignature()); const llvm::Type* valPtrType = LSI->getNativePtrType(); assert(ptr && "No native function given"); - Constant* CI = ConstantInt::get(Type::Int64Ty, uint64_t(ptr)); + Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(ptr)); return ConstantExpr::getIntToPtr(CI, valPtrType); } @@ -134,7 +144,8 @@ #ifdef SERVICE Value* JavaJITCompiler::getIsolate(Jnjvm* isolate, Value* Where) { - ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(isolate)); + LLVMContext& Context = getLLVMModule()->getContext(); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(isolate)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::ptrType); } #endif Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Wed Jul 15 08:31:22 2009 @@ -161,8 +161,8 @@ #if JNJVM_EXECUTE > 1 { Value* args[3] = { - ConstantInt::get(Type::Int32Ty, (int64_t)bytecodes[i]), - ConstantInt::get(Type::Int32Ty, (int64_t)i), + llvmContext->getConstantInt(Type::Int32Ty, (int64_t)bytecodes[i]), + llvmContext->getConstantInt(Type::Int32Ty, (int64_t)i), TheCompiler->getMethodInClass(compilingMethod) }; @@ -241,13 +241,13 @@ break; case BIPUSH : - push(ConstantExpr::getSExt(ConstantInt::get(Type::Int8Ty, + push(ConstantExpr::getSExt(llvmContext->getConstantInt(Type::Int8Ty, bytecodes[++i]), Type::Int32Ty), false); break; case SIPUSH : - push(ConstantExpr::getSExt(ConstantInt::get(Type::Int16Ty, + push(ConstantExpr::getSExt(llvmContext->getConstantInt(Type::Int16Ty, readS2(bytecodes, i)), Type::Int32Ty), false); break; @@ -1098,7 +1098,7 @@ case IUSHR : { Value* val2 = popAsInt(); Value* val1 = popAsInt(); - Value* mask = ConstantInt::get(Type::Int32Ty, 0x1F); + Value* mask = llvmContext->getConstantInt(Type::Int32Ty, 0x1F); val2 = BinaryOperator::CreateAnd(val2, mask, "", currentBlock); push(BinaryOperator::CreateLShr(val1, val2, "", currentBlock), false); @@ -1107,7 +1107,7 @@ case LUSHR : { Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock); - Value* mask = ConstantInt::get(Type::Int64Ty, 0x3F); + Value* mask = llvmContext->getConstantInt(Type::Int64Ty, 0x3F); val2 = BinaryOperator::CreateAnd(val2, mask, "", currentBlock); pop(); // remove the 0 on the stack Value* val1 = pop(); @@ -1179,7 +1179,7 @@ sint16 val = WREAD_S1(bytecodes, false, i, wide); llvm::Value* add = BinaryOperator::CreateAdd( new LoadInst(intLocals[idx], "", currentBlock), - ConstantInt::get(Type::Int32Ty, val), "", + llvmContext->getConstantInt(Type::Int32Ty, val), "", currentBlock); new StoreInst(add, intLocals[idx], false, currentBlock); break; @@ -1715,7 +1715,7 @@ case JSR : { uint32 tmp = i; Value* expr = ConstantExpr::getIntToPtr( - ConstantInt::get(Type::Int64Ty, + llvmContext->getConstantInt(Type::Int64Ty, uint64_t (jsrIndex++)), module->JavaObjectType); push(expr, false); @@ -1734,7 +1734,7 @@ uint32 index = 0; for (std::vector::iterator i = jsrs.begin(), e = jsrs.end(); i!= e; ++i, ++index) { - inst->addCase(ConstantInt::get(Type::Int32Ty, index), *i); + inst->addCase(llvmContext->getConstantInt(Type::Int32Ty, index), *i); } break; @@ -1755,7 +1755,7 @@ const llvm::Type* type = index->getType(); for (sint32 cur = low; cur < high; ++cur) { Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, - ConstantInt::get(type, cur), index, ""); + llvmContext->getConstantInt(type, cur), index, ""); BasicBlock* falseBlock = createBasicBlock("continue tableswitch"); branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock); @@ -1785,7 +1785,7 @@ key = new SExtInst(key, Type::Int32Ty, "", currentBlock); } for (uint32 cur = 0; cur < nbs; ++cur) { - Value* val = ConstantInt::get(Type::Int32Ty, readU4(bytecodes, i)); + Value* val = llvmContext->getConstantInt(Type::Int32Ty, readU4(bytecodes, i)); Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val, key, ""); BasicBlock* falseBlock = createBasicBlock("continue lookupswitch"); @@ -1904,7 +1904,7 @@ valCl = TheCompiler->getNativeClass(dcl); #else Value* args[2] = { isolateLocal, - ConstantInt::get(Type::Int32Ty, id - 4) }; + llvmContext->getConstantInt(Type::Int32Ty, id - 4) }; valCl = CallInst::Create(module->GetJnjvmArrayClassFunction, args, args + 2, "", currentBlock); #endif @@ -2055,7 +2055,7 @@ } else { BasicBlock* ifFalse = createBasicBlock("false type compare"); BranchInst::Create(endBlock, ifFalse, cmp, currentBlock); - node->addIncoming(ConstantInt::getFalse(), currentBlock); + node->addIncoming(llvmContext->getConstantIntFalse(), currentBlock); currentBlock = ifFalse; } @@ -2083,7 +2083,7 @@ objVT, "", currentBlock); uint32 depth = cl->virtualVT->depth; - ConstantInt* CI = ConstantInt::get(Type::Int32Ty, depth); + ConstantInt* CI = llvmContext->getConstantInt(Type::Int32Ty, depth); Value* displayArgs[2] = { inDisplay, CI }; Value* VTInDisplay = CallInst::Create(module->GetVTInDisplayFunction, @@ -2138,7 +2138,7 @@ Value* valCl = getResolvedCommonClass(index, true, 0); Value** args = (Value**)alloca(sizeof(Value*) * (dim + 2)); args[0] = valCl; - args[1] = ConstantInt::get(Type::Int32Ty, dim); + args[1] = llvmContext->getConstantInt(Type::Int32Ty, dim); for (int cur = dim + 1; cur >= 2; --cur) args[cur] = pop(); Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Wed Jul 15 08:31:22 2009 @@ -113,6 +113,7 @@ void JnjvmModule::initialise() { Module* module = globalModule; + LLVMContext& Context = module->getContext(); jnjvm::llvm_runtime::makeLLVMModuleContents(module); VTType = PointerType::getUnqual(module->getTypeByName("VT")); @@ -178,10 +179,10 @@ JavaObjectNullConstant = module->getContext().getNullValue(JnjvmModule::JavaObjectType); - MaxArraySizeConstant = ConstantInt::get(Type::Int32Ty, + MaxArraySizeConstant = Context.getConstantInt(Type::Int32Ty, JavaArray::MaxArraySize); JavaArraySizeConstant = - ConstantInt::get(Type::Int32Ty, sizeof(JavaObject) + sizeof(ssize_t)); + Context.getConstantInt(Type::Int32Ty, sizeof(JavaObject) + sizeof(ssize_t)); JavaArrayElementsOffsetConstant = mvm::MvmModule::constantTwo; @@ -191,19 +192,19 @@ OffsetClassInVTConstant = mvm::MvmModule::constantThree; OffsetDepthInVTConstant = mvm::MvmModule::constantFour; OffsetDisplayInVTConstant = mvm::MvmModule::constantSeven; - OffsetBaseClassVTInVTConstant = ConstantInt::get(Type::Int32Ty, 17); + OffsetBaseClassVTInVTConstant = Context.getConstantInt(Type::Int32Ty, 17); OffsetObjectSizeInClassConstant = mvm::MvmModule::constantOne; - OffsetVTInClassConstant = ConstantInt::get(Type::Int32Ty, 7); + OffsetVTInClassConstant = Context.getConstantInt(Type::Int32Ty, 7); OffsetTaskClassMirrorInClassConstant = mvm::MvmModule::constantTwo; OffsetStaticInstanceInTaskClassMirrorConstant = mvm::MvmModule::constantTwo; OffsetStatusInTaskClassMirrorConstant = mvm::MvmModule::constantZero; OffsetInitializedInTaskClassMirrorConstant = mvm::MvmModule::constantOne; - OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 9); - OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 10); + OffsetJavaExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 9); + OffsetCXXExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 10); - ClassReadyConstant = ConstantInt::get(Type::Int8Ty, ready); + ClassReadyConstant = Context.getConstantInt(Type::Int8Ty, ready); LLVMAssessorInfo::initialise(); } Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Wed Jul 15 08:31:22 2009 @@ -119,6 +119,7 @@ JavaLLVMCompiler* TheCompiler = (JavaLLVMCompiler*)meth->classDef->classLoader->getCompiler(); JnjvmModule* module = TheCompiler->getIntrinsics(); + LLVMContext* Context = F.getContext(); bool Changed = false; for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { BasicBlock *Cur = BI; @@ -408,7 +409,7 @@ ConstantInt* Cons = dyn_cast(Index); assert(CI && "Wrong use of GetConstantPoolAt"); uint64 val = Cons->getZExtValue(); - Value* indexes = ConstantInt::get(Type::Int32Ty, val + 1); + Value* indexes = Context->getConstantInt(Type::Int32Ty, val + 1); #else Value* indexes = Index; #endif @@ -535,7 +536,7 @@ BasicBlock* FailedBlock = BasicBlock::Create("", &F); PHINode* node = PHINode::Create(Type::Int1Ty, "", CurEndBlock); - ConstantInt* CC = ConstantInt::get(Type::Int32Ty, + ConstantInt* CC = Context->getConstantInt(Type::Int32Ty, JavaVirtualTable::getOffsetIndex()); Value* indices[2] = { module->constantZero, CC }; Value* Offset = GetElementPtrInst::Create(VT2, indices, indices + 2, @@ -593,7 +594,7 @@ // if (VT1.cache == VT2 || VT1 == VT2) goto end with true; // else goto headerLoop; ConstantInt* cacheIndex = - ConstantInt::get(Type::Int32Ty, JavaVirtualTable::getCacheIndex()); + Context->getConstantInt(Type::Int32Ty, JavaVirtualTable::getCacheIndex()); Value* indices[2] = { module->constantZero, cacheIndex }; Instruction* CachePtr = GetElementPtrInst::Create(VT1, indices, indices + 2, "", CI); @@ -611,7 +612,7 @@ // size = VT1->nbSecondaryTypes; // i = 0; // goto test; - ConstantInt* sizeIndex = ConstantInt::get(Type::Int32Ty, + ConstantInt* sizeIndex = Context->getConstantInt(Type::Int32Ty, JavaVirtualTable::getNumSecondaryTypesIndex()); indices[1] = sizeIndex; Instruction* Size = GetElementPtrInst::Create(VT1, indices, @@ -620,7 +621,7 @@ Size = new LoadInst(Size, "", false, Preheader); Size = new PtrToIntInst(Size, Type::Int32Ty, "", Preheader); - ConstantInt* secondaryTypesIndex = ConstantInt::get(Type::Int32Ty, + ConstantInt* secondaryTypesIndex = Context->getConstantInt(Type::Int32Ty, JavaVirtualTable::getSecondaryTypesIndex()); indices[1] = secondaryTypesIndex; Instruction* secondaryTypes = Modified: vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp Wed Jul 15 08:31:22 2009 @@ -168,6 +168,7 @@ bool EscapeAnalysis::processMalloc(Instruction* I, Value* Size, Value* VT, Loop* CurLoop) { Instruction* Alloc = I; + LLVMContext* Context = I->getParent()->getContext(); ConstantInt* CI = dyn_cast(Size); bool hasFinalizer = true; @@ -219,7 +220,7 @@ BB->getInstList().insert(BB->getTerminator(), Alloc); } - AllocaInst* AI = new AllocaInst(Type::Int8Ty, Size, "", Alloc); + AllocaInst* AI = new AllocaInst(*Context, Type::Int8Ty, Size, "", Alloc); BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc); DOUT << "escape" << Alloc->getParent()->getParent()->getName() << "\n"; Alloc->replaceAllUsesWith(BI); Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Wed Jul 15 08:31:22 2009 @@ -87,55 +87,55 @@ Type::Int32Ty : Type::Int64Ty; // Constant declaration - constantLongMinusOne = ConstantInt::get(Type::Int64Ty, (uint64_t)-1); - constantLongZero = ConstantInt::get(Type::Int64Ty, 0); - constantLongOne = ConstantInt::get(Type::Int64Ty, 1); - constantZero = ConstantInt::get(Type::Int32Ty, 0); - constantInt8Zero = ConstantInt::get(Type::Int8Ty, 0); - constantOne = ConstantInt::get(Type::Int32Ty, 1); - constantTwo = ConstantInt::get(Type::Int32Ty, 2); - constantThree = ConstantInt::get(Type::Int32Ty, 3); - constantFour = ConstantInt::get(Type::Int32Ty, 4); - constantFive = ConstantInt::get(Type::Int32Ty, 5); - constantSix = ConstantInt::get(Type::Int32Ty, 6); - constantSeven = ConstantInt::get(Type::Int32Ty, 7); - constantEight = ConstantInt::get(Type::Int32Ty, 8); - constantMinusOne = ConstantInt::get(Type::Int32Ty, (uint64_t)-1); - constantMinInt = ConstantInt::get(Type::Int32Ty, MinInt); - constantMaxInt = ConstantInt::get(Type::Int32Ty, MaxInt); - constantMinLong = ConstantInt::get(Type::Int64Ty, MinLong); - constantMaxLong = ConstantInt::get(Type::Int64Ty, MaxLong); - constantFloatZero = ConstantFP::get(Type::FloatTy, 0.0f); - constantFloatOne = ConstantFP::get(Type::FloatTy, 1.0f); - constantFloatTwo = ConstantFP::get(Type::FloatTy, 2.0f); - constantDoubleZero = ConstantFP::get(Type::DoubleTy, 0.0); - constantDoubleOne = ConstantFP::get(Type::DoubleTy, 1.0); - constantMaxIntFloat = ConstantFP::get(Type::FloatTy, MaxIntFloat); - constantMinIntFloat = ConstantFP::get(Type::FloatTy, MinIntFloat); - constantMinLongFloat = ConstantFP::get(Type::FloatTy, MinLongFloat); - constantMinLongDouble = ConstantFP::get(Type::DoubleTy, MinLongDouble); - constantMaxLongFloat = ConstantFP::get(Type::FloatTy, MaxLongFloat); - constantMaxIntDouble = ConstantFP::get(Type::DoubleTy, MaxIntDouble); - constantMinIntDouble = ConstantFP::get(Type::DoubleTy, MinIntDouble); - constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, MaxLongDouble); - constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, MaxLongDouble); - constantFloatInfinity = ConstantFP::get(Type::FloatTy, MaxFloat); - constantFloatMinusInfinity = ConstantFP::get(Type::FloatTy, MinFloat); - constantDoubleInfinity = ConstantFP::get(Type::DoubleTy, MaxDouble); - constantDoubleMinusInfinity = ConstantFP::get(Type::DoubleTy, MinDouble); - constantDoubleMinusZero = ConstantFP::get(Type::DoubleTy, -0.0); - constantFloatMinusZero = ConstantFP::get(Type::FloatTy, -0.0f); - constantThreadIDMask = ConstantInt::get(pointerSizeType, mvm::Thread::IDMask); + constantLongMinusOne = globalContext->getConstantInt(Type::Int64Ty, (uint64_t)-1); + constantLongZero = globalContext->getConstantInt(Type::Int64Ty, 0); + constantLongOne = globalContext->getConstantInt(Type::Int64Ty, 1); + constantZero = globalContext->getConstantInt(Type::Int32Ty, 0); + constantInt8Zero = globalContext->getConstantInt(Type::Int8Ty, 0); + constantOne = globalContext->getConstantInt(Type::Int32Ty, 1); + constantTwo = globalContext->getConstantInt(Type::Int32Ty, 2); + constantThree = globalContext->getConstantInt(Type::Int32Ty, 3); + constantFour = globalContext->getConstantInt(Type::Int32Ty, 4); + constantFive = globalContext->getConstantInt(Type::Int32Ty, 5); + constantSix = globalContext->getConstantInt(Type::Int32Ty, 6); + constantSeven = globalContext->getConstantInt(Type::Int32Ty, 7); + constantEight = globalContext->getConstantInt(Type::Int32Ty, 8); + constantMinusOne = globalContext->getConstantInt(Type::Int32Ty, (uint64_t)-1); + constantMinInt = globalContext->getConstantInt(Type::Int32Ty, MinInt); + constantMaxInt = globalContext->getConstantInt(Type::Int32Ty, MaxInt); + constantMinLong = globalContext->getConstantInt(Type::Int64Ty, MinLong); + constantMaxLong = globalContext->getConstantInt(Type::Int64Ty, MaxLong); + constantFloatZero = globalContext->getConstantFP(Type::FloatTy, 0.0f); + constantFloatOne = globalContext->getConstantFP(Type::FloatTy, 1.0f); + constantFloatTwo = globalContext->getConstantFP(Type::FloatTy, 2.0f); + constantDoubleZero = globalContext->getConstantFP(Type::DoubleTy, 0.0); + constantDoubleOne = globalContext->getConstantFP(Type::DoubleTy, 1.0); + constantMaxIntFloat = globalContext->getConstantFP(Type::FloatTy, MaxIntFloat); + constantMinIntFloat = globalContext->getConstantFP(Type::FloatTy, MinIntFloat); + constantMinLongFloat = globalContext->getConstantFP(Type::FloatTy, MinLongFloat); + constantMinLongDouble = globalContext->getConstantFP(Type::DoubleTy, MinLongDouble); + constantMaxLongFloat = globalContext->getConstantFP(Type::FloatTy, MaxLongFloat); + constantMaxIntDouble = globalContext->getConstantFP(Type::DoubleTy, MaxIntDouble); + constantMinIntDouble = globalContext->getConstantFP(Type::DoubleTy, MinIntDouble); + constantMaxLongDouble = globalContext->getConstantFP(Type::DoubleTy, MaxLongDouble); + constantMaxLongDouble = globalContext->getConstantFP(Type::DoubleTy, MaxLongDouble); + constantFloatInfinity = globalContext->getConstantFP(Type::FloatTy, MaxFloat); + constantFloatMinusInfinity = globalContext->getConstantFP(Type::FloatTy, MinFloat); + constantDoubleInfinity = globalContext->getConstantFP(Type::DoubleTy, MaxDouble); + constantDoubleMinusInfinity = globalContext->getConstantFP(Type::DoubleTy, MinDouble); + constantDoubleMinusZero = globalContext->getConstantFP(Type::DoubleTy, -0.0); + constantFloatMinusZero = globalContext->getConstantFP(Type::FloatTy, -0.0f); + constantThreadIDMask = globalContext->getConstantInt(pointerSizeType, mvm::Thread::IDMask); constantStackOverflowMask = - ConstantInt::get(pointerSizeType, mvm::Thread::StackOverflowMask); - constantFatMask = ConstantInt::get(pointerSizeType, + globalContext->getConstantInt(pointerSizeType, mvm::Thread::StackOverflowMask); + constantFatMask = globalContext->getConstantInt(pointerSizeType, pointerSizeType == Type::Int32Ty ? 0x80000000 : 0x8000000000000000LL); - constantPtrOne = ConstantInt::get(pointerSizeType, 1); - constantPtrZero = ConstantInt::get(pointerSizeType, 0); + constantPtrOne = globalContext->getConstantInt(pointerSizeType, 1); + constantPtrZero = globalContext->getConstantInt(pointerSizeType, 0); constantPtrNull = globalContext->getNullValue(ptrType); constantPtrLogSize = - ConstantInt::get(Type::Int32Ty, sizeof(void*) == 8 ? 3 : 2); + globalContext->getConstantInt(Type::Int32Ty, sizeof(void*) == 8 ? 3 : 2); arrayPtrType = PointerType::getUnqual(ArrayType::get(Type::Int8Ty, 0)); } Modified: vmkit/trunk/lib/N3/Mono/MonoString.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/Mono/MonoString.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/N3/Mono/MonoString.cpp (original) +++ vmkit/trunk/lib/N3/Mono/MonoString.cpp Wed Jul 15 08:31:22 2009 @@ -9,6 +9,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" +#include "llvm/LLVMContext.h" #include "mvm/JIT.h" @@ -50,10 +51,12 @@ VirtualMachine* vm = VMThread::get()->vm; if (!str->_llvmVar) { const Type* pty = mvm::MvmModule::ptrType; + Module* Mod = vm->getLLVMModule(); + LLVMContext& Context = Mod->getContext(); Constant* cons = - ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), pty); - str->_llvmVar = new GlobalVariable(*(vm->getLLVMModule()), pty, true, + str->_llvmVar = new GlobalVariable(*Mod, pty, true, GlobalValue::ExternalLinkage, cons, ""); } Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Wed Jul 15 08:31:22 2009 @@ -102,7 +102,8 @@ #ifdef MULTIPLE_GC Value* GC = ++(block->getParent()->arg_begin()); #endif - + + Function* llvmFunction = block->getParent(); Constant* zero = mvm::MvmModule::constantZero; for (std::vector::iterator i = fields.begin(), e = fields.end(); i!= e; ++i) { @@ -112,7 +113,7 @@ args.push_back(zero); if (boxed) { ConstantInt* CI = dyn_cast(field->offset); - args.push_back(ConstantInt::get(CI->getValue() + 1)); + args.push_back(llvmFunction->getContext()->getConstantInt(CI->getValue() + 1)); } else { args.push_back(field->offset); } @@ -124,7 +125,7 @@ args.push_back(zero); if (boxed) { ConstantInt* CI = dyn_cast(field->offset); - args.push_back(ConstantInt::get(CI->getValue() + 1)); + args.push_back(llvmFunction->getContext()->getConstantInt(CI->getValue() + 1)); } else { args.push_back(field->offset); } @@ -624,13 +625,13 @@ return; } else if (type->super == MSCorlib::pValue || type->super == MSCorlib::pEnum) { - obj = new AllocaInst(type->naturalType, "", currentBlock); + obj = new AllocaInst(*(llvmFunction->getContext()), type->naturalType, "", currentBlock); uint64 size = module->getTypeSize(type->naturalType); std::vector params; params.push_back(new BitCastInst(obj, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); @@ -737,7 +738,7 @@ std::vector params; params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -949,7 +950,7 @@ void* natPtr = NativeUtil::nativeLookup(compilingClass, compilingMethod); Value* valPtr = - ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (uint64)natPtr), + ConstantExpr::getIntToPtr(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, (uint64)natPtr), PointerType::getUnqual(funcType)); Value* result = CallInst::Create(valPtr, nativeArgs.begin(), @@ -977,7 +978,7 @@ } if (nbe) { - supplLocal = new AllocaInst(VMObject::llvmType, "exceptionVar", + supplLocal = new AllocaInst(*(llvmFunction->getContext()), VMObject::llvmType, "exceptionVar", currentBlock); } @@ -1209,7 +1210,7 @@ const Type* cur = i->getType(); - AllocaInst* alloc = new AllocaInst(cur, "", currentBlock); + AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cur, "", currentBlock); new StoreInst(i, alloc, false, currentBlock); arguments.push_back(alloc); } @@ -1222,7 +1223,7 @@ e = temp.end(); i!= e; ++i) { VMCommonClass* cl = *i; cl->resolveType(false, false, genMethod); - AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); + AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, currentBlock); @@ -1233,7 +1234,7 @@ params.push_back(new BitCastInst(alloc, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); @@ -1281,7 +1282,7 @@ currentBlock)); params.push_back(new BitCastInst(endNode, module->ptrType, "", currentBlock)); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantFour); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1386,7 +1387,7 @@ const Type* cur = (*i)->getType(); - AllocaInst* alloc = new AllocaInst(cur, "", currentBlock); + AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cur, "", currentBlock); new StoreInst(*i, alloc, false, currentBlock); arguments.push_back(alloc); } @@ -1399,7 +1400,7 @@ e = temp.end(); i!= e; ++i) { VMCommonClass* cl = *i; cl->resolveType(false, false, genMethod); - AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); + AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, currentBlock); @@ -1410,7 +1411,7 @@ params.push_back(new BitCastInst(alloc, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); @@ -1622,7 +1623,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } Value* val = 0; @@ -1654,7 +1655,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } @@ -1691,7 +1692,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } @@ -1720,7 +1721,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } Modified: vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp Wed Jul 15 08:31:22 2009 @@ -364,12 +364,14 @@ if (!_llvmVar) { aquire(); if (!_llvmVar) { + Module* Mod = vm->getLLVMModule(); + LLVMContext& Context = Mod->getContext(); const Type* pty = mvm::MvmModule::ptrType; Constant* cons = - ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), pty); - _llvmVar = new GlobalVariable(*(vm->getLLVMModule()), pty, true, + _llvmVar = new GlobalVariable(*Mod, pty, true, GlobalValue::ExternalLinkage, cons, ""); @@ -384,11 +386,13 @@ classDef->aquire(); if (!_llvmVar) { const Type* pty = mvm::MvmModule::ptrType; + Module* Mod = classDef->vm->getLLVMModule(); + LLVMContext& Context = Mod->getContext(); Constant* cons = - ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), pty); - _llvmVar = new GlobalVariable(*(classDef->vm->getLLVMModule()), pty, true, + _llvmVar = new GlobalVariable(*Mod, pty, true, GlobalValue::ExternalLinkage, cons, ""); } @@ -401,12 +405,14 @@ if (!_llvmVar) { classDef->aquire(); if (!_llvmVar) { + Module* Mod = classDef->vm->getLLVMModule(); + LLVMContext& Context = Mod->getContext(); const Type* pty = mvm::MvmModule::ptrType; Constant* cons = - ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), pty); - _llvmVar = new GlobalVariable(*(classDef->vm->getLLVMModule()), pty, true, + _llvmVar = new GlobalVariable(*Mod, pty, true, GlobalValue::ExternalLinkage, cons, ""); Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Wed Jul 15 08:31:22 2009 @@ -164,6 +164,7 @@ static void store(Value* val, Value* local, bool vol, BasicBlock* currentBlock, mvm::MvmModule* module) { const Type* contained = local->getType()->getContainedType(0); + Function* llvmFunction = currentBlock->getParent(); if (contained->isSingleValueType()) { if (val->getType() != contained) { convertValue(val, contained, currentBlock); @@ -175,7 +176,7 @@ std::vector params; params.push_back(new BitCastInst(local, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); } else { @@ -185,15 +186,16 @@ static Value* load(Value* val, const char* name, BasicBlock* currentBlock, mvm::MvmModule* module) { const Type* contained = val->getType()->getContainedType(0); + Function* llvmFunction = currentBlock->getParent(); if (contained->isSingleValueType()) { return new LoadInst(val, name, currentBlock); } else { uint64 size = module->getTypeSize(contained); - Value* ret = new AllocaInst(contained, "", currentBlock); + Value* ret = new AllocaInst(*(llvmFunction->getContext()), contained, "", currentBlock); std::vector params; params.push_back(new BitCastInst(ret, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); return ret; @@ -228,13 +230,13 @@ #if N3_EXECUTE > 1 if (bytecodes[i] == 0xFE) { std::vector args; - args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNamesFE[bytecodes[i + 1]])); - args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod)); + args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)OpcodeNamesFE[bytecodes[i + 1]])); + args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); CallInst::Create(printExecutionLLVM, args.begin(), args.end(), "", currentBlock); } else { std::vector args; - args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]])); - args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod)); + args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]])); + args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); CallInst::Create(printExecutionLLVM, args.begin(), args.end(), "", currentBlock); } #endif @@ -703,7 +705,7 @@ uint32 index = 0; for (std::vector::iterator i = leaves.begin(), e = leaves.end(); i!= e; ++i, ++index) { - inst->addCase(ConstantInt::get(Type::Int32Ty, index), *i); + inst->addCase(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, index), *i); } //currentBlock = bb2; @@ -747,22 +749,22 @@ } case LDC_I4 : { - push(ConstantInt::get(Type::Int32Ty, readS4(bytecodes, i))); + push(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, readS4(bytecodes, i))); break; } case LDC_I8 : { - push(ConstantInt::get(Type::Int64Ty, readS8(bytecodes, i))); + push(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, readS8(bytecodes, i))); break; } case LDC_R4 : { - push(ConstantFP::get(Type::FloatTy, readFloat(bytecodes, i))); + push(llvmFunction->getContext()->getConstantFP(Type::FloatTy, readFloat(bytecodes, i))); break; } case LDC_R8 : { - push(ConstantFP::get(Type::DoubleTy, readDouble(bytecodes, i))); + push(llvmFunction->getContext()->getConstantFP(Type::DoubleTy, readDouble(bytecodes, i))); break; } @@ -817,7 +819,7 @@ } case LDC_I4_S : { - push(ConstantInt::get(Type::Int32Ty, readS1(bytecodes, i))); + push(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, readS1(bytecodes, i))); break; } @@ -952,7 +954,7 @@ } if (res) { Value* expr = ConstantExpr::getIntToPtr( - ConstantInt::get(Type::Int64Ty, + llvmFunction->getContext()->getConstantInt(Type::Int64Ty, uint64_t (leaveIndex++)), VMObject::llvmType); @@ -984,7 +986,7 @@ } if (res) { Value* expr = ConstantExpr::getIntToPtr( - ConstantInt::get(Type::Int64Ty, + llvmFunction->getContext()->getConstantInt(Type::Int64Ty, uint64_t (leaveIndex++)), VMObject::llvmType); @@ -1028,7 +1030,7 @@ case NOP : break; case NOT : { - push(BinaryOperator::CreateNot(pop(), "", currentBlock)); + push(BinaryOperator::CreateNot(*(llvmFunction->getContext()), pop(), "", currentBlock)); break; } @@ -1260,7 +1262,7 @@ sint32 index = next + offset; assert(index > 0); BasicBlock* BB = opcodeInfos[index].newBlock; - SI->addCase(ConstantInt::get(Type::Int32Ty, t), BB); + SI->addCase(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, t), BB); } break; } @@ -1300,7 +1302,7 @@ if (val->getType()->getTypeID() != Type::PointerTyID) { convertValue(val, type->naturalType, currentBlock); - Value* tmp = new AllocaInst(type->naturalType, "", currentBlock); + Value* tmp = new AllocaInst(*(llvmFunction->getContext()), type->naturalType, "", currentBlock); new StoreInst(val, tmp, false, currentBlock); val = tmp; } @@ -1311,7 +1313,7 @@ std::vector params; params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1578,7 +1580,7 @@ uint32 value = readU4(bytecodes, i); uint32 index = value & 0xfffffff; const UTF8* utf8 = compilingClass->assembly->readUserString(index); - Value* val = ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (int64_t)utf8), + Value* val = ConstantExpr::getIntToPtr(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, (int64_t)utf8), module->ptrType); Value* res = CallInst::Create(newStringLLVM, val, "", currentBlock); /*CLIString * str = @@ -1792,7 +1794,7 @@ true, genClass, genMethod); assert(type); - Value* val = new AllocaInst(type->naturalType, "", currentBlock); + Value* val = new AllocaInst(*(llvmFunction->getContext()), type->naturalType, "", currentBlock); Value* obj = pop(); if (obj->getType() != type->virtualType) { @@ -1810,7 +1812,7 @@ std::vector params; params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1922,7 +1924,7 @@ } case LOCALLOC : { - push(new AllocaInst(Type::Int8Ty, pop(), "", currentBlock)); + push(new AllocaInst(*(llvmFunction->getContext()), Type::Int8Ty, pop(), "", currentBlock)); break; } @@ -1961,7 +1963,7 @@ params.push_back(new BitCastInst(pop(), module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(ConstantInt::get(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); Modified: vmkit/trunk/lib/N3/VMCore/VMCache.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMCache.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMCache.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMCache.cpp Wed Jul 15 08:31:22 2009 @@ -92,7 +92,7 @@ Value* five = module->constantFive; Value* llvmEnv = - ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (enveloppe)), + ConstantExpr::getIntToPtr(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, uint64_t (enveloppe)), Enveloppe::llvmType); std::vector args1; Modified: vmkit/trunk/lib/N3/VMCore/VMClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMClass.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMClass.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMClass.cpp Wed Jul 15 08:31:22 2009 @@ -279,7 +279,7 @@ for (std::vector::iterator i = cl->staticFields.begin(), e = cl->staticFields.end(); i!= e; ++i) { // preincrement because 0 is VMObject - (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset); + (*i)->offset = vm->getLLVMModule()->getContext().getConstantInt(llvm::Type::Int32Ty, ++offset); } for (std::vector::iterator i = cl->staticFields.begin(), e = cl->staticFields.end(); i!= e; ++i) { @@ -329,7 +329,7 @@ uint32 offset = -1; for (std::vector::iterator i = virtualFields.begin(), e = virtualFields.end(); i!= e; ++i) { - (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset); + (*i)->offset = vm->getLLVMModule()->getContext().getConstantInt(llvm::Type::Int32Ty, ++offset); const llvm::Type* type = (*i)->signature->naturalType; Elts.push_back(type); } @@ -343,7 +343,7 @@ uint32 offset = 0; for (std::vector::iterator i = virtualFields.begin(), e = virtualFields.end(); i!= e; ++i) { - (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset); + (*i)->offset = vm->getLLVMModule()->getContext().getConstantInt(llvm::Type::Int32Ty, ++offset); const llvm::Type* type = (*i)->signature->naturalType; Elts.push_back(type); } Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=75784&r1=75783&r2=75784&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Wed Jul 15 08:31:22 2009 @@ -29,6 +29,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PassNameParser.h" #include "llvm/Support/PluginLoader.h" +#include "llvm/Support/RegistryParser.h" #include "llvm/Support/Streams.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/raw_ostream.h" @@ -37,6 +38,7 @@ #include "llvm/Target/TargetMachineRegistry.h" #include "llvm/Target/TargetMachine.h" + #include "MvmGC.h" #include "mvm/JIT.h" #include "mvm/Object.h" @@ -119,6 +121,9 @@ WithClinit("with-clinit", cl::desc("Set a property"), cl::ZeroOrMore, cl::CommaSeparated); +static cl::opt > +MArch("march", cl::desc("Architecture to generate code for:")); inline void addPass(FunctionPassManager *PM, Pass *P) { @@ -187,26 +192,36 @@ TheModule->setTargetTriple(TargetTriple); else TheModule->setTargetTriple(mvm::MvmModule::getHostTriple()); - - // Create the TargetMachine we will be generating code with. - std::string Err; - const TargetMachineRegistry::entry *TME = - TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Err); - if (!TME) { - cerr << "Did not get a target machine!\n"; - exit(1); + + + // Allocate target machine. First, check whether the user has + // explicitly specified an architecture to compile for. + const Target *TheTarget; + if (MArch) { + TheTarget = &MArch->TheTarget; + } else { + std::string Err; + TheTarget = + TargetRegistry::getClosestStaticTargetForModule(*TheModule, Err); + if (TheTarget == 0) { + std::cerr << argv[0] << ": error auto-selecting target for module '" + << Err << "'. Please use the -march option to explicitly " + << "pick a target.\n"; + return 1; + } } - std::string FeatureStr; - TargetMachine* TheTarget = TME->CtorFn(*TheModule, FeatureStr); + std::string FeaturesStr; + TargetMachine *Target = + TheTarget->createTargetMachine(*TheModule, FeaturesStr); // Install information about target datalayout stuff into the module for // optimizer use. - TheModule->setDataLayout(TheTarget->getTargetData()-> + TheModule->setDataLayout(Target->getTargetData()-> getStringRepresentation()); - mvm::MvmModule::initialise(CodeGenOpt::Default, TheModule, TheTarget); + mvm::MvmModule::initialise(CodeGenOpt::Default, TheModule, Target); } else { mvm::MvmModule::initialise(); } From nicolas.geoffray at lip6.fr Thu Jul 16 04:26:41 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 16 Jul 2009 11:26:41 -0000 Subject: [vmkit-commits] [vmkit] r75904 [1/2] - in /vmkit/trunk/mmtk: ./ java/ java/src/ java/src/org/ java/src/org/j3/ java/src/org/j3/config/ java/src/org/j3/mmtk/ java/src/org/j3/options/ java/src/org/j3/runtime/ java/src/org/jikesrvm/ java/src/org/mmtk/ java/src/org/mmtk/plan/ java/src/org/mmtk/plan/copyms/ java/src/org/mmtk/plan/generational/ java/src/org/mmtk/plan/generational/copying/ java/src/org/mmtk/plan/generational/immix/ java/src/org/mmtk/plan/generational/marksweep/ java/src/org/mmtk/plan/immix/ java/src/org/mmtk/p... Message-ID: <200907161126.n6GBQuSg016747@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 16 06:26:34 2009 New Revision: 75904 URL: http://llvm.org/viewvc/llvm-project?rev=75904&view=rev Log: Import MMTk and the VMKit interface for MMTk. Added: vmkit/trunk/mmtk/ vmkit/trunk/mmtk/java/ vmkit/trunk/mmtk/java/build.xml vmkit/trunk/mmtk/java/src/ vmkit/trunk/mmtk/java/src/org/ vmkit/trunk/mmtk/java/src/org/j3/ vmkit/trunk/mmtk/java/src/org/j3/config/ vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/ vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java vmkit/trunk/mmtk/java/src/org/j3/options/ vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java vmkit/trunk/mmtk/java/src/org/j3/runtime/ vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java vmkit/trunk/mmtk/java/src/org/jikesrvm/ vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java vmkit/trunk/mmtk/java/src/org/mmtk/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/ vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Chunk.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Line.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/MutatorLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ObjectHeader.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/BaseGenericFreeList.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/Conversions.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/CycleDetector.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/DoublyLinkedList.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/HeapGrowthManager.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Mmapper.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/PageResource.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/ vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java vmkit/trunk/mmtk/java/src/org/vmmagic/ vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Extent.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ExtentArray.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReference.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReferenceArray.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Offset.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/OffsetArray.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Word.java vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java vmkit/trunk/mmtk/java/src/org/vmutil/ vmkit/trunk/mmtk/java/src/org/vmutil/options/ vmkit/trunk/mmtk/java/src/org/vmutil/options/AddressOption.java vmkit/trunk/mmtk/java/src/org/vmutil/options/BooleanOption.java vmkit/trunk/mmtk/java/src/org/vmutil/options/EnumOption.java vmkit/trunk/mmtk/java/src/org/vmutil/options/FloatOption.java vmkit/trunk/mmtk/java/src/org/vmutil/options/IntOption.java vmkit/trunk/mmtk/java/src/org/vmutil/options/MicrosecondsOption.java vmkit/trunk/mmtk/java/src/org/vmutil/options/Option.java vmkit/trunk/mmtk/java/src/org/vmutil/options/OptionSet.java vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java vmkit/trunk/mmtk/magic/ vmkit/trunk/mmtk/magic/LowerJavaRT.cpp vmkit/trunk/mmtk/magic/LowerMagic.cpp vmkit/trunk/mmtk/magic/Makefile vmkit/trunk/mmtk/mmtk-j3/ vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp vmkit/trunk/mmtk/mmtk-j3/Assert.cpp vmkit/trunk/mmtk/mmtk-j3/Collection.cpp vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp vmkit/trunk/mmtk/mmtk-j3/Lock.cpp vmkit/trunk/mmtk/mmtk-j3/Makefile vmkit/trunk/mmtk/mmtk-j3/Memory.cpp vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp vmkit/trunk/mmtk/mmtk-j3/Selected.cpp vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp vmkit/trunk/mmtk/mmtk-j3/Strings.cpp vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp vmkit/trunk/mmtk/mmtk-j3/VM.cpp Added: vmkit/trunk/mmtk/java/build.xml URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/build.xml?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/build.xml (added) +++ vmkit/trunk/mmtk/java/build.xml Thu Jul 16 06:26:34 2009 @@ -0,0 +1,9 @@ + + + + + + + + + Added: vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,58 @@ +//===------------------------- Selected.java ------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.config; + +import org.mmtk.utility.Log; + +import org.vmmagic.pragma.*; + +public class Selected { + public static final String name = "org.mmtk.plan.marksweep.MS"; + @Uninterruptible + public static final class Plan extends org.mmtk.plan.marksweep.MS + { + private static final Plan plan = new Plan(); + + @Inline + public static Plan get() { return plan; } + } + + @Uninterruptible + public static final class Constraints extends org.mmtk.plan.marksweep.MSConstraints + { + private static final Constraints constraints = new Constraints(); + + @Inline + public static Constraints get() { return constraints; } + } + + @Uninterruptible + public static class Collector extends org.mmtk.plan.marksweep.MSCollector + { + private static final Collector bootstrapCollector = new Collector(); + + public static void staticCollect() { + bootstrapCollector.collect(); + } + + public Collector() {} + @Inline + public native static Collector get(); + } + + @Uninterruptible + public static class Mutator extends org.mmtk.plan.marksweep.MSMutator + { + private static final Mutator bootstrapThread = new Mutator(); + + @Inline + public static native Mutator get(); + } +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,70 @@ +//===---------------- ActivePlan.java - Plan for J3 -----------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + + +import org.mmtk.plan.Plan; +import org.mmtk.plan.CollectorContext; +import org.mmtk.plan.MutatorContext; +import org.mmtk.plan.PlanConstraints; +import org.mmtk.utility.Log; + +import org.j3.config.Selected; + +import org.vmmagic.pragma.*; + +public final class ActivePlan extends org.mmtk.vm.ActivePlan { + + /** @return The active Plan instance. */ + @Inline + public Plan global() { + return Selected.Plan.get(); + } + + /** @return The active PlanConstraints instance. */ + @Inline + public PlanConstraints constraints() { + return Selected.Constraints.get(); + } + + /** @return The number of registered CollectorContext instances. */ + @Inline + public native int collectorCount(); + + /** @return The active CollectorContext instance. */ + @Inline + public CollectorContext collector() { + return Selected.Collector.get(); + } + + /** @return The active MutatorContext instance. */ + @Inline + public MutatorContext mutator() { + return Selected.Mutator.get(); + } + + /** @return The log for the active thread */ + public Log log() { + return Selected.Mutator.get().getLog(); + } + + /** Reset the mutator iterator */ + public native void resetMutatorIterator(); + + /** + * Return the next MutatorContext in a + * synchronized iteration of all mutators. + * + * @return The next MutatorContext in a + * synchronized iteration of all mutators, or + * null when all mutators have been done. + */ + public native MutatorContext getNextMutator(); +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,92 @@ +//===--------------------------- Assert.java ------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +package org.j3.mmtk; + +import org.mmtk.policy.Space; +import org.vmmagic.pragma.*; +import org.j3.runtime.VM; + + at Uninterruptible +public final class Assert extends org.mmtk.vm.Assert { + + /** + * true if assertions should be verified + */ + protected final boolean getVerifyAssertionsConstant() { + return VM.VerifyAssertions; + } + + /** + * This method should be called whenever an error is encountered. + * + * @param str A string describing the error condition. + */ + public final void error(String str) { + Space.printUsagePages(); + Space.printUsageMB(); + fail(str); + } + + /** + * Logs a message and traceback, then exits. + * + * @param message the string to log + */ + public final void fail(String message) { + VM.sysFail(message); + } + + @Uninterruptible + public final void exit(int rc) { + VM.sysExit(rc); + } + + /** + * Checks that the given condition is true. If it is not, this + * method does a traceback and exits. All calls to this method + * must be guarded by VM.VERIFY_ASSERTIONS. + * + * @param cond the condition to be checked + */ + @Inline(value=Inline.When.AllArgumentsAreConstant) + public final void _assert(boolean cond) { + if (!org.mmtk.vm.VM.VERIFY_ASSERTIONS) + VM.sysFail("All assertions must be guarded by VM.VERIFY_ASSERTIONS: please check the failing assertion"); + VM._assert(cond); + } + + /** + * Checks that the given condition is true. If it is not, this + * method prints a message, does a traceback and exits. All calls + * to this method must be guarded by VM.VERIFY_ASSERTIONS. + * + * @param cond the condition to be checked + * @param message the message to print + */ + @Inline(value=Inline.When.ArgumentsAreConstant, arguments={1}) + public final void _assert(boolean cond, String message) { + if (!org.mmtk.vm.VM.VERIFY_ASSERTIONS) + VM.sysFail("All assertions must be guarded by VM.VERIFY_ASSERTIONS: please check the failing assertion"); + if (!cond) VM.sysWriteln(message); + VM._assert(cond); + } + + public native final void dumpStack(); + + /** + * Checks if the virtual machine is running. This value changes, so + * the call-through to the VM must be a method. + * + * @return true if the virtual machine is running + */ + public final boolean runningVM() { return VM.runningVM; } + +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,212 @@ +//===--------------- Barriers.java - Barriers for J3 ----------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.jikesrvm.Magic; +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +public final class Barriers extends org.mmtk.vm.Barriers { + /** + * Perform the actual write of the write barrier. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param target The value that the slot will be updated to + * @param metaDataA The offset from the ref + * @param metaDataB The index of the FieldReference + * @param mode The context in which the write is occuring + */ + @Inline + public final void performWriteInBarrier(ObjectReference ref, Address slot, + ObjectReference target, Word metaDataA, + Word metaDataB, int mode) { + Object obj = ref.toObject(); + Offset offset = metaDataA.toOffset(); + int location = metaDataB.toInt(); + Magic.setObjectAtOffset(obj, offset, target.toObject(), location); + } + + /** + * Perform the actual write of the write barrier, writing the value as a raw word. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param rawTarget The value that the slot will be updated to + * @param metaDataA The offset from the ref + * @param metaDataB The index of the FieldReference + * @param mode The context in which the write is occuring + */ + @Inline + public final void performRawWriteInBarrier(ObjectReference ref, Address slot, + Word rawTarget, Word metaDataA, + Word metaDataB, int mode) { + Object obj = ref.toObject(); + Offset offset = metaDataA.toOffset(); + int location = metaDataB.toInt(); + Magic.setWordAtOffset(obj, offset, rawTarget, location); + } + + /** + * Perform the actual read of the read barrier. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param metaDataA The offset from the ref + * @param metaDataB The index of the FieldReference + * @param mode The context in which the write is occuring + * @return the read value + */ + @Inline + public final ObjectReference performReadInBarrier(ObjectReference ref, Address slot, + Word metaDataA, Word metaDataB, int mode) { + Object obj = ref.toObject(); + Offset offset = metaDataA.toOffset(); + int location = metaDataB.toInt(); + return ObjectReference.fromObject(Magic.getObjectAtOffset(obj, offset, location)); + } + + /** + * Perform the actual read of the read barrier, returning the value as a raw word. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param metaDataA The offset from the ref + * @param metaDataB The index of the FieldReference + * @param mode The context in which the write is occuring + * @return the read value + */ + @Inline + public final Word performRawReadInBarrier(ObjectReference ref, Address slot, + Word metaDataA, Word metaDataB, int mode) { + Object obj = ref.toObject(); + Offset offset = metaDataA.toOffset(); + int location = metaDataB.toInt(); + return Magic.getWordAtOffset(obj, offset, location); + } + + /** + * Atomically write a reference field of an object or array and return + * the old value of the reference field. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param target The value that the slot will be updated to + * @param metaDataA The offset from the ref + * @param metaDataB Unused + * @param mode The context in which the write is occuring + * @return The value that was replaced by the write. + */ + @Inline + public final ObjectReference performWriteInBarrierAtomic( + ObjectReference ref, Address slot, + ObjectReference target, Word metaDataA, + Word metaDataB, int mode) { + Object obj = ref.toObject(); + Object newObject = target.toObject(); + Offset offset = metaDataA.toOffset(); + Object oldObject; + do { + oldObject = Magic.prepareObject(obj, offset); + } while (!Magic.attemptObject(obj, offset, oldObject, newObject)); + return ObjectReference.fromObject(oldObject); + } + + + /** + * Atomically write a raw reference field of an object or array and return + * the old value of the reference field. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param rawTarget The value that the slot will be updated to + * @param metaDataA The offset from the ref + * @param metaDataB Unused + * @param mode The context in which the write is occuring + * @return The value that was replaced by the write. + */ + @Inline + public final Word performRawWriteInBarrierAtomic( + ObjectReference ref, Address slot, + Word rawTarget, Word metaDataA, + Word metaDataB, int mode) { + Object obj = ref.toObject(); + Offset offset = metaDataA.toOffset(); + Word oldValue; + do { + oldValue = Magic.prepareWord(obj, offset); + } while (!Magic.attemptWord(obj, offset, oldValue, rawTarget)); + return oldValue; + } + + /** + * Attempt an atomic compare and exchange in a write barrier sequence. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param old The old reference to be swapped out + * @param target The value that the slot will be updated to + * @param metaDataA The offset from the ref + * @param metaDataB Unused + * @param mode The context in which the write is occuring + * @return True if the compare and swap was successful + */ + @Inline + public final boolean tryCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot, + ObjectReference old, ObjectReference target, + Word metaDataA, Word metaDataB, int mode) { + Object oldValue; + Offset offset = metaDataA.toOffset(); + do { + oldValue = Magic.prepareObject(ref, offset); + if (oldValue != old) return false; + } while (!Magic.attemptObject(ref, offset, oldValue, target)); + return true; + } + + + /** + * Attempt an atomic compare and exchange in a write barrier sequence. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param rawOld The old reference to be swapped out + * @param rawTarget The value that the slot will be updated to + * @param metaDataA The offset from the ref + * @param metaDataB Unused + * @param mode The context in which the write is occuring + * @return True if the compare and swap was successful + */ + @Inline + public final boolean tryRawCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot, + Word rawOld, Word rawTarget, Word metaDataA, + Word metaDataB, int mode) { + Offset offset = metaDataA.toOffset(); + do { + Word currentValue = Magic.prepareWord(ref, offset); + if (currentValue != rawOld) return false; + } while (!Magic.attemptObject(ref, offset, rawOld, rawTarget)); + return true; + } + + /** + * Sets an element of an object array without invoking any write + * barrier. This method is called by the Map class to ensure + * potentially-allocation-triggering write barriers do not occur in + * allocation slow path code. + * + * @param dst the destination array + * @param index the index of the element to set + * @param value the new value for the element + */ + public final void setArrayNoBarrier(Object [] dst, int index, Object value) { + dst[index] = value; + } +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,128 @@ +//===---------------------- BuildTimeConfig.java --------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; + +import org.j3.runtime.VM; +import org.j3.config.Selected; + +/** + * Read build-time configuration information for MMTk from a Java properties + * file. Properties read through this mechanism should be read at build time + * and saved in static final fields. + * + * This is a wrapper for a java.util.Properties object. + */ +public final class BuildTimeConfig extends org.mmtk.vm.BuildTimeConfig { + + /** + * The underlying properties object + */ + private Properties props; + + public BuildTimeConfig(String property_file_property, String default_property_file) { + props = getProperties(property_file_property,default_property_file); + } + + public BuildTimeConfig(String property_file_property) { + props = getProperties(property_file_property,null); + } + + /** + * @param property_file_property The name of the property that sets + * the location of the properties file + * @param default_property_file The default properties file. + * + */ + private Properties getProperties(String property_file_property, String default_property_file) { + Properties props = new Properties(); + return props; + /*String propFileName; + if (default_property_file == null) { + propFileName = System.getProperty(property_file_property); + if (propFileName == null) { + System.err.println(property_file_property+" must specify a properties file"); + VM.sysExit(1); + } + } else { + propFileName = System.getProperty(property_file_property, default_property_file); + } + File propFile = new File(propFileName); + + try { + BufferedInputStream propFileStream = new BufferedInputStream(new FileInputStream(propFile)); + props.load(propFileStream); + propFileStream.close(); + } catch (FileNotFoundException e) { + if (!propFileName.equals(default_property_file)) { + System.err.println(propFileName+" not found."); + VM.sysExit(1); + } + } catch (IOException e) { + e.printStackTrace(); + VM.sysExit(1); + } + return props;*/ + } + + @Override + public String getPlanName() { + return Selected.name; + } + + @Override + public boolean getBooleanProperty(String name, boolean dflt) { + String value = props.getProperty(name,Boolean.toString(dflt)); + return Boolean.valueOf(value); + } + + @Override + public boolean getBooleanProperty(String name) { + String value = props.getProperty(name); + if (value == null) + throw new RuntimeException("Undefined property "+name); + return Boolean.valueOf(value); + } + + @Override + public int getIntProperty(String name, int dflt) { + String value = props.getProperty(name,Integer.toString(dflt)); + return Integer.valueOf(value); + } + + @Override + public int getIntProperty(String name) { + String value = props.getProperty(name); + if (value == null) + throw new RuntimeException("Undefined property "+name); + return Integer.valueOf(value); + } + + @Override + public String getStringProperty(String name, String dflt) { + return props.getProperty(name,dflt); + } + + @Override + public String getStringProperty(String name) { + String value = props.getProperty(name); + if (value == null) + throw new RuntimeException("Undefined property "+name); + return value; + } + + +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,120 @@ +//===------------------------- Collection.java ----------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.CollectorContext; +import org.mmtk.plan.MutatorContext; +import org.mmtk.utility.options.Options; + +import org.vmmagic.pragma.Inline; +import org.vmmagic.pragma.Interruptible; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.pragma.UninterruptibleNoWarn; +import org.vmmagic.pragma.Unpreemptible; +import org.vmmagic.unboxed.Address; + + at Uninterruptible +public final class Collection extends org.mmtk.vm.Collection { + + /** + * Triggers a collection. + * + * @param why the reason why a collection was triggered. 0 to + * TRIGGER_REASONS - 1. + */ + @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process") + public native final void triggerCollection(int why); + + /** + * Joins a collection. + */ + @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process") + public native final void joinCollection(); + + /** + * The maximum number collection attempts across threads. + */ + public native int maximumCollectionAttempt(); + + /** + * Report that the the physical allocation has succeeded. + */ + public native void reportAllocationSuccess(); + + /** + * Report that a physical allocation has failed. + */ + public native void reportPhysicalAllocationFailed(); + + /** + * Does the VM consider this an emergency allocation, where the normal + * heap size rules can be ignored. + */ + public native boolean isEmergencyAllocation(); + + /** + * Trigger an asynchronous collection, checking for memory + * exhaustion first. + */ + @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process") + public native final void triggerAsyncCollection(int why); + + /** + * Determine whether a collection cycle has fully completed (this is + * used to ensure a GC is not in the process of completing, to + * avoid, for example, an async GC being triggered on the switch + * from GC to mutator thread before all GC threads have switched. + * + * @return True if GC is not in progress. + */ + @Uninterruptible + public native final boolean noThreadsInGC(); + + /** + * Prepare a mutator for a collection. + * + * @param m the mutator to prepare + */ + public native final void prepareMutator(MutatorContext m); + + /** + * Prepare a collector for a collection. + * + * @param c the collector to prepare + */ + public native final void prepareCollector(CollectorContext c); + + /** + * Rendezvous with all other processors, returning the rank + * (that is, the order this processor arrived at the barrier). + */ + public native final int rendezvous(int where); + + // REVIEW: what are the semantics of this method in a concurrent collector? + /** @return The number of active collector threads */ + public native final int activeGCThreads(); + + /** + * @return The ordinal ID of the running collector thread w.r.t. + * the set of active collector threads (zero based) + */ + public native final int activeGCThreadOrdinal(); + + /** + * Request each mutator flush remembered sets. This method + * will trigger the flush and then yield until all processors have + * flushed. + */ + @UninterruptibleNoWarn("This method is really unpreemptible, since it involves blocking") + public native void requestMutatorFlush(); + +} + Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +//===--------------------------- Debug.java -------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.vmmagic.pragma.Uninterruptible; + +/** + * Debugger support for the MMTk harness + */ + at Uninterruptible +public final class Debug extends org.mmtk.vm.Debug { + + /** + * Enable/disable MMTk debugger support + */ + @Override + public boolean isEnabled() { + return false; + } + +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,501 @@ +//===-------------------------- Factory.java ------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.vmutil.options.OptionSet; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.vm.ReferenceProcessor.Semantics; + +import org.j3.runtime.VM; + +/** + * This is a VM-specific class which defines factory methods for + * VM-specific types which must be instantiated within MMTk. + * + * @see org.mmtk.vm.Factory + */ +public final class Factory extends org.mmtk.vm.Factory { + + private static final String DEFAULT_MMTK_PROPERTIES = ".mmtk.properties"; + private static final String CONFIG_FILE_PROPERTY = "mmtk.properties"; + + /** + * Create or retrieve the OptionSet used for MMTk options. + * + * @return A concrete VM-specific OptionSet instance + */ + public OptionSet getOptionSet() { + return org.j3.options.OptionSet.gc; + } + + /** + * Create a new ActivePlan instance using the appropriate VM-specific + * concrete ActivePlan sub-class. + * + * @see ActivePlan + * @return A concrete VM-specific ActivePlan instance. + */ + public org.mmtk.vm.ActivePlan newActivePlan() { + try { + return new ActivePlan(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new ActivePlan!"); + return null; // never get here + } + } + + /** + * Create a new Assert instance using the appropriate VM-specific + * concrete Assert sub-class. + * + * @see Assert + * @return A concrete VM-specific Assert instance. + */ + public org.mmtk.vm.Assert newAssert() { + try { + return new Assert(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Assert!"); + return null; // never get here + } + } + + /** + * Create a new Barriers instance using the appropriate VM-specific + * concrete Barriers sub-class. + * + * @see Barriers + * @return A concrete VM-specific Barriers instance. + */ + public org.mmtk.vm.Barriers newBarriers() { + try { + return new Barriers(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Barriers!"); + return null; // never get here + } + } + + /** + * Create a new Collection instance using the appropriate VM-specific + * concrete Collection sub-class. + * + * @see Collection + * @return A concrete VM-specific Collection instance. + */ + public org.mmtk.vm.Collection newCollection() { + try { + return new Collection(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Collection!"); + return null; // never get here + } + } + + /** + * Create a new BuildTimeConfig instance using the appropriate VM-specific + * concrete BuildTimeConfig sub-class. + * + * @see Collection + * @return A concrete VM-specific Collection instance. + */ + public org.mmtk.vm.BuildTimeConfig newBuildTimeConfig() { + try { + return new BuildTimeConfig(CONFIG_FILE_PROPERTY, DEFAULT_MMTK_PROPERTIES); + } catch (Exception e) { + VM.sysFail("Failed to allocate new BuildTimeConfiguration!"); + return null; // never get here + } + } + + /** + * Create a new Lock instance using the appropriate VM-specific + * concrete Lock sub-class. + * + * @see Lock + * + * @param name The string to be associated with this lock instance + * @return A concrete VM-specific Lock instance. + */ + public org.mmtk.vm.Lock newLock(String name) { + try { + return new Lock(name); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Lock!"); + return null; // never get here + } + } + + /** + * Create a new Memory instance using the appropriate VM-specific + * concrete Memory sub-class. + * + * @see Memory + * @return A concrete VM-specific Memory instance. + */ + public org.mmtk.vm.Memory newMemory() { + try { + return new Memory(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Memory!"); + return null; // never get here + } + } + + /** + * Create a new ObjectModel instance using the appropriate VM-specific + * concrete ObjectModel sub-class. + * + * @see ObjectModel + * @return A concrete VM-specific ObjectModel instance. + */ + public org.mmtk.vm.ObjectModel newObjectModel() { + try { + return new ObjectModel(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new ObjectModel!"); + return null; // never get here + } + } + + /** + * Create a new ReferenceProcessor instance using the appropriate VM-specific + * concrete ReferenceProcessor sub-class. + * + * @see ReferenceProcessor + * @return A concrete VM-specific ReferenceProcessor instance. + */ + public org.mmtk.vm.ReferenceProcessor newReferenceProcessor(Semantics semantics) { + try { + return ReferenceProcessor.get(semantics); + } catch (Exception e) { + VM.sysFail("Failed to allocate new ReferenceProcessor!"); + return null; // never get here + } + } + + /** + * Create a new FinalizableProcessor instance using the appropriate VM-specific + * concrete FinalizableProcessor sub-class. + * + * @see ReferenceProcessor + * @return A concrete VM-specific FinalizableProcessor instance. + */ + public org.mmtk.vm.FinalizableProcessor newFinalizableProcessor() { + try { + return FinalizableProcessor.getProcessor(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new FinalizableProcessor!"); + return null; // never get here + } + } + + /** + * Create a new Scanning instance using the appropriate VM-specific + * concrete Scanning sub-class. + * + * @see Scanning + * @return A concrete VM-specific Scanning instance. + */ + public org.mmtk.vm.Scanning newScanning() { + try { + return new Scanning(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Scanning!"); + return null; // never get here + } + } + + /** + * Create a new Statistics instance using the appropriate VM-specific + * concrete Statistics sub-class. + * + * @see Statistics + * @return A concrete VM-specific Statistics instance. + */ + public org.mmtk.vm.Statistics newStatistics() { + try { + return new Statistics(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Statistics!"); + return null; // never get here + } + } + + /** + * Create a new Strings instance using the appropriate VM-specific + * concrete Strings sub-class. + * + * @see Strings + * @return A concrete VM-specific Strings instance. + */ + public org.mmtk.vm.Strings newStrings() { + try { + return new Strings(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new Strings!"); + return null; // never get here + } + } + + /** + * Create a new SynchronizedCounter instance using the appropriate + * VM-specific concrete SynchronizedCounter sub-class. + * + * @see SynchronizedCounter + * + * @return A concrete VM-specific SynchronizedCounter instance. + */ + public org.mmtk.vm.SynchronizedCounter newSynchronizedCounter() { + try { + return new SynchronizedCounter(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new SynchronizedCounter!"); + return null; // never get here + } + } + + /** + * Create a new TraceInterface instance using the appropriate VM-specific + * concrete TraceInterface sub-class. + * + * @see TraceInterface + * @return A concrete VM-specific TraceInterface instance. + */ + public org.mmtk.vm.TraceInterface newTraceInterface() { + try { + return new TraceInterface(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new TraceInterface!"); + return null; // never get here + } + } + + /** + * Create a new MMTk_Events instance using the appropriate VM-specific + * concrete MMTk_Events sub-class. + * + * @see MMTk_Events + * @return A concrete VM-specific MMTk_Events instance. + */ + public org.mmtk.vm.MMTk_Events newEvents() { + try { + return new MMTk_Events(); + } catch (Exception e) { + VM.sysFail("Failed to allocate new MMTk_Events!"); + return null; // never get here + } + } + + public org.mmtk.vm.Debug newDebug() { + return new Debug(); + } + + /********************************************************************** + * GCspy methods + */ + + /** + * Create a new Util instance using the appropriate VM-specific + * concrete Util sub-class. + * + * @see org.mmtk.vm.gcspy.Util + * @return A concrete VM-specific Util instance. + */ + public org.mmtk.vm.gcspy.Util newGCspyUtil() { + try { + return null; + } catch (Exception e) { + VM.sysFail("Failed to allocate new Util!"); + return null; // never get here + } + } + + /** + * Create a new ServerInterpreter instance using the appropriate VM-specific + * concrete ServerInterpreter sub-class. + * + * @see org.mmtk.vm.gcspy.ServerInterpreter + * @return A concrete VM-specific ServerInterpreter instance. + */ + public org.mmtk.vm.gcspy.ServerInterpreter newGCspyServerInterpreter() { + try { + return null; + } catch (Exception e) { + VM.sysFail("Failed to allocate new ServerInterpreter!"); + return null; // never get here + } + } + + /** + * Create a new ServerSpace instance using the appropriate VM-specific + * concrete ServerSpace sub-class. + * + * @param serverInterpreter The server that owns this space + * @param serverName The server's name + * @param driverName The space driver's name + * @param title Title for the space + * @param blockInfo A label for each block + * @param tileNum Max number of tiles in this space + * @param unused A label for unused blocks + * @param mainSpace Whether this space is the main space + * + * @see org.mmtk.vm.gcspy.ServerSpace + * @return A concrete VM-specific ServerSpace instance. + */ + public org.mmtk.vm.gcspy.ServerSpace newGCspyServerSpace( + org.mmtk.vm.gcspy.ServerInterpreter serverInterpreter, + String serverName, + String driverName, + String title, + String blockInfo, + int tileNum, + String unused, + boolean mainSpace){ + try { + return null; + } catch (Exception e) { + VM.sysFail("Failed to allocate new ServerSpace!"); + return null; // never get here + } + } + + /** + * Create a new ByteStream instance using the appropriate + * VM-specific concrete ByteStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see org.mmtk.vm.gcspy.IntStream + * + * @return A concrete VM-specific ByteStream instance. + */ + public org.mmtk.vm.gcspy.ByteStream newGCspyByteStream( + AbstractDriver driver, + String name, + byte minValue, + byte maxValue, + byte zeroValue, + byte defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + try { + return null; + } catch (Exception e) { + VM.sysFail("Failed to allocate new ByteStream!"); + return null; // never get here + } + } + /** + * Create a new IntStream instance using the appropriate + * VM-specific concrete IntStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see org.mmtk.vm.gcspy.IntStream + * + * @return A concrete VM-specific IntStream instance. + */ + public org.mmtk.vm.gcspy.IntStream newGCspyIntStream( + AbstractDriver driver, + String name, + int minValue, + int maxValue, + int zeroValue, + int defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + try { + return null; + } catch (Exception e) { + VM.sysFail("Failed to allocate new IntStream!"); + return null; // never get here + } + } + + /** + * Create a new ShortStream instance using the appropriate + * VM-specific concrete ShortStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see org.mmtk.vm.gcspy.IntStream + * + * @return A concrete VM-specific ShortStream instance. + */ + public org.mmtk.vm.gcspy.ShortStream newGCspyShortStream( + AbstractDriver driver, + String name, + short minValue, + short maxValue, + short zeroValue, + short defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + try { + return null; + } catch (Exception e) { + VM.sysFail("Failed to allocate new ShortStream!"); + return null; // never get here + } + } +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,68 @@ +//===---------------------- FinalizableProcessor.java ---------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +import org.j3.runtime.VM; +import org.j3.config.Selected; +import org.mmtk.plan.TraceLocal; + +/** + * This class manages the processing of finalizable objects. + */ + + at Uninterruptible +public final class FinalizableProcessor extends org.mmtk.vm.FinalizableProcessor { + + /******************************************************************** + * Class fields + */ + + /** The FinalizableProcessor singleton */ + private static final FinalizableProcessor finalizableProcessor = new FinalizableProcessor(); + + public static FinalizableProcessor getProcessor() { + return finalizableProcessor; + } + + public native void clear(); + + /** + * Scan through all entries in the table and forward. + * + * Currently ignores the nursery hint. + * + * TODO parallelise this code? + * + * @param trace The trace + * @param nursery Is this a nursery collection ? + */ + @Override + public native void forward(TraceLocal trace, boolean nursery); + + /** + * Scan through the list of references. Calls ReferenceProcessor's + * processReference method for each reference and builds a new + * list of those references still active. + * + * Depending on the value of nursery, we will either + * scan all references, or just those created since the last scan. + * + * TODO parallelise this code + * + * @param nursery Scan only the newly created references + */ + @Override + @UninterruptibleNoWarn + public native void scan(TraceLocal trace, boolean nursery); + +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,39 @@ +//===--------------------------- Lock.java --------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + at Uninterruptible public class Lock extends org.mmtk.vm.Lock { + + private int state; + private String name; // logical name of lock + + // Diagnosis Instance fields + public Lock(String name) { + this(); + this.name = name; + } + + public Lock() { + state = 0; + } + + public void setName(String str) { + name = str; + } + + public native void acquire(); + + public native void check(int w); + + public native void release(); +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +//===-------------------- --- MMTk_Events.java ----------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.mmtk.policy.Space; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Extent; + +/** + * Implementation of simple MMTK event generation hooks + * to allow MMTk to generate TuningFork events. + */ + at Uninterruptible +public class MMTk_Events extends org.mmtk.vm.MMTk_Events { + + public void tracePageAcquired(Space space, Address startAddress, int numPages) { + } + + public void tracePageReleased(Space space, Address startAddress, int numPages) { + } + + public void heapSizeChanged(Extent heapSize) { + } +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,147 @@ +//===-------------------------- Memory.java -------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.mmtk.plan.Plan; +import org.mmtk.policy.ImmortalSpace; +import org.mmtk.utility.Constants; +import org.mmtk.utility.heap.VMRequest; + +import org.j3.runtime.VM; +import org.jikesrvm.Magic; +import org.jikesrvm.SizeConstants; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + at Uninterruptible +public final class Memory extends org.mmtk.vm.Memory { + + protected native final Address getHeapStartConstant(); + protected native final Address getHeapEndConstant(); + protected native final Address getAvailableStartConstant(); + protected native final Address getAvailableEndConstant(); + protected final byte getLogBytesInAddressConstant() { return (byte)SizeConstants.LOG_BYTES_IN_ADDRESS; } + protected final byte getLogBytesInWordConstant() { return (byte)SizeConstants.LOG_BYTES_IN_WORD; } + protected final byte getLogBytesInPageConstant() { return (byte)SizeConstants.LOG_BYTES_IN_PAGE; } + protected final byte getLogMinAlignmentConstant() { return (byte)SizeConstants.LOG_BYTES_IN_INT;} + protected final int getMaxBytesPaddingConstant() { return (byte)SizeConstants.BYTES_IN_DOUBLE; } + protected final int getAlignmentValueConstant() { return 0xdeadbeef; } + + /* On Intel we align code to 16 bytes as recommended in the optimization manual */ + protected final byte getMaxAlignmentShiftConstant() { + return (byte)((VM.BuildForIA32 ? 1 : 0) + SizeConstants.LOG_BYTES_IN_LONG - SizeConstants.LOG_BYTES_IN_INT); + } + + private static ImmortalSpace bootSpace; + + /** + * Return the space associated with/reserved for the VM. + */ + @Interruptible + public final ImmortalSpace getVMSpace() { + if (bootSpace == null) { + bootSpace = new ImmortalSpace("boot", Plan.DEFAULT_POLL_FREQUENCY, VMRequest.create()); + } + return bootSpace; + } + + /** Global preparation for a collection. */ + public final void globalPrepareVMSpace() { bootSpace.prepare(); } + + /** Per-collector preparation for a collection. */ + public final void collectorPrepareVMSpace() {} + + /** Per-collector post-collection work. */ + public final void collectorReleaseVMSpace() {} + + /** Global post-collection work. */ + public final void globalReleaseVMSpace() { bootSpace.release(); } + + /** + * Sets the range of addresses associated with a heap. + * + * @param id the heap identifier + * @param start the address of the start of the heap + * @param end the address of the end of the heap + */ + public final void setHeapRange(int id, Address start, Address end) {} + + /** + * Demand zero mmaps an area of virtual memory. + * + * @param start the address of the start of the area to be mapped + * @param size the size, in bytes, of the area to be mapped + * @return 0 if successful, otherwise the system errno + */ + public native final int dzmmap(Address start, int size); + + /** + * Protects access to an area of virtual memory. + * + * @param start the address of the start of the area to be mapped + * @param size the size, in bytes, of the area to be mapped + * @return true if successful, otherwise + * false + */ + public native final boolean mprotect(Address start, int size); + + /** + * Allows access to an area of virtual memory. + * + * @param start the address of the start of the area to be mapped + * @param size the size, in bytes, of the area to be mapped + * @return true if successful, otherwise + * false + */ + public native final boolean munprotect(Address start, int size); + + /** + * Zero a region of memory. + * @param start Start of address range (inclusive) + * @param len Length in bytes of range to zero + * Returned: nothing + */ + public native final void zero(Address start, Extent len); + + /** + * Zero a range of pages of memory. + * @param start Start of address range (must be a page address) + * @param len Length in bytes of range (must be multiple of page size) + */ + public native final void zeroPages(Address start, int len); + + /** + * Logs the contents of an address and the surrounding memory to the + * error output. + * + * @param start the address of the memory to be dumped + * @param beforeBytes the number of bytes before the address to be + * included + * @param afterBytes the number of bytes after the address to be + * included + */ + public native final void dumpMemory(Address start, int beforeBytes, + int afterBytes); + + /* + * Utilities from the VM class + */ + + @Inline + public final void sync() { + Magic.sync(); + } + + @Inline + public final void isync() { + Magic.isync(); + } +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,237 @@ +//===------------------------ ObjectModel.java ----------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + at Uninterruptible +public final class ObjectModel extends org.mmtk.vm.ObjectModel { + + protected native Offset getArrayBaseOffset(); + + /** + * Copy an object using a plan's allocCopy to get space and install + * the forwarding pointer. On entry, from must have + * been reserved for copying by the caller. This method calls the + * plan's getStatusForCopy() method to establish a new + * status word for the copied object and postCopy() to + * allow the plan to perform any post copy actions. + * + * @param from the address of the object to be copied + * @return the address of the new object + */ + @Inline + public native ObjectReference copy(ObjectReference from, int allocator); + + /** + * Copy an object to be pointer to by the to address. This is required + * for delayed-copy collectors such as compacting collectors. During the + * collection, MMTk reserves a region in the heap for an object as per + * requirements found from ObjectModel and then asks ObjectModel to + * determine what the object's reference will be post-copy. + * + * @param from the address of the object to be copied + * @param to The target location. + * @param region The start (or an address less than) the region that was reserved for this object. + * @return Address The address past the end of the copied object + */ + @Inline + public native Address copyTo(ObjectReference from, ObjectReference to, Address region); + + /** + * Return the reference that an object will be refered to after it is copied + * to the specified region. Used in delayed-copy collectors such as compacting + * collectors. + * + * @param from The object to be copied. + * @param to The region to be copied to. + * @return The resulting reference. + */ + public native ObjectReference getReferenceWhenCopiedTo(ObjectReference from, Address to); + + /** + * Gets a pointer to the address just past the end of the object. + * + * @param object The object. + */ + public native Address getObjectEndAddress(ObjectReference object); + + /** + * Return the size required to copy an object + * + * @param object The object whose size is to be queried + * @return The size required to copy obj + */ + public native int getSizeWhenCopied(ObjectReference object); + + /** + * Return the alignment requirement for a copy of this object + * + * @param object The object whose size is to be queried + * @return The alignment required for a copy of obj + */ + public native int getAlignWhenCopied(ObjectReference object); + + /** + * Return the alignment offset requirements for a copy of this object + * + * @param object The object whose size is to be queried + * @return The alignment offset required for a copy of obj + */ + public native int getAlignOffsetWhenCopied(ObjectReference object); + + /** + * Return the size used by an object + * + * @param object The object whose size is to be queried + * @return The size of obj + */ + public native int getCurrentSize(ObjectReference object); + + /** + * Return the next object in the heap under contiguous allocation + */ + public native ObjectReference getNextObject(ObjectReference object); + + /** + * Return an object reference from knowledge of the low order word + */ + public native ObjectReference getObjectFromStartAddress(Address start); + + /** + * Get the type descriptor for an object. + * + * @param ref address of the object + * @return byte array with the type descriptor + */ + public native byte [] getTypeDescriptor(ObjectReference ref); + + @Inline + public native int getArrayLength(ObjectReference object); + + /** + * Is the passed object an array? + * + * @param object address of the object + */ + public native boolean isArray(ObjectReference object); + + /** + * Is the passed object a primitive array? + * + * @param object address of the object + */ + public native boolean isPrimitiveArray(ObjectReference object); + + /** + * Attempts to set the bits available for memory manager use in an + * object. The attempt will only be successful if the current value + * of the bits matches oldVal. The comparison with the + * current value and setting are atomic with respect to other + * allocators. + * + * @param object the address of the object + * @param oldVal the required current value of the bits + * @param newVal the desired new value of the bits + * @return true if the bits were set, + * false otherwise + */ + public native boolean attemptAvailableBits(ObjectReference object, + Word oldVal, Word newVal); + + /** + * Gets the value of bits available for memory manager use in an + * object, in preparation for setting those bits. + * + * @param object the address of the object + * @return the value of the bits + */ + public native Word prepareAvailableBits(ObjectReference object); + + /** + * Sets the byte available for memory manager use in an object. + * + * @param object the address of the object + * @param val the new value of the byte + */ + public native void writeAvailableByte(ObjectReference object, byte val); + + /** + * Read the byte available for memory manager use in an object. + * + * @param object the address of the object + * @return the value of the byte + */ + public native byte readAvailableByte(ObjectReference object); + + /** + * Sets the bits available for memory manager use in an object. + * + * @param object the address of the object + * @param val the new value of the bits + */ + public native void writeAvailableBitsWord(ObjectReference object, Word val); + + /** + * Read the bits available for memory manager use in an object. + * + * @param object the address of the object + * @return the value of the bits + */ + public native Word readAvailableBitsWord(ObjectReference object); + + /** + * Gets the offset of the memory management header from the object + * reference address. XXX The object model / memory manager + * interface should be improved so that the memory manager does not + * need to know this. + * + * @return the offset, relative the object reference address + */ + /* AJG: Should this be a variable rather than method? */ + public native Offset GC_HEADER_OFFSET(); + + /** + * Returns the lowest address of the storage associated with an object. + * + * @param object the reference address of the object + * @return the lowest address of the object + */ + @Inline + public native Address objectStartRef(ObjectReference object); + + /** + * Returns an address guaranteed to be inside the storage assocatied + * with and object. + * + * @param object the reference address of the object + * @return an address inside the object + */ + public native Address refToAddress(ObjectReference object); + + /** + * Checks if a reference of the given type in another object is + * inherently acyclic. + * + * @return true if a reference of the type is + * inherently acyclic + */ + @Inline + public native boolean isAcyclic(ObjectReference typeRef); + + /** + * Dump debugging information for an object. + * + * @param object The object whose information is to be dumped + */ + public native void dumpObject(ObjectReference object); +} + Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,103 @@ +//===--------------------- ReferenceProcessor.java ------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +package org.j3.mmtk; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.utility.options.Options; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +import org.j3.runtime.VM; + + at Uninterruptible +public final class ReferenceProcessor extends org.mmtk.vm.ReferenceProcessor { + + /******************************************************************** + * Class fields + */ + + private static final ReferenceProcessor softReferenceProcessor = + new ReferenceProcessor(Semantics.SOFT); + private static final ReferenceProcessor weakReferenceProcessor = + new ReferenceProcessor(Semantics.WEAK); + private static final ReferenceProcessor phantomReferenceProcessor = + new ReferenceProcessor(Semantics.PHANTOM); + + private final Semantics semantics; + + private ReferenceProcessor(Semantics semantics) { + this.semantics = semantics; + } + + /** + * Factory method. + * Creates an instance of the appropriate reference type processor. + * @return the reference processor + */ + @Interruptible + public static ReferenceProcessor get(Semantics semantics) { + switch(semantics) { + case WEAK: return weakReferenceProcessor; + case SOFT: return softReferenceProcessor; + case PHANTOM: return phantomReferenceProcessor; + default: + VM._assert(false,"Unrecognized semantics"); + return null; + } + } + + /** + * Scan through all references and forward. + * + * Collectors like MarkCompact determine liveness and move objects + * using separate traces. + * + * Currently ignores the nursery hint. + * + * TODO parallelise this code + * + * @param trace The trace + * @param nursery Is this a nursery collection ? + */ + @Override + public native void forward(TraceLocal trace, boolean nursery); + + /** + * Clear the contents of the table. This is called when reference types are + * disabled to make it easier for VMs to change this setting at runtime. + */ + @Override + public native void clear(); + + /** + * Scan through the list of references. Calls ReferenceProcessor's + * processReference method for each reference and builds a new + * list of those references still active. + * + * Depending on the value of nursery, we will either + * scan all references, or just those created since the last scan. + * + * TODO parallelise this code + * + * @param nursery Scan only the newly created references + */ + @Override + public native void scan(TraceLocal trace, boolean nursery); + + /*********************************************************************** + * + * Statistics and debugging + */ + + public native int countWaitingReferences(); +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,145 @@ +//===------------------------- Scanning.java ------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.TransitiveClosure; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + at Uninterruptible +public final class Scanning extends org.mmtk.vm.Scanning { + + @Inline + public native void scanObject(TransitiveClosure trace, ObjectReference object); + + /** + * Invoke a specialized scan method. Note that these methods must have been allocated + * explicitly through Plan and PlanConstraints. + * + * @param id The specialized method id + * @param trace The trace the method has been specialized for + * @param object The object to be scanned + */ + @Inline + public native void specializedScanObject(int id, TransitiveClosure trace, ObjectReference object); + + + /** + * Precopying of a object's fields, processing each pointer field encountered. + * + * @param trace The trace being used. + * @param object The object to be scanned. + */ + @Inline + public native void precopyChildren(TraceLocal trace, ObjectReference object); + + /** + * Prepares for using the computeAllRoots method. The + * thread counter allows multiple GC threads to co-operatively + * iterate through the thread data structure (if load balancing + * parallel GC threads were not important, the thread counter could + * simply be replaced by a for loop). + */ + public native void resetThreadCounter(); + + /** + * Pre-copy all potentially movable instances used in the course of + * GC. This includes the thread objects representing the GC threads + * themselves. It is crucial that these instances are forwarded + * prior to the GC proper. Since these instances are + * not enqueued for scanning, it is important that when roots + * are computed the same instances are explicitly scanned and + * included in the set of roots. The existence of this method + * allows the actions of calculating roots and forwarding GC + * instances to be decoupled. + * + * The thread table is scanned in parallel by each processor, by striding + * through the table at a gap of chunkSize*numProcs. Feel free to adjust + * chunkSize if you want to tune a parallel collector. + * + * Explicitly no-inlined to prevent over-inlining of collectionPhase. + * + * TODO Experiment with specialization to remove virtual dispatch ? + */ + @NoInline + public native void preCopyGCInstances(TraceLocal trace); + + /** + * Computes static roots. This method establishes all such roots for + * collection and places them in the root locations queue. This method + * should not have side effects (such as copying or forwarding of + * objects). There are a number of important preconditions: + * + *
    + *
  • All objects used in the course of GC (such as the GC thread + * objects) need to be "pre-copied" prior to calling this method. + *
  • The threadCounter must be reset so that load + * balancing parallel GC can share the work of scanning threads. + *
+ * + * @param trace The trace to use for computing roots. + */ + public native void computeStaticRoots(TraceLocal trace); + + /** + * Computes global roots. This method establishes all such roots for + * collection and places them in the root locations queue. This method + * should not have side effects (such as copying or forwarding of + * objects). There are a number of important preconditions: + * + *
    + *
  • All objects used in the course of GC (such as the GC thread + * objects) need to be "pre-copied" prior to calling this method. + *
  • The threadCounter must be reset so that load + * balancing parallel GC can share the work of scanning threads. + *
+ * + * @param trace The trace to use for computing roots. + */ + public native void computeGlobalRoots(TraceLocal trace); + + /** + * Computes roots pointed to by threads, their associated registers + * and stacks. This method places these roots in the root values, + * root locations and interior root locations queues. This method + * should not have side effects (such as copying or forwarding of + * objects). There are a number of important preconditions: + * + *
    + *
  • All objects used in the course of GC (such as the GC thread + * objects) need to be "pre-copied" prior to calling this method. + *
  • The threadCounter must be reset so that load + * balancing parallel GC can share the work of scanning threads. + *
+ * + * TODO rewrite to avoid the per-thread synchronization, like precopy. + * + * @param trace The trace to use for computing roots. + */ + public native void computeThreadRoots(TraceLocal trace); + + /** + * Compute all roots out of the VM's boot image (if any). This method is a no-op + * in the case where the VM does not maintain an MMTk-visible Java space. However, + * when the VM does maintain a space (such as a boot image) which is visible to MMTk, + * that space could either be scanned by MMTk as part of its transitive closure over + * the whole heap, or as a (considerable) performance optimization, MMTk could avoid + * scanning the space if it is aware of all pointers out of that space. This method + * is used to establish the root set out of the scannable space in the case where + * such a space exists. + * + * @param trace The trace object to use to report root locations. + */ + public void computeBootImageRoots(TraceLocal trace) { + } +} + Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,89 @@ +//===------------------------ Statistics.java -----------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.vmmagic.pragma.*; + + at Uninterruptible +public final class Statistics extends org.mmtk.vm.Statistics { + /** + * Returns the number of collections that have occurred. + * + * @return The number of collections that have occurred. + */ + @Uninterruptible + public native int getCollectionCount(); + + /** + * Read nanoTime (high resolution, monotonically increasing clock). + * Has same semantics as java.lang.System.nanoTime(). + */ + public native long nanoTime(); + + /** + * Read a cycle counter (high resolution, non-monotonic clock). + * This method should be used with care as the cycle counters (especially on IA32 SMP machines) + * are not a reliably time source. + */ + public native long cycles(); + + /** + * Convert nanoseconds to milliseconds + */ + public double nanosToMillis(long c) { + return ((double)c)/1e6; + } + + /** + * Convert nanoseconds to seconds + */ + public double nanosToSecs(long c) { + return ((double)c)/1e9; + } + + /** + * Convert milliseconds to nanoseconds + */ + public long millisToNanos(double t) { + return (long)(t * 1e6); + } + + /** + * Convert seconds to nanoseconds + */ + public long secsToNanos(double t) { + return (long)(t * 1e9); + } + + /** + * Initialize performance counters + * + * @param metric An integer identifying the metric being read + */ + public native void perfCtrInit(int metric); + + /** + * Read the current cycle count from the perfctr libraries + * + * @return the current cycle count from the perfctr libraries + */ + public native long perfCtrReadCycles(); + + /** + * Read the current event count for the metric being measured by the + * perfctr libraries + * + * @return the current event count for the metric being measured by the + * perfctr libraries + */ + public native long perfCtrReadMetric(); + +} + Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,49 @@ +//===------------------------- Strings.java -------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +import org.vmmagic.pragma.Uninterruptible; + + + at Uninterruptible +public final class Strings extends org.mmtk.vm.Strings { + /** + * Log a message. + * + * @param c character array with message starting at index 0 + * @param len number of characters in message + */ + public native void write(char [] c, int len); + + /** + * Log a thread identifier and a message. + * + * @param c character array with message starting at index 0 + * @param len number of characters in message + */ + public native void writeThreadId(char [] c, int len); + + /** + * Copies characters from the string into the character array. + * Thread switching is disabled during this method's execution. + *

+ * TODO: There are special memory management semantics here that + * someone should document. + * + * @param src the source string + * @param dst the destination array + * @param dstBegin the start offset in the desination array + * @param dstEnd the index after the last character in the + * destination to copy to + * @return the number of characters copied. + */ + public native int copyStringToChars(String src, char [] dst, + int dstBegin, int dstEnd); +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +//===---------- SynchronizedCounter.java - Atomic counter -----------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.mmtk; + +/** + * A counter that supports atomic increment and reset. + */ +public final class SynchronizedCounter extends org.mmtk.vm.SynchronizedCounter { + + private int count = 0; + + public native int reset(); + + public native int increment(); + + public int peek() { + return count; + } + +} Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,80 @@ +//===----------------------- TraceInterface.java --------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + + +package org.j3.mmtk; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Class that supports scanning Objects or Arrays for references + * during tracing, handling those references, and computing death times + */ + at Uninterruptible +public class TraceInterface extends org.mmtk.vm.TraceInterface { + + + /*********************************************************************** + * + * Public Methods + */ + + /** + * Returns if the VM is ready for a garbage collection. + * + * @return True if the VM is ready for GC, false otherwise. + */ + public native boolean gcEnabled(); + + /** + * This adjusts the offset into an object to reflect what it would look like + * if the fields were laid out in memory space immediately after the object + * pointer. + * + * @param isScalar If this is a pointer store to a scalar object + * @param src The address of the source object + * @param slot The address within src into which + * the update will be stored + * @return The easy to understand offset of the slot + */ + public native Offset adjustSlotOffset(boolean isScalar, + ObjectReference src, + Address slot); + + /** + * This skips over the frames added by the tracing algorithm, outputs + * information identifying the method the containts the "new" call triggering + * the allocation, and returns the address of the first non-trace, non-alloc + * stack frame. + * + *@param typeRef The type reference (tib) of the object just allocated + * @return The frame pointer address for the method that allocated the object + */ + @Interruptible + public native Address skipOwnFramesAndDump(ObjectReference typeRef); + + /*********************************************************************** + * + * Wrapper methods + */ + public native void updateDeathTime(ObjectReference obj); + public native void setDeathTime(ObjectReference ref, Word time_); + public native void setLink(ObjectReference ref, ObjectReference link); + public native void updateTime(Word time_); + public native Word getOID(ObjectReference ref); + public native Word getDeathTime(ObjectReference ref); + public native ObjectReference getLink(ObjectReference ref); + public native Address getBootImageLink(); + public native Word getOID(); + public native void setOID(Word oid); + public native int getHeaderSize(); + public native int getHeaderEndOffset(); +} Added: vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,161 @@ +//===------------------------- OptionSet.java -----------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +package org.j3.options; + + +import org.mmtk.utility.Constants; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Extent; +import org.vmmagic.unboxed.Word; +import org.vmutil.options.AddressOption; +import org.vmutil.options.BooleanOption; +import org.vmutil.options.EnumOption; +import org.vmutil.options.FloatOption; +import org.vmutil.options.IntOption; +import org.vmutil.options.MicrosecondsOption; +import org.vmutil.options.Option; +import org.vmutil.options.PagesOption; +import org.vmutil.options.StringOption; + +import org.jikesrvm.SizeConstants; +import org.j3.runtime.VM; + +/** + * Class to handle command-line arguments and options for GC. + */ +public final class OptionSet extends org.vmutil.options.OptionSet { + + private String prefix; + + public static final OptionSet gc = new OptionSet("-X:gc"); + + private OptionSet(String prefix) { + this.prefix = prefix; + } + + /** + * Format and log an option value. + * + * @param o The option. + * @param forXml Is this part of xml output? + */ + protected void logValue(Option o, boolean forXml) { + switch (o.getType()) { + case Option.BOOLEAN_OPTION: + VM.sysWrite(((BooleanOption) o).getValue() ? "true" : "false"); + break; + case Option.INT_OPTION: + VM.sysWrite(((IntOption) o).getValue()); + break; + case Option.ADDRESS_OPTION: + VM.sysWrite(((AddressOption) o).getValue()); + break; + case Option.FLOAT_OPTION: + VM.sysWrite(((FloatOption) o).getValue()); + break; + case Option.MICROSECONDS_OPTION: + VM.sysWrite(((MicrosecondsOption) o).getMicroseconds()); + VM.sysWrite(" usec"); + break; + case Option.PAGES_OPTION: + VM.sysWrite(((PagesOption) o).getBytes()); + VM.sysWrite(" bytes"); + break; + case Option.STRING_OPTION: + VM.sysWrite(((StringOption) o).getValue()); + break; + case Option.ENUM_OPTION: + VM.sysWrite(((EnumOption) o).getValueString()); + break; + } + } + + /** + * Log a string. + */ + protected void logString(String s) { + VM.sysWrite(s); + } + + /** + * Print a new line. + */ + protected void logNewLine() { + VM.sysWriteln(); + } + + /** + * Determine the VM specific key for a given option name. Option names are + * space delimited with capitalised words (e.g. "GC Verbosity Level"). + * + * @param name The option name. + * @return The VM specific key. + */ + protected String computeKey(String name) { + int space = name.indexOf(' '); + if (space < 0) return name.toLowerCase(); + + String word = name.substring(0, space); + String key = word.toLowerCase(); + + do { + int old = space+1; + space = name.indexOf(' ', old); + if (space < 0) { + key += name.substring(old); + return key; + } + key += name.substring(old, space); + } while (true); + } + + /** + * A non-fatal error occurred during the setting of an option. This method + * calls into the VM and shall not cause the system to stop. + * + * @param o The responsible option. + * @param message The message associated with the warning. + */ + protected void warn(Option o, String message) { + VM.sysWriteln("WARNING: Option '" + o.getKey() + "' : " + message); + } + + /** + * A fatal error occurred during the setting of an option. This method + * calls into the VM and is required to cause the system to stop. + * + * @param o The responsible option. + * @param message The error message associated with the failure. + */ + protected void fail(Option o, String message) { + VM.sysFail("ERROR: Option '" + o.getKey() + "' : " + message); + } + + /** + * Convert bytes into pages, rounding up if necessary. + * + * @param bytes The number of bytes. + * @return The corresponding number of pages. + */ + @Uninterruptible + protected int bytesToPages(Extent bytes) { + return bytes.plus(Constants.BYTES_IN_PAGE-1).toWord().rshl(Constants.LOG_BYTES_IN_PAGE).toInt(); + } + + /** + * Convert from pages into bytes. + * @param pages the number of pages. + * @return The corresponding number of bytes. + */ + @Uninterruptible + protected Extent pagesToBytes(int pages) { + return Word.fromIntZeroExtend(pages).lsh(Constants.LOG_BYTES_IN_PAGE).toExtent(); + } +} Added: vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java (added) +++ vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,41 @@ +//===---------------------------- VM.java ---------------------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +package org.j3.runtime; + +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Extent; + +public final class VM { + + private native static boolean verifyAssertions(); + private native static boolean buildForIA32(); + private native static boolean buildFor64Addr(); + + public final static boolean NOT_REACHED = false; + + public final static boolean VerifyAssertions = verifyAssertions(); + public final static boolean runningVM = false; + public final static boolean BuildForIA32 = buildForIA32(); + public final static boolean BuildFor64Addr = buildFor64Addr(); + + + public native static void sysFail(String a); + public native static void sysExit(int a); + public native static void _assert(boolean cond); + public native static void _assert(boolean cond, String msg); + public native static void sysWriteln(String a); + public native static void sysWriteln(); + public native static void sysWrite(String a); + public native static void sysWrite(int a); + public native static void sysWrite(float a); + public native static void sysWrite(Address a); + public native static void sysWrite(Extent a); +} Added: vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java (added) +++ vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,352 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.jikesrvm; + +import org.vmmagic.Intrinsic; +import org.vmmagic.pragma.Entrypoint; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Offset; +import org.vmmagic.unboxed.Word; +import org.vmmagic.unboxed.WordArray; + +import org.j3.runtime.VM; + +/** + * Magic methods for accessing raw machine memory, registers, and + * operating system calls. + * + *

These are "inline assembler functions" that cannot be implemented in + * Java code. Their names are recognized by RVM's compilers + * and cause inline machine code to be generated instead of + * actual method calls. + */ + at SuppressWarnings({"UnusedDeclaration"}) + at Intrinsic +public final class Magic { + + /** + * Read contents of hardware time base registers. + * Note: we think that 1 "tick" == 4 "machine cycles", but this seems to be + * undocumented and may vary across processor implementations. + * @return number of ticks (epoch undefined) + */ + public static long getTimeBase() { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + //---------------------------------------// + // Memory Access. // + //---------------------------------------// + + /** + * Get unsigned byte at arbitrary (byte) offset from object. The + * most significant 24bits of the result will be 0. + */ + public static byte getUnsignedByteAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + /** + * Get byte at arbitrary (byte) offset from object. The most + * significant 24bits of the result will be the same as the most + * significant bit in the byte. + */ + public static byte getByteAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + /** + * Get short at arbitrary (byte) offset from object. The most + * significant 16bits will be the same as the most significant bit + * in the short. + */ + public static short getShortAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return (short) -1; + } + + /** + * Get char at arbitrary (byte) offset from object. The most + * significant 16bits will be 0. + */ + public static char getCharAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return (char) -1; + } + + /** + * Get int at arbitrary (byte) offset from object. + * Use getIntAtOffset(obj, ofs) instead of getMemoryInt(objectAsAddress(obj)+ofs) + */ + public static int getIntAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + /** + * Get Word at arbitrary (byte) offset from object. + * Use getWordAtOffset(obj, ofs) instead of getMemoryWord(objectAsAddress(obj)+ofs) + */ + public static Word getWordAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return Word.max(); + } + + /** + * Get Object at arbitrary (byte) offset from object. + * Use getObjectAtOffset(obj, ofs) instead of + * addressAsObject(getMemoryAddress(objectAsAddress(obj)+ofs)) + */ + public static Object getObjectAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return null; + } + + /** + * Get Object at arbitrary (byte) offset from object. + * Use getObjectAtOffset(obj, ofs) instead of + * addressAsObject(getMemoryAddress(objectAsAddress(obj)+ofs)) + */ + public static Object getObjectAtOffset(Object object, Offset offset, int locationMetadata) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return null; + } + + /** + * Get Word at arbitrary (byte) offset from object. + */ + public static Word getWordAtOffset(Object object, Offset offset, int locationMetadata) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return null; + } + + /** + * Get long at arbitrary (byte) offset from object. + * Use getlongAtOffset(obj, ofs) instead of two getIntAtOffset + */ + public static long getLongAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + /** + * Get double at arbitrary (byte) offset from object. + * Use getDoubleAtOffset(obj, ofs) instead of two getIntAtOffset + */ + public static double getDoubleAtOffset(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + /** + * Set byte at arbitrary (byte) offset from object. + */ + public static void setByteAtOffset(Object object, Offset offset, byte newvalue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set char at arbitrary (byte) offset from object. + */ + public static void setCharAtOffset(Object object, Offset offset, char newvalue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set int at arbitrary (byte) offset from object. + * Use setIntAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, new) + */ + public static void setIntAtOffset(Object object, Offset offset, int newvalue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set word at arbitrary (byte) offset from object. + * Use setWordAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, new) + */ + public static void setWordAtOffset(Object object, Offset offset, Word newvalue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set word at arbitrary (byte) offset from object. + * Use setWordAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, new) + */ + public static void setWordAtOffset(Object object, Offset offset, Word newvalue, int locationMetadata) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set Object at arbitrary (byte) offset from object. + * Use setObjectAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, objectAsAddress(new)) + */ + public static void setObjectAtOffset(Object object, Offset offset, Object newvalue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set Object at arbitrary (byte) offset from object. + */ + public static void setObjectAtOffset(Object object, Offset offset, Object newvalue, int locationMetadata) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set long at arbitrary (byte) offset from object. + * Use setlongAtOffset(obj, ofs) instead of two setIntAtOffset + */ + public static void setLongAtOffset(Object object, Offset offset, long newvalue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + /** + * Set double at arbitrary (byte) offset from object. + * Use setDoubleAtOffset(obj, ofs) instead of two setIntAtOffset + */ + public static void setDoubleAtOffset(Object object, Offset offset, double newvalue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + + //---------------------------------------// + // Atomic Memory Access Primitives. // + //---------------------------------------// + + /** + * Get contents of (object + offset) and begin conditional critical section. + */ + public static int prepareInt(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + /** + * Get contents of (object + offset) and begin conditional critical section. + */ + public static Object prepareObject(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return null; + } + + /** + * Get contents of (object + offset) and begin conditional critical section. + */ + public static Address prepareAddress(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return Address.max(); + } + + /** + * Get contents of (object + offset) and begin conditional critical section. + */ + public static Word prepareWord(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return Word.max(); + } + + /** + * Get contents of (object + offset) and begin conditional critical section. + */ + @Uninterruptible + public static long prepareLong(Object object, Offset offset) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return -1; + } + + /** + * Sets the memory at (object + offset) to newValue if its contents are oldValue. + * Must be paired with a preceding prepare (which returned the oldValue) + * Returns true if successful. + * Ends conditional critical section. + */ + public static boolean attemptInt(Object object, Offset offset, int oldValue, int newValue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return false; + } + + /** + * Sets the memory at (object + offset) to newValue if its contents are oldValue. + * Must be paired with a preceding prepare (which returned the oldValue) + * Returns true if successful. + * Ends conditional critical section. + */ + public static boolean attemptObject(Object object, Offset offset, Object oldValue, Object newValue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return false; + } + + /** + * Sets the memory at (object + offset) to newValue if its contents are oldValue. + * Must be paired with a preceding prepare (which returned the oldValue) + * Returns true if successful. + * Ends conditional critical section. + */ + public static boolean attemptAddress(Object object, Offset offset, Address oldValue, Address newValue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return false; + } + + /** + * Sets the memory at (object + offset) to newValue if its contents are oldValue. + * Must be paired with a preceding prepare (which returned the oldValue) + * Returns true if successful. + * Ends conditional critical section. + */ + public static boolean attemptWord(Object object, Offset offset, Word oldValue, Word newValue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return false; + } + + /** + * Sets the memory at (object + offset) to newValue if its contents are oldValue. + * Must be paired with a preceding prepare (which returned the oldValue) + * Returns true if successful. + * Ends conditional critical section. + */ + public static boolean attemptLong(Object object, Offset offset, long oldValue, + long newValue) { + if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + return false; + } + + //---------------------------------------// + // Cache Management. // + //---------------------------------------// + + /**** NOTE: all per-address operations now live in vmmagic.Address *****/ + + /** + * Wait for preceeding cache flush/invalidate instructions to + * complete on all processors. + */ + public static void sync() { + if (VM.runningVM && VM.VerifyAssertions) { + VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + } + + /** + * Wait for all preceeding instructions to complete and discard any + * prefetched instructions on this processor. + */ + public static void isync() { + if (VM.runningVM && VM.VerifyAssertions) { + VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler + } + } + +} + Added: vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java (added) +++ vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,76 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.jikesrvm; + +import org.j3.runtime.VM; + +/** + * Constants defining the basic sizes of primitive quantities + */ +public interface SizeConstants { + + int LOG_BYTES_IN_BYTE = 0; + int BYTES_IN_BYTE = 1; + int LOG_BITS_IN_BYTE = 3; + int BITS_IN_BYTE = 1 << LOG_BITS_IN_BYTE; + + int LOG_BYTES_IN_BOOLEAN = 0; + int BYTES_IN_BOOLEAN = 1 << LOG_BYTES_IN_BOOLEAN; + int LOG_BITS_IN_BOOLEAN = LOG_BITS_IN_BYTE + LOG_BYTES_IN_BOOLEAN; + int BITS_IN_BOOLEAN = 1 << LOG_BITS_IN_BOOLEAN; + + int LOG_BYTES_IN_CHAR = 1; + int BYTES_IN_CHAR = 1 << LOG_BYTES_IN_CHAR; + int LOG_BITS_IN_CHAR = LOG_BITS_IN_BYTE + LOG_BYTES_IN_CHAR; + int BITS_IN_CHAR = 1 << LOG_BITS_IN_CHAR; + + int LOG_BYTES_IN_SHORT = 1; + int BYTES_IN_SHORT = 1 << LOG_BYTES_IN_SHORT; + int LOG_BITS_IN_SHORT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_SHORT; + int BITS_IN_SHORT = 1 << LOG_BITS_IN_SHORT; + + int LOG_BYTES_IN_INT = 2; + int BYTES_IN_INT = 1 << LOG_BYTES_IN_INT; + int LOG_BITS_IN_INT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_INT; + int BITS_IN_INT = 1 << LOG_BITS_IN_INT; + + int LOG_BYTES_IN_FLOAT = 2; + int BYTES_IN_FLOAT = 1 << LOG_BYTES_IN_FLOAT; + int LOG_BITS_IN_FLOAT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_FLOAT; + int BITS_IN_FLOAT = 1 << LOG_BITS_IN_FLOAT; + + int LOG_BYTES_IN_LONG = 3; + int BYTES_IN_LONG = 1 << LOG_BYTES_IN_LONG; + int LOG_BITS_IN_LONG = LOG_BITS_IN_BYTE + LOG_BYTES_IN_LONG; + int BITS_IN_LONG = 1 << LOG_BITS_IN_LONG; + + int LOG_BYTES_IN_DOUBLE = 3; + int BYTES_IN_DOUBLE = 1 << LOG_BYTES_IN_DOUBLE; + int LOG_BITS_IN_DOUBLE = LOG_BITS_IN_BYTE + LOG_BYTES_IN_DOUBLE; + int BITS_IN_DOUBLE = 1 << LOG_BITS_IN_DOUBLE; + + int LOG_BYTES_IN_ADDRESS = VM.BuildFor64Addr ? 3 : 2; + int BYTES_IN_ADDRESS = 1 << LOG_BYTES_IN_ADDRESS; + int LOG_BITS_IN_ADDRESS = LOG_BITS_IN_BYTE + LOG_BYTES_IN_ADDRESS; + int BITS_IN_ADDRESS = 1 << LOG_BITS_IN_ADDRESS; + + int LOG_BYTES_IN_WORD = VM.BuildFor64Addr ? 3 : 2; + int BYTES_IN_WORD = 1 << LOG_BYTES_IN_WORD; + int LOG_BITS_IN_WORD = LOG_BITS_IN_BYTE + LOG_BYTES_IN_WORD; + int BITS_IN_WORD = 1 << LOG_BITS_IN_WORD; + + int LOG_BYTES_IN_PAGE = 12; + int BYTES_IN_PAGE = 1 << LOG_BYTES_IN_PAGE; + int LOG_BITS_IN_PAGE = LOG_BITS_IN_BYTE + LOG_BYTES_IN_PAGE; + int BITS_IN_PAGE = 1 << LOG_BITS_IN_PAGE; +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,205 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.policy.ImmortalLocal; +import org.mmtk.utility.sanitychecker.SanityCheckerLocal; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.alloc.BumpPointer; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class (and its sub-classes) implement per-collector thread + * behavior. We assume N collector threads and M + * mutator threads, where N is often equal to the number of + * available processors, P (for P-way parallelism at GC-time), and + * M may simply be the number of mutator (application) threads. + * Both N and M are determined by the VM, not MMTk. In + * the case where a VM uses posix threads (pthreads) for each mutator + * ("1:1" threading), M will typically be equal to the number of + * mutator threads. When a uses "green threads" or a hybrid threading + * scheme (such as Jikes RVM), M will typically be equal to the + * level of true parallelism (ie the number of underlying + * kernel threads).

+ * + *

Collector operations are separated into per-collector thread + * operations (the bulk of the GC), and per-mutator thread operations + * (important in flushing and restoring per-mutator state such as allocator + * state and write buffer/remset state). {@link SimplePhase} + * ensures that per-collector thread GC phases are performed by each + * collector thread, and that the M per-mutator thread operations + * are multiplexed across the N active collector threads.

+ * + *

MMTk assumes that the VM instantiates instances of {@link CollectorContext} + * in thread local storage (TLS) for each thread participating in + * collection. Accesses to this state are therefore assumed to be + * low-cost at GC time.

+ * + *

MMTk explicitly separates thread-local (this class) and global + * operations (See {@link Plan}), so that syncrhonization is localized + * and explicit, and thus hopefully minimized (See {@link Plan}). Global (Plan) + * and per-thread (this class) state are also explicitly separated. + * Operations in this class (and its children) are therefore strictly + * local to each collector thread, and synchronized operations always + * happen via access to explicitly global classes such as Plan and its + * children.

+ * + *

This class (and its children) therefore typically implement per-collector + * thread structures such as collection work queues.

+ * + * @see MutatorContext + * @see org.mmtk.vm.ActivePlan + * @see Plan + */ + at Uninterruptible public abstract class CollectorContext implements Constants { + + /**************************************************************************** + * Instance fields + */ + /** Unique collector identifier */ + private int id; + + /** Per-collector allocator into the immortal space */ + protected final BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace); + + /** Used for aborting concurrent phases pre-empted by stop the world collection */ + protected boolean resetConcurrentWork; + + /** Used for sanity checking */ + protected final SanityCheckerLocal sanityLocal = new SanityCheckerLocal(); + + /**************************************************************************** + * + * Initialization + */ + protected CollectorContext() { + } + + /** + * Notify that the collector context is registered and ready to execute. + * + * @param id The id of this collector context. + */ + public void initCollector(int id) { + this.id = id; + } + + /**************************************************************************** + * Collection-time allocation. + */ + + /** + * Allocate memory when copying an object. + * + * @param original The object that is being copied. + * @param bytes The number of bytes required for the copy. + * @param align Required alignment for the copy. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @return The address of the newly allocated region. + */ + public Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + VM.assertions.fail("Collector has not implemented allocCopy"); + return Address.max(); + } + + /** + * Perform any post-copy actions. + * + * @param ref The newly allocated object. + * @param typeRef the type reference for the instance being created. + * @param bytes The size of the space to be allocated (in bytes). + * @param allocator The allocator statically assigned to this allocation. + */ + public void postCopy(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + VM.assertions.fail("Collector has not implemented postCopy"); + } + + /** + * Run-time check of the allocator to use for a given copy allocation + * + * At the moment this method assumes that allocators will use the simple + * (worst) method of aligning to determine if the object is a large object + * to ensure that no objects are larger than other allocators can handle. + * + * @param from The object that is being copied. + * @param bytes The number of bytes to be allocated. + * @param align The requested alignment. + * @param allocator The allocator statically assigned to this allocation. + * @return The allocator dyncamically assigned to this allocation. + */ + @Inline + public int copyCheckAllocator(ObjectReference from, int bytes, + int align, int allocator) { + boolean large = Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES; + return large ? Plan.ALLOC_LOS : allocator; + } + + /**************************************************************************** + * Collection. + */ + + /** Perform a garbage collection */ + public abstract void collect(); + + /** Perform some concurrent garbage collection */ + public abstract void concurrentCollect(); + + /** + * Perform a (local) collection phase. + * + * @param phaseId The unique phase identifier + * @param primary Should this thread be used to execute any single-threaded + * local operations? + */ + public abstract void collectionPhase(short phaseId, boolean primary); + + /** + * Perform some concurrent collection work. + * + * @param phaseId The unique phase identifier + */ + public abstract void concurrentCollectionPhase(short phaseId); + + /** @return The current trace instance. */ + public abstract TraceLocal getCurrentTrace(); + + /** + * Abort concurrent work due to pre-empt by stop the world collection. + */ + protected void resetConcurrentWork() { + resetConcurrentWork = true; + } + + /** + * Allow concurrent work to continue. + */ + protected void clearResetConcurrentWork() { + resetConcurrentWork = false; + } + + /**************************************************************************** + * Miscellaneous. + */ + + /** @return the unique identifier for this collector context. */ + @Inline + public int getId() { return id; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,134 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.Constants; +import org.mmtk.utility.statistics.Timer; +import org.mmtk.utility.Log; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * Phases of a garbage collection. + * + * A complex phase is a sequence of phases. + * + */ + at Uninterruptible +public final class ComplexPhase extends Phase + implements Constants { + + /**************************************************************************** + * Instance fields + */ + + /** + * The phases that comprise this phase. + */ + private final int[] scheduledSubPhases; + + /** + * Construct a complex phase from an array of phase IDs. + * + * @param name The name of the phase. + * @param scheduledSubPhases The sub phases + */ + protected ComplexPhase(String name, int[] scheduledSubPhases) { + super(name); + this.scheduledSubPhases = scheduledSubPhases; + checkPhases(); + } + + /** + * Construct a complex phase from an array of phase IDs, but using + * the specified timer rather than creating one. + * + * @param name The name of the phase. + * @param timer The timer for this phase to contribute to. + * @param scheduledSubPhases The sub phases + */ + protected ComplexPhase(String name, Timer timer, int[] scheduledSubPhases) { + super(name, timer); + this.scheduledSubPhases = scheduledSubPhases; + checkPhases(); + } + + /** + * Validate the scheduled sub phases. + */ + private void checkPhases() { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(scheduledSubPhases.length > 0); + for(int scheduledPhase: scheduledSubPhases) { + VM.assertions._assert(getSchedule(scheduledPhase) > 0); + VM.assertions._assert(getPhaseId(scheduledPhase) > 0); + } + } + } + + /** + * The number of scheduled sub phases. + */ + protected int count() { + return scheduledSubPhases.length; + } + + /** + * Return an individual scheduled sub phase. + * + * @param index The index + * @return The scheduled phase. + */ + protected int get(int index) { + return scheduledSubPhases[index]; + } + + /** + * Display a description of this phase, for debugging purposes. + */ + protected void logPhase() { + Log.write("ComplexPhase("); + Log.write(name); + Log.write(", < "); + for (int subPhase : scheduledSubPhases) { + short ordering = getSchedule(subPhase); + short phaseId = getPhaseId(subPhase); + Log.write(getScheduleName(ordering)); + Log.write("("); + Log.write(getName(phaseId)); + Log.write(") "); + } + Log.write(">)"); + } + + /** + * Replace a scheduled phase. Used for example to replace a placeholder. + * + * @param oldScheduledPhase The scheduled phase to replace. + * @param newScheduledPhase The new scheduled phase. + */ + public void replacePhase(int oldScheduledPhase, int newScheduledPhase) { + for (int i = 0; i < scheduledSubPhases.length; i++) { + int scheduledPhase = scheduledSubPhases[i]; + if (scheduledPhase == oldScheduledPhase) { + /* Replace */ + scheduledSubPhases[i] = newScheduledPhase; + } else if (getSchedule(scheduledPhase) == SCHEDULE_COMPLEX) { + /* Recurse */ + ComplexPhase p = (ComplexPhase)getPhase(getPhaseId(scheduledPhase)); + p.replacePhase(oldScheduledPhase, newScheduledPhase); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.policy.ImmortalSpace; +import org.mmtk.utility.heap.VMRequest; + +/** + * This interface provides an immortal allocation space for GCspy objects. + */ +public interface GCspyPlan { + + /** + * Any GCspy objects allocated after booting are allocated + * in a separate immortal space. + */ + ImmortalSpace gcspySpace = + new ImmortalSpace("gcspy", Plan.DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + /** The descriptor for the GCspy allocation space */ + int GCSPY = gcspySpace.getDescriptor(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,423 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.policy.MarkSweepLocal; +import org.mmtk.policy.Space; +import org.mmtk.policy.ImmortalLocal; +import org.mmtk.policy.LargeObjectLocal; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.alloc.BumpPointer; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class (and its sub-classes) implement per-mutator thread + * behavior. We assume N collector threads and M + * mutator threads, where N is often equal to the number of + * available processors, P (for P-way parallelism at GC-time), and + * M may simply be the number of mutator (application) threads. + * Both N and M are determined by the VM, not MMTk. In + * the case where a VM uses posix threads (pthreads) for each mutator + * ("1:1" threading), M will typically be equal to the number of + * mutator threads. When a uses "green threads" or a hybrid threading + * scheme (such as Jikes RVM), M will typically be equal to the + * level of true parallelism (ie the number of underlying + * kernel threads).

+ * + * MMTk assumes that the VM instantiates instances of MutatorContext + * in thread local storage (TLS) for each thread participating in + * collection. Accesses to this state are therefore assumed to be + * low-cost during mutator time.

+ * + * This class (and its children) is therefore used for unsynchronized + * per-mutator operations such as allocation and write barriers. + * The semantics and necessary state for these operations are therefore + * specified in the GC-specific subclasses of this class. + * + * MMTk explicitly separates thread-local (this class) and global + * operations (@see Plan), so that syncrhonization is localized + * and explicit, and thus hopefully minimized (@see Plan). Gloabl (Plan) + * and per-thread (this class) state are also explicitly separated. + * Operations in this class (and its children) are therefore strictly + * local to each mutator thread, and synchronized operations always + * happen via access to explicitly global classes such as Plan and its + * children. Therefore only "fast path" (unsynchronized) + * allocation and barrier semantics are defined in MutatorContext and + * its subclasses. These call out to "slow path" (synchronize(d) + * methods which have global state and are globally synchronized. For + * example, an allocation fast path may bump a pointer without any + * syncrhonization (the "fast path") until a limit is reached, at which + * point the "slow path" is called, and more memory is aquired from a + * global resource.

+ * + * As the super-class of all per-mutator contexts, this class implements + * basic per-mutator behavior common to all MMTk collectors, including + * support for immortal and large object space allocation, as well as + * empty stubs for write barriers (to be overridden by sub-classes as + * needed). + * + * @see CollectorContext + * @see org.mmtk.vm.ActivePlan + * @see Plan + */ + at Uninterruptible +public abstract class MutatorContext implements Constants { + + /**************************************************************************** + * Initialization + */ + + + /** + * Notify that the mutator context is registered and ready to execute. From + * this point it will be included in iterations over mutators. + * + * @param id The id of this mutator context. + */ + public void initMutator(int id) { + this.id = id; + } + + /** + * The mutator is about to be cleaned up, make sure all local data is returned. + */ + public void deinitMutator() { + flush(); + } + + /**************************************************************************** + * Instance fields + */ + + /** Unique mutator identifier */ + private int id; + + /** Used for printing log information in a thread safe manner */ + protected final Log log = new Log(); + + /** Per-mutator allocator into the immortal space */ + protected final BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace); + + /** Per-mutator allocator into the large object space */ + protected final LargeObjectLocal los = new LargeObjectLocal(Plan.loSpace); + + /** Per-mutator allocator into the small code space */ + private final MarkSweepLocal smcode = Plan.USE_CODE_SPACE ? new MarkSweepLocal(Plan.smallCodeSpace) : null; + + /** Per-mutator allocator into the large code space */ + private final LargeObjectLocal lgcode = Plan.USE_CODE_SPACE ? new LargeObjectLocal(Plan.largeCodeSpace) : null; + + /** Per-mutator allocator into the non moving space */ + private final MarkSweepLocal nonmove = new MarkSweepLocal(Plan.nonMovingSpace); + + + /**************************************************************************** + * + * Collection. + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The unique phase identifier + * @param primary Should this thread be used to execute any single-threaded + * local operations? + */ + public abstract void collectionPhase(short phaseId, boolean primary); + + /**************************************************************************** + * + * Allocation. + */ + + /** + * Run-time check of the allocator to use for a given allocation + * + * At the moment this method assumes that allocators will use the simple + * (worst) method of aligning to determine if the object is a large object + * to ensure that no objects are larger than other allocators can handle. + * + * @param bytes The number of bytes to be allocated + * @param align The requested alignment. + * @param allocator The allocator statically assigned to this allocation + * @return The allocator dynamically assigned to this allocation + */ + @Inline + public int checkAllocator(int bytes, int align, int allocator) { + int maxBytes = Allocator.getMaximumAlignedSize(bytes, align); + if (allocator == Plan.ALLOC_DEFAULT) { + return (maxBytes > Plan.MAX_NON_LOS_DEFAULT_ALLOC_BYTES) ? Plan.ALLOC_LOS : allocator; + } + + if (Plan.USE_CODE_SPACE && allocator == Plan.ALLOC_CODE) { + return (maxBytes > Plan.MAX_NON_LOS_NONMOVING_ALLOC_BYTES) ? Plan.ALLOC_LARGE_CODE : allocator; + } + + if (allocator == Plan.ALLOC_NON_REFERENCE) { + return (maxBytes > Plan.MAX_NON_LOS_DEFAULT_ALLOC_BYTES) ? Plan.ALLOC_LOS : Plan.ALLOC_DEFAULT; + } + + if (allocator == Plan.ALLOC_NON_MOVING) { + return (maxBytes > Plan.MAX_NON_LOS_NONMOVING_ALLOC_BYTES) ? Plan.ALLOC_LOS : allocator; + } + + return allocator; + } + + /** + * Allocate memory for an object. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The low address of the allocated chunk. + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + switch (allocator) { + case Plan.ALLOC_LOS: return los.alloc(bytes, align, offset); + case Plan.ALLOC_IMMORTAL: return immortal.alloc(bytes, align, offset); + case Plan.ALLOC_CODE: return smcode.alloc(bytes, align, offset); + case Plan.ALLOC_LARGE_CODE: return lgcode.alloc(bytes, align, offset); + case Plan.ALLOC_NON_MOVING: return nonmove.alloc(bytes, align, offset); + default: + VM.assertions.fail("No such allocator"); + return Address.zero(); + } + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + switch (allocator) { + case Plan.ALLOC_LOS: Plan.loSpace.initializeHeader(ref, true); return; + case Plan.ALLOC_IMMORTAL: Plan.immortalSpace.initializeHeader(ref); return; + case Plan.ALLOC_CODE: Plan.smallCodeSpace.initializeHeader(ref, true); return; + case Plan.ALLOC_LARGE_CODE: Plan.largeCodeSpace.initializeHeader(ref, true); return; + case Plan.ALLOC_NON_MOVING: Plan.nonMovingSpace.initializeHeader(ref, true); return; + default: + VM.assertions.fail("No such allocator"); + } + } + + /**************************************************************************** + * + * Space - Allocator mapping. + */ + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == Plan.immortalSpace) return immortal; + if (space == Plan.loSpace) return los; + if (space == Plan.nonMovingSpace) return nonmove; + if (Plan.USE_CODE_SPACE && space == Plan.smallCodeSpace) return smcode; + if (Plan.USE_CODE_SPACE && space == Plan.largeCodeSpace) return lgcode; + + // Invalid request has been made + if (space == Plan.metaDataSpace) { + VM.assertions.fail("MutatorContext.getAllocatorFromSpace given meta space"); + } else if (space != null) { + VM.assertions.fail("MutatorContext.getAllocatorFromSpace given invalid space"); + } else { + VM.assertions.fail("MutatorContext.getAllocatorFromSpace given null space"); + } + + return null; + } + + /**************************************************************************** + * + * Write and read barriers. By default do nothing, override if + * appropriate. + */ + + /** + * A new reference is about to be created. Take appropriate write + * barrier actions.

+ * + * By default do nothing, override if appropriate. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occurred + */ + public void writeBarrier(ObjectReference src, Address slot, + ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + // Either: write barriers are used and this is overridden, or + // write barriers are not used and this is never called + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + } + + /** + * Attempt to atomically exchange the value in the given slot + * with the passed replacement value. If a new reference is + * created, we must then take appropriate write barrier actions.

+ * + * By default do nothing, override if appropriate. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param old The old reference to be swapped out + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occurred + * @return True if the swap was successful. + */ + public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot, + ObjectReference old, ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + // Either: write barriers are used and this is overridden, or + // write barriers are not used and this is never called + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + return false; + } + + /** + * A number of references are about to be copied from object + * src to object dst (as in an array + * copy). Thus, dst is the mutated object. Take + * appropriate write barrier actions.

+ * + * @param src The source of the values to be copied + * @param srcOffset The offset of the first source address, in + * bytes, relative to src (in principle, this could be + * negative). + * @param dst The mutated object, i.e. the destination of the copy. + * @param dstOffset The offset of the first destination address, in + * bytes relative to tgt (in principle, this could be + * negative). + * @param bytes The size of the region being copied, in bytes. + * @return True if the update was performed by the barrier, false if + * left to the caller (always false in this case). + */ + public boolean writeBarrier(ObjectReference src, Offset srcOffset, + ObjectReference dst, Offset dstOffset, + int bytes) { + // Either: write barriers are used and this is overridden, or + // write barriers are not used and this is never called + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + return false; + } + + /** + * Read a reference type. In a concurrent collector this may + * involve adding the referent to the marking queue. + * + * @param referent The referent being read. + * @return The new referent. + */ + @Inline + public ObjectReference referenceTypeReadBarrier(ObjectReference referent) { + // Either: read barriers are used and this is overridden, or + // read barriers are not used and this is never called + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + return ObjectReference.nullReference(); + } + + /** + * Read a reference. Take appropriate read barrier action, and + * return the value that was read.

This is a substituting + * barrier. The call to this barrier takes the place of a load.

+ * + * @param src The object reference holding the field being read. + * @param slot The address of the slot being read. + * @param metaDataA A value that assists the host VM in creating a load + * @param metaDataB A value that assists the host VM in creating a load + * @param mode The context in which the load occurred + * @return The reference that was read. + */ + @Inline + public ObjectReference readBarrier(ObjectReference src, Address slot, Word metaDataA, Word metaDataB, int mode) { + // Either: read barriers are used and this is overridden, or + // read barriers are not used and this is never called + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + return ObjectReference.nullReference(); + } + + /** + * Flush mutator context, in response to a requestMutatorFlush. + * Also called by the default implementation of deinitMutator. + */ + public void flush() { + flushRememberedSets(); + smcode.flush(); + nonmove.flush(); + } + + /** + * Flush per-mutator remembered sets into the global remset pool. + */ + public void flushRememberedSets() { + // Either: write barriers are used and this is overridden, or + // write barriers are not used and this is a no-op + } + + /** + * Assert that the remsets have been flushed. This is critical to + * correctness. We need to maintain the invariant that remset entries + * do not accrue during GC. If the host JVM generates barrier entires + * it is its own responsibility to ensure that they are flushed before + * returning to MMTk. + */ + public void assertRemsetsFlushed() { + // Either: write barriers are used and this is overridden, or + // write barriers are not used and this is a no-op + } + + /*********************************************************************** + * + * Miscellaneous + */ + + /** @return the Log instance for this PlanLocal */ + public final Log getLog() { + return log; + } + + /** @return the unique identifier for this mutator context. */ + @Inline + public int getId() { return id; } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,658 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.statistics.Timer; +import org.mmtk.vm.Collection; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * A garbage collection proceeds as a sequence of phases. Each + * phase is either simple (singular) or complex (an array). + * + * The context an individual phase executes in may be global, mutator, + * or collector. + * + * Phases are executed within a stack and all synchronization between + * parallel GC threads is managed from within this class. + * + * @see CollectorContext#collectionPhase + * @see MutatorContext#collectionPhase + * @see Plan#collectionPhase + */ + at Uninterruptible +public abstract class Phase implements Constants { + /*********************************************************************** + * + * Phase allocation and storage. + */ + + /** The maximum number of phases */ + private static final int MAX_PHASES = 64; + /** The array of phase instances. Zero is unused. */ + private static final Phase[] phases = new Phase[MAX_PHASES]; + /** The id to be allocated for the next phase */ + private static short nextPhaseId = 1; + + /** Run the phase globally. */ + protected static final short SCHEDULE_GLOBAL = 1; + /** Run the phase on collectors. */ + protected static final short SCHEDULE_COLLECTOR = 2; + /** Run the phase on mutators. */ + protected static final short SCHEDULE_MUTATOR = 3; + /** Don't run this phase. */ + protected static final short SCHEDULE_PLACEHOLDER = 100; + /** This is a complex phase. */ + protected static final short SCHEDULE_COMPLEX = 101; + + /** + * Retrieve a phase by the unique phase identifier. + * + * @param id The phase identifier. + * @return The Phase instance. + */ + public static Phase getPhase(short id) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(id < nextPhaseId, "Phase ID unknown"); + VM.assertions._assert(phases[id] != null, "Uninitialised phase"); + } + return phases[id]; + } + + /** Get the phase id component of an encoded phase */ + protected static short getPhaseId(int scheduledPhase) { + short phaseId = (short)(scheduledPhase & 0x0000FFFF); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(phaseId > 0); + return phaseId; + } + + /** + * @param phaseId The unique phase identifier. + * @return The name of the phase. + */ + public static String getName(short phaseId) { + return phases[phaseId].name; + } + + /** Get the ordering component of an encoded phase */ + protected static short getSchedule(int scheduledPhase) { + short ordering = (short)((scheduledPhase >> 16) & 0x0000FFFF); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(ordering > 0); + return ordering; + } + + /** Get the ordering component of an encoded phase */ + protected static String getScheduleName(short ordering) { + switch (ordering) { + case SCHEDULE_GLOBAL: return "Global"; + case SCHEDULE_COLLECTOR: return "Collector"; + case SCHEDULE_MUTATOR: return "Mutator"; + case SCHEDULE_PLACEHOLDER: return "Placeholder"; + case SCHEDULE_COMPLEX: return "Complex"; + default: return "UNKNOWN!"; + } + } + + /** + * Construct a phase. + * + * @param name Display name of the phase + */ + @Interruptible + public static short createSimple(String name) { + return new SimplePhase(name).getId(); + } + + /** + * Construct a phase, re-using a specified timer. + * + * @param name Display name of the phase + */ + @Interruptible + public static short createSimple(String name, Timer timer) { + return new SimplePhase(name, timer).getId(); + } + + /** + * Construct a complex phase. + * + * @param name Display name of the phase + * @param scheduledPhases The phases in this complex phase. + */ + @Interruptible + public static short createComplex(String name,int... scheduledPhases) { + return new ComplexPhase(name, scheduledPhases).getId(); + } + + /** + * Construct a complex phase, re-using a specified timer. + * + * @param name Display name of the phase + * @param timer Timer for this phase to contribute to + * @param scheduledPhases The phases in this complex phase. + */ + @Interruptible + public static short createComplex(String name, Timer timer, int... scheduledPhases) { + return new ComplexPhase(name, timer, scheduledPhases).getId(); + } + + /** + * Take the passed phase and return an encoded phase to + * run that phase as a complex phase. + * + * @param phaseId The phase to run as complex + * @return The encoded phase value. + */ + public static int scheduleComplex(short phaseId) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof ComplexPhase); + return (SCHEDULE_COMPLEX << 16) + phaseId; + } + + /** + * Take the passed phase and return an encoded phase to + * run that phase in a global context; + * + * @param phaseId The phase to run globally + * @return The encoded phase value. + */ + public static int scheduleGlobal(short phaseId) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase); + return (SCHEDULE_GLOBAL << 16) + phaseId; + } + + /** + * Take the passed phase and return an encoded phase to + * run that phase in a collector context; + * + * @param phaseId The phase to run on collectors + * @return The encoded phase value. + */ + public static int scheduleCollector(short phaseId) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase); + return (SCHEDULE_COLLECTOR << 16) + phaseId; + } + + /** + * Take the passed phase and return an encoded phase to + * run that phase in a mutator context; + * + * @param phaseId The phase to run on mutators + * @return The encoded phase value. + */ + public static int scheduleMutator(short phaseId) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase); + return (SCHEDULE_MUTATOR << 16) + phaseId; + } + + /** + * Take the passed phase and return an encoded phase to + * run that phase in a mutator context; + * + * @param phaseId The phase to run on mutators + * @return The encoded phase value. + */ + public static int schedulePlaceholder(short phaseId) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase); + return (SCHEDULE_PLACEHOLDER << 16) + phaseId; + } + + /*********************************************************************** + * + * Phase instance fields/methods. + */ + + /** + * The unique phase identifier. + */ + protected final short id; + + /** + * The name of the phase. + */ + protected final String name; + + /** + * The Timer that is started and stopped around the execution of this + * phase. + */ + protected final Timer timer; + + /** + * Create a new Phase. This involves creating a corresponding Timer + * instance, allocating a unique identifier, and registering the + * Phase. + * + * @param name The name for the phase. + */ + protected Phase(String name) { + this(name, new Timer(name, false, true)); + } + + /** + * Create a new phase. This involves setting the corresponding Timer + * instance, allocating a unique identifier, and registering the Phase. + * + * @param name The name of the phase. + * @param timer The timer, or null if this is an untimed phase. + */ + protected Phase(String name, Timer timer) { + this.name = name; + this.timer = timer; + this.id = nextPhaseId++; + phases[this.id] = this; + } + + /** + * @return The unique identifier for this phase. + */ + public final short getId() { + return this.id; + } + + /** + * Display a phase for debugging purposes. + */ + protected abstract void logPhase(); + + /*********************************************************************** + * + * Phase stack + */ + + /** The maximum stack depth for the phase stack. */ + private static final int MAX_PHASE_STACK_DEPTH = MAX_PHASES; + + /** Stores the current sub phase for a complex phase. Each entry corresponds to a phase stack entry */ + private static int[] complexPhaseCursor = new int[MAX_PHASE_STACK_DEPTH]; + + /** The phase stack. Stores the current nesting of phases */ + private static int[] phaseStack = new int[MAX_PHASE_STACK_DEPTH]; + + /** The current stack pointer */ + private static int phaseStackPointer = -1; + + /** + * The current even (0 mod 2) scheduled phase. + * As we only sync at the end of a phase we need this to ensure that + * the primary thread setting the phase does not race with the other + * threads reading it. + */ + private static int evenScheduledPhase; + + /** + * The current odd (1 mod 2) scheduled phase. + * As we only sync at the end of a phase we need this to ensure that + * the primary thread setting the phase does not race with the other + * threads reading it. + */ + private static int oddScheduledPhase; + + /** + * Do we need to add a sync point to reset the mutator count. This + * is necessary for consecutive mutator phases and unneccessary + * otherwise. Again we separate in even and odd to ensure that there + * is no race between the primary thread setting and the helper + * threads reading. + */ + private static boolean evenMutatorResetRendezvous; + + /** + * Do we need to add a sync point to reset the mutator count. This + * is necessary for consecutive mutator phases and unneccessary + * otherwise. Again we separate in even and odd to ensure that there + * is no race between the primary thread setting and the helper + * threads reading. + */ + private static boolean oddMutatorResetRendezvous; + + /** + * The complex phase whose timer should be started after the next + * rendezvous. We can not start the timer at the point we determine + * the next complex phase as we determine the next phase at the + * end of the previous phase before the sync point. + */ + private static short startComplexTimer; + + /** + * The complex phase whose timer should be stopped after the next + * rendezvous. We can not start the timer at the point we determine + * the next complex phase as we determine the next phase at the + * end of the previous phase before the sync point. + */ + private static short stopComplexTimer; + + /** + * Place a phase on the phase stack and begin processing. + * + * @param scheduledPhase The phase to execute + * @return True if the phase stack is exhausted. + */ + public static boolean beginNewPhaseStack(int scheduledPhase) { + int order = VM.collection.rendezvous(1001); + + if (order == 1) { + pushScheduledPhase(scheduledPhase); + } + return processPhaseStack(false); + } + + /** + * Process the phase stack. This method is called by multiple threads. + */ + private static boolean processPhaseStack(boolean resume) { + int order = VM.collection.rendezvous(1001); + final boolean primary = order == 1; + + boolean log = Options.verbose.getValue() >= 6; + boolean logDetails = Options.verbose.getValue() >= 7; + + if (primary && resume) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Phase.isPhaseStackEmpty()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Plan.gcInProgress()); + Plan.setGCStatus(Plan.GC_PROPER); + } + + /* In order to reduce the need for synchronization, we keep an odd or even + * counter for the number of phases processed. As each phase has a single + * rendezvous it is only possible to be out by one so the odd or even counter + * protects us. */ + boolean isEvenPhase = true; + + if (primary) { + /* First phase will be even, so we say we are odd here so that the next phase set is even*/ + setNextPhase(false, getNextPhase(), false); + } + + /* Make sure everyone sees the first phase */ + VM.collection.rendezvous(1002); + + /* Global and Collector instances used in phases */ + Plan plan = VM.activePlan.global(); + CollectorContext collector = VM.activePlan.collector(); + + /* The main phase execution loop */ + int scheduledPhase; + while((scheduledPhase = getCurrentPhase(isEvenPhase)) > 0) { + short schedule = getSchedule(scheduledPhase); + short phaseId = getPhaseId(scheduledPhase); + Phase p = getPhase(phaseId); + + /* Start the timer(s) */ + if (primary) { + if (resume) { + resumeComplexTimers(); + } + if (p.timer != null) p.timer.start(); + if (startComplexTimer > 0) { + Phase.getPhase(startComplexTimer).timer.start(); + startComplexTimer = 0; + } + } + + if (log) { + Log.write("Execute "); + p.logPhase(); + } + + /* Execute a single simple scheduled phase */ + switch (schedule) { + /* Global phase */ + case SCHEDULE_GLOBAL: { + if (logDetails) Log.writeln(" as Global..."); + if (primary) { + if (VM.DEBUG) VM.debugging.globalPhase(phaseId,true); + plan.collectionPhase(phaseId); + if (VM.DEBUG) VM.debugging.globalPhase(phaseId,false); + } + break; + } + + /* Collector phase */ + case SCHEDULE_COLLECTOR: { + if (logDetails) Log.writeln(" as Collector..."); + if (VM.DEBUG) VM.debugging.collectorPhase(phaseId,order,true); + collector.collectionPhase(phaseId, primary); + if (VM.DEBUG) VM.debugging.collectorPhase(phaseId,order,false); + break; + } + + /* Mutator phase */ + case SCHEDULE_MUTATOR: { + if (logDetails) Log.writeln(" as Mutator..."); + /* Iterate through all mutator contexts */ + MutatorContext mutator; + while ((mutator = VM.activePlan.getNextMutator()) != null) { + if (VM.DEBUG) VM.debugging.mutatorPhase(phaseId,mutator.getId(),true); + mutator.collectionPhase(phaseId, primary); + if (VM.DEBUG) VM.debugging.mutatorPhase(phaseId,mutator.getId(),false); + } + break; + } + + default: { + /* getNextPhase has done the wrong thing */ + VM.assertions.fail("Invalid schedule in Phase.processPhaseStack"); + break; + } + } + + if (primary) { + /* Set the next phase by processing the stack */ + int next = getNextPhase(); + boolean needsResetRendezvous = (next > 0) && (schedule == SCHEDULE_MUTATOR && getSchedule(next) == SCHEDULE_MUTATOR); + setNextPhase(isEvenPhase, next, needsResetRendezvous); + } + + /* Sync point after execution of a phase */ + VM.collection.rendezvous(1004); + + /* Mutator phase reset */ + if (primary && schedule == SCHEDULE_MUTATOR) { + VM.activePlan.resetMutatorIterator(); + } + + /* At this point, in the case of consecutive phases with mutator + * scheduling, we have to double-synchronize to ensure all + * collector threads see the reset mutator counter. */ + if (needsMutatorResetRendezvous(isEvenPhase)) { + VM.collection.rendezvous(1005); + } + + /* Stop the timer(s) */ + if (primary) { + if (p.timer != null) p.timer.stop(); + if (stopComplexTimer > 0) { + Phase.getPhase(stopComplexTimer).timer.stop(); + stopComplexTimer = 0; + } + } + + /* Flip the even / odd phase sense */ + isEvenPhase = !isEvenPhase; + resume = false; + } + + /* Phase stack exhausted so we return true */ + return true; + } + + /** + * Get the next phase. + */ + private static int getCurrentPhase(boolean isEvenPhase) { + return isEvenPhase ? evenScheduledPhase : oddScheduledPhase; + } + + /** + * Do we need a mutator reset rendezvous in this phase? + */ + private static boolean needsMutatorResetRendezvous(boolean isEvenPhase) { + return isEvenPhase ? evenMutatorResetRendezvous : oddMutatorResetRendezvous; + } + /** + * Set the next phase. If we are in an even phase the next phase is odd. + */ + private static void setNextPhase(boolean isEvenPhase, int scheduledPhase, boolean needsResetRendezvous) { + if (isEvenPhase) { + oddScheduledPhase = scheduledPhase; + evenMutatorResetRendezvous = needsResetRendezvous; + } else { + evenScheduledPhase = scheduledPhase; + oddMutatorResetRendezvous = needsResetRendezvous; + } + } + + /** + * Pull the next scheduled phase off the stack. This may involve + * processing several complex phases and skipping placeholders, etc. + * + * @return The next phase to run, or -1 if no phases are left. + */ + private static int getNextPhase() { + boolean allowConcurrentPhase = Plan.collectionTrigger == Collection.INTERNAL_PHASE_GC_TRIGGER; + + while (phaseStackPointer >= 0) { + int scheduledPhase = peekScheduledPhase(); + short schedule = getSchedule(scheduledPhase); + short phaseId = getPhaseId(scheduledPhase); + + switch(schedule) { + case SCHEDULE_PLACEHOLDER: { + /* Placeholders are ignored and we continue looking */ + popScheduledPhase(); + continue; + } + + case SCHEDULE_GLOBAL: + case SCHEDULE_COLLECTOR: + case SCHEDULE_MUTATOR: { + /* Simple phases are just popped off the stack and executed */ + popScheduledPhase(); + return scheduledPhase; + } + + case SCHEDULE_COMPLEX: { + /* A complex phase may either be a newly pushed complex phase, + * or a complex phase we are in the process of executing in + * which case we move to the next subphase. */ + ComplexPhase p = (ComplexPhase)getPhase(phaseId); + int cursor = incrementComplexPhaseCursor(); + if (cursor == 0 && p.timer != null) { + /* Tell the primary thread to start the timer after the next sync. */ + startComplexTimer = phaseId; + } + if (cursor < p.count()) { + /* There are more entries, we push the next one and continue */ + pushScheduledPhase(p.get(cursor)); + continue; + } + + /* We have finished this complex phase */ + popScheduledPhase(); + if (p.timer != null) { + /* Tell the primary thread to stop the timer after the next sync. */ + stopComplexTimer = phaseId; + } + continue; + } + + default: { + VM.assertions.fail("Invalid phase type encountered"); + } + } + } + return -1; + } + + /** + * Pause all of the timers for the complex phases sitting in the stack. + */ + private static void pauseComplexTimers() { + for(int i=phaseStackPointer; i >=0; i--) { + Phase p = getPhase(getPhaseId(phaseStack[i])); + if (p.timer != null) p.timer.stop(); + } + } + + /** + * Resume all of the timers for the complex phases sitting in the stack. + */ + private static void resumeComplexTimers() { + for(int i=phaseStackPointer; i >=0; i--) { + Phase p = getPhase(getPhaseId(phaseStack[i])); + if (p.timer != null) p.timer.start(); + } + } + + /** + * Return true if phase stack is empty, false otherwise. + * + * @return true if phase stack is empty, false otherwise. + */ + @Inline + public static boolean isPhaseStackEmpty() { + return phaseStackPointer < 0; + } + + /** + * Clears the scheduled phase stack. + */ + @Inline + public static void resetPhaseStack() { + phaseStackPointer = -1; + } + + /** + * Push a scheduled phase onto the top of the work stack. + * + * @param scheduledPhase The scheduled phase. + */ + @Inline + public static void pushScheduledPhase(int scheduledPhase) { + phaseStack[++phaseStackPointer] = scheduledPhase; + complexPhaseCursor[phaseStackPointer] = 0; + } + + /** + * Increment the cursor associated with the current phase + * stack entry. This is used to remember the current sub phase + * when executing a complex phase. + * + * @return The old value of the cursor. + */ + @Inline + private static int incrementComplexPhaseCursor() { + return complexPhaseCursor[phaseStackPointer]++; + } + + /** + * Pop off the scheduled phase at the top of the work stack. + */ + @Inline + private static int popScheduledPhase() { + return phaseStack[phaseStackPointer--]; + } + + /** + * Peek the scheduled phase at the top of the work stack. + */ + @Inline + private static int peekScheduledPhase() { + return phaseStack[phaseStackPointer]; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,1051 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.policy.MarkSweepSpace; +import org.mmtk.policy.Space; +import org.mmtk.policy.ImmortalSpace; +import org.mmtk.policy.RawPageSpace; +import org.mmtk.policy.LargeObjectSpace; +import org.mmtk.utility.alloc.LinearScan; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Conversions; +import org.mmtk.utility.heap.HeapGrowthManager; +import org.mmtk.utility.heap.Map; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.*; +import org.mmtk.utility.sanitychecker.SanityChecker; +import org.mmtk.utility.statistics.PerfCounter; +import org.mmtk.utility.statistics.Timer; +import org.mmtk.utility.statistics.Stats; + +import org.mmtk.vm.VM; +import org.mmtk.vm.Collection; + + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This abstract class implements the global core functionality for all + * memory management schemes. All global MMTk plans should inherit from + * this class.

+ * + * All plans make a clear distinction between global and + * thread-local activities, and divides global and local state + * into separate class hierarchies. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. There is a single instance of Plan (or the + * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel + * threads" (aka CPUs). Thus instance + * methods of PlanLocal allow fast, unsynchronized access to functions such as + * allocation and collection. + * + * The global instance defines and manages static resources + * (such as memory and virtual memory resources). This mapping of threads to + * instances is crucial to understanding the correctness and + * performance properties of MMTk plans. + */ + at Uninterruptible +public abstract class Plan implements Constants { + /**************************************************************************** + * Constants + */ + + /* GC State */ + public static final int NOT_IN_GC = 0; // this must be zero for C code + public static final int GC_PREPARE = 1; // before setup and obtaining root + public static final int GC_PROPER = 2; + + /* Polling */ + public static final int DEFAULT_POLL_FREQUENCY = (128 << 10) >> LOG_BYTES_IN_PAGE; + public static final int META_DATA_POLL_FREQUENCY = DEFAULT_POLL_FREQUENCY; + + /* Space Size Constants. */ + public static final boolean USE_CODE_SPACE = true; + public static final float PLOS_FRAC = 0.07f; + public static final int HEAP_FULL_MINIMUM = (1 << 17) >> LOG_BYTES_IN_PAGE; // 128K + public static final int HEAP_FULL_PERCENTAGE = 2; + + /* Allocator Constants */ + public static final int ALLOC_DEFAULT = 0; + public static final int ALLOC_NON_REFERENCE = 1; + public static final int ALLOC_NON_MOVING = 2; + public static final int ALLOC_IMMORTAL = 3; + public static final int ALLOC_LOS = 4; + public static final int ALLOC_PRIMITIVE_LOS = 5; + public static final int ALLOC_GCSPY = 6; + public static final int ALLOC_CODE = 7; + public static final int ALLOC_LARGE_CODE = 8; + public static final int ALLOC_HOT_CODE = USE_CODE_SPACE ? ALLOC_CODE : ALLOC_DEFAULT; + public static final int ALLOC_COLD_CODE = USE_CODE_SPACE ? ALLOC_CODE : ALLOC_DEFAULT; + public static final int ALLOC_STACK = ALLOC_LOS; + public static final int ALLOCATORS = 9; + public static final int DEFAULT_SITE = -1; + + /* Miscellaneous Constants */ +// public static final int LOS_SIZE_THRESHOLD = SegregatedFreeListSpace.MAX_CELL_SIZE; + public static final int NON_PARTICIPANT = 0; + public static final boolean GATHER_WRITE_BARRIER_STATS = false; + public static final int DEFAULT_MIN_NURSERY = (256 * 1024) >> LOG_BYTES_IN_PAGE; + public static final int DEFAULT_MAX_NURSERY = (32 << 20) >> LOG_BYTES_IN_PAGE; + public static final boolean SCAN_BOOT_IMAGE = true; // scan it for roots rather than trace it + public static final int MAX_COLLECTION_ATTEMPTS = 10; + // public static final boolean REQUIRES_LOS = VM.activePlan.constraints().requiresLOS(); + public static final int MAX_NON_LOS_DEFAULT_ALLOC_BYTES = VM.activePlan.constraints().maxNonLOSDefaultAllocBytes(); + public static final int MAX_NON_LOS_NONMOVING_ALLOC_BYTES = VM.activePlan.constraints().maxNonLOSNonMovingAllocBytes(); + public static final int MAX_NON_LOS_COPY_BYTES = VM.activePlan.constraints().maxNonLOSCopyBytes(); + + +/* Do we support a log bit in the object header? Some write barriers may use it */ + public static final boolean NEEDS_LOG_BIT_IN_HEADER = VM.activePlan.constraints().needsLogBitInHeader(); + public static final Word LOG_SET_MASK = VM.activePlan.constraints().unloggedBit(); + private static final Word LOG_CLEAR_MASK = LOG_SET_MASK.not(); + public static final Word UNLOGGED_BIT = VM.activePlan.constraints().unloggedBit(); + + /**************************************************************************** + * Class variables + */ + + /** The space that holds any VM specific objects (e.g. a boot image) */ + public static final Space vmSpace = VM.memory.getVMSpace(); + + /** Any immortal objects allocated after booting are allocated here. */ + public static final ImmortalSpace immortalSpace = new ImmortalSpace("immortal", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + /** All meta data that is used by MMTk is allocated (and accounted for) in the meta data space. */ + public static final RawPageSpace metaDataSpace = new RawPageSpace("meta", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + /** Large objects are allocated into a special large object space. */ + public static final LargeObjectSpace loSpace = new LargeObjectSpace("los", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + /** Space used by the sanity checker (used at runtime only if sanity checking enabled */ + public static final RawPageSpace sanitySpace = new RawPageSpace("sanity", Integer.MAX_VALUE, VMRequest.create()); + + /** Space used to allocate objects that cannot be moved. we do not need a large space as the LOS is non-moving. */ + public static final MarkSweepSpace nonMovingSpace = new MarkSweepSpace("non-moving", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + public static final MarkSweepSpace smallCodeSpace = USE_CODE_SPACE ? new MarkSweepSpace("sm-code", DEFAULT_POLL_FREQUENCY, VMRequest.create()) : null; + public static final LargeObjectSpace largeCodeSpace = USE_CODE_SPACE ? new LargeObjectSpace("lg-code", DEFAULT_POLL_FREQUENCY, VMRequest.create()) : null; + + /* Space descriptors */ + public static final int IMMORTAL = immortalSpace.getDescriptor(); + public static final int VM_SPACE = vmSpace.getDescriptor(); + public static final int META = metaDataSpace.getDescriptor(); + public static final int LOS = loSpace.getDescriptor(); + public static final int SANITY = sanitySpace.getDescriptor(); + public static final int NON_MOVING = nonMovingSpace.getDescriptor(); + public static final int SMALL_CODE = USE_CODE_SPACE ? smallCodeSpace.getDescriptor() : 0; + public static final int LARGE_CODE = USE_CODE_SPACE ? largeCodeSpace.getDescriptor() : 0; + + /** Timer that counts total time */ + public static final Timer totalTime = new Timer("time"); + + /** Performance counters */ + public static final PerfCounter totalPerfCnt = new PerfCounter("perf"); + + /** Support for time-limited GCs */ + protected static long timeCap; + + /** Support for allocation-site identification */ + protected static int allocationSiteCount = 0; + + /** Global sanity checking state **/ + public static final SanityChecker sanityChecker = new SanityChecker(); + + /**************************************************************************** + * Constructor. + */ + public Plan() { + /* Create base option instances */ + Options.verbose = new Verbose(); + Options.verboseTiming = new VerboseTiming(); + Options.stressFactor = new StressFactor(); + Options.noFinalizer = new NoFinalizer(); + Options.noReferenceTypes = new NoReferenceTypes(); + Options.fullHeapSystemGC = new FullHeapSystemGC(); + Options.harnessAll = new HarnessAll(); + Options.ignoreSystemGC = new IgnoreSystemGC(); + Options.metaDataLimit = new MetaDataLimit(); + Options.nurserySize = new NurserySize(); + Options.variableSizeHeap = new VariableSizeHeap(); + Options.eagerMmapSpaces = new EagerMmapSpaces(); + Options.sanityCheck = new SanityCheck(); + Options.debugAddress = new DebugAddress(); + Options.perfMetric = new PerfMetric(); + Map.finalizeStaticSpaceMap(); + registerSpecializedMethods(); + } + + /**************************************************************************** + * Boot. + */ + + /** + * The boot method is called early in the boot process before any + * allocation. + */ + @Interruptible + public void boot() { + } + + /** + * The postBoot method is called by the runtime immediately after + * command-line arguments are available. Note that allocation must + * be supported prior to this point because the runtime + * infrastructure may require allocation in order to parse the + * command line arguments. For this reason all plans should operate + * gracefully on the default minimum heap size until the point that + * boot is called. + */ + @Interruptible + public void postBoot() { + VM.statistics.perfCtrInit(Options.perfMetric.getValue()); + if (Options.verbose.getValue() > 2) Space.printVMMap(); + if (Options.verbose.getValue() > 3) VM.config.printConfig(); + if (Options.verbose.getValue() > 0) Stats.startAll(); + if (Options.eagerMmapSpaces.getValue()) Space.eagerlyMmapMMTkSpaces(); + } + + /** + * The fullyBooted method is called by the runtime just before normal + * execution commences. + */ + @Interruptible + public void fullyBooted() { + initialized = true; + if (Options.harnessAll.getValue()) harnessBegin(); + } + + /** + * The VM is about to exit. Perform any clean up operations. + * + * @param value The exit value + */ + @Interruptible + public void notifyExit(int value) { + if (Options.harnessAll.getValue()) harnessEnd(); + if (Options.verbose.getValue() == 1) { + Log.write("[End "); + totalTime.printTotalSecs(); + Log.writeln(" s]"); + } else if (Options.verbose.getValue() == 2) { + Log.write("[End "); + totalTime.printTotalMillis(); + Log.writeln(" ms]"); + } + if (Options.verboseTiming.getValue()) printDetailedTiming(true); + } + + /** + * Any Plan can override this to provide additional plan specific + * timing information. + * + * @param totals Print totals + */ + protected void printDetailedTiming(boolean totals) {} + + /** + * Perform any required initialization of the GC portion of the header. + * Called for objects created at boot time. + * + * @param ref the object ref to the storage to be initialized + * @param typeRef the type reference for the instance being created + * @param size the number of bytes allocated by the GC system for + * this object. + * @param status the initial value of the status word + * @return The new value of the status word + */ + @Inline + public Word setBootTimeGCBits(Address ref, ObjectReference typeRef, + int size, Word status) { + if (NEEDS_LOG_BIT_IN_HEADER) + return status.or(UNLOGGED_BIT); + else + return status; // nothing to do (no bytes of GC header) + } + + /** + * Perform any required write barrier action when installing an object reference + * a boot time. + * + * @param reference the reference value that is to be stored + * @return The raw value to be + */ + public Word bootTimeWriteBarrier(Word reference) { + return reference; + } + + /**************************************************************************** + * Allocation + */ + public static int getAllocationSite(boolean compileTime) { + if (compileTime) // a new allocation site is being compiled + return allocationSiteCount++; + else // an anonymous site + return DEFAULT_SITE; + } + + /**************************************************************************** + * Collection. + */ + + /** + * Perform a (global) collection phase. + */ + public abstract void collectionPhase(short phase); + + /** + * Replace a phase. + * + * @param oldScheduledPhase The scheduled phase to insert after + * @param scheduledPhase The scheduled phase to insert + */ + @Interruptible + public void replacePhase(int oldScheduledPhase, int scheduledPhase) { + VM.assertions.fail("replacePhase not implemented for this plan"); + } + + + /** + * Insert a phase. + * + * @param markerScheduledPhase The scheduled phase to insert after + * @param scheduledPhase The scheduled phase to insert + */ + @Interruptible + public void insertPhaseAfter(int markerScheduledPhase, int scheduledPhase) { + short tempPhase = Phase.createComplex("auto-gen", null, markerScheduledPhase, scheduledPhase); + replacePhase(markerScheduledPhase, Phase.scheduleComplex(tempPhase)); + } + + /** + * @return Whether last GC was an exhaustive attempt to collect the heap. For many collectors this is the same as asking whether the last GC was a full heap collection. + */ + public boolean lastCollectionWasExhaustive() { + return lastCollectionFullHeap(); + } + + /** + * @return Whether last GC is a full GC. + */ + public boolean lastCollectionFullHeap() { + return true; + } + + /** + * @return Is last GC a full collection? + */ + public static boolean isEmergencyCollection() { + return emergencyCollection; + } + + /** + * @return True if we have run out of heap space. + */ + public final boolean lastCollectionFailed() { + return !(collectionTrigger == Collection.EXTERNAL_GC_TRIGGER || + collectionTrigger == Collection.INTERNAL_PHASE_GC_TRIGGER) && + (getPagesAvail() < getHeapFullThreshold() || getPagesAvail() < requiredAtStart); + } + + /** + * Force the next collection to be full heap. + */ + public void forceFullHeapCollection() {} + + /** + * @return Is current GC only collecting objects allocated since last GC. + */ + public boolean isCurrentGCNursery() { + return false; + } + + private long lastStressPages = 0; + + /** + * Return the expected reference count. For non-reference counting + * collectors this becomes a true/false relationship. + * + * @param object The object to check. + * @param sanityRootRC The number of root references to the object. + * @return The expected (root excluded) reference count. + */ + public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { + Space space = Space.getSpaceForObject(object); + return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD; + } + + /** + * Perform a linear scan of all spaces to check for possible leaks. + * This is only called after a full-heap GC. + * + * @param scanner The scanner callback to use. + */ + public void sanityLinearScan(LinearScan scanner) { + } + + /** + * @return True is a stress test GC is required + */ + @Inline + public final boolean stressTestGCRequired() { + long pages = Space.cumulativeCommittedPages(); + if (initialized && + ((pages ^ lastStressPages) > Options.stressFactor.getPages())) { + lastStressPages = pages; + return true; + } else + return false; + } + + /**************************************************************************** + * GC State + */ + + protected static int requiredAtStart; + protected static int collectionTrigger; + protected static boolean emergencyCollection; + protected static boolean awaitingAsyncCollection; + protected static boolean stacksPrepared; + + private static boolean initialized = false; + private static boolean collectionTriggered; + @Entrypoint + private static int gcStatus = NOT_IN_GC; // shared variable + + /** @return Is the memory management system initialized? */ + public static boolean isInitialized() { + return initialized; + } + + /** + * Has collection has triggered? + */ + public static boolean isCollectionTriggered() { + return collectionTriggered; + } + + /** + * Set that a collection has been triggered. + */ + public static void setCollectionTriggered() { + collectionTriggered = true; + } + + /** + * A collection has fully completed. Clear the triggered flag. + */ + public static void collectionComplete() { + collectionTriggered = false; + } + + /** + * Return true if stacks have been prepared in this collection cycle. + * + * @return True if stacks have been prepared in this collection cycle. + */ + public static boolean stacksPrepared() { + return stacksPrepared; + } + /** + * Return true if a collection is in progress. + * + * @return True if a collection is in progress. + */ + public static boolean gcInProgress() { + return gcStatus != NOT_IN_GC; + } + + /** + * Return true if a collection is in progress and past the preparatory stage. + * + * @return True if a collection is in progress and past the preparatory stage. + */ + public static boolean gcInProgressProper() { + return gcStatus == GC_PROPER; + } + + /** + * Sets the GC status. + * + * @param s The new GC status. + */ + public static void setGCStatus(int s) { + if (gcStatus == NOT_IN_GC) { + /* From NOT_IN_GC to any phase */ + stacksPrepared = false; + if (Stats.gatheringStats()) { + Stats.startGC(); + VM.activePlan.global().printPreStats(); + } + } + VM.memory.isync(); + gcStatus = s; + VM.memory.sync(); + if (gcStatus == NOT_IN_GC) { + /* From any phase to NOT_IN_GC */ + if (Stats.gatheringStats()) { + Stats.endGC(); + VM.activePlan.global().printPostStats(); + } + } + } + + /** + * Print out statistics at the start of a GC + */ + public void printPreStats() { + if ((Options.verbose.getValue() == 1) || + (Options.verbose.getValue() == 2)) { + Log.write("[GC "); Log.write(Stats.gcCount()); + if (Options.verbose.getValue() == 1) { + Log.write(" Start "); + Plan.totalTime.printTotalSecs(); + Log.write(" s"); + } else { + Log.write(" Start "); + Plan.totalTime.printTotalMillis(); + Log.write(" ms"); + } + Log.write(" "); + Log.write(Conversions.pagesToKBytes(getPagesUsed())); + Log.write("KB "); + Log.flush(); + } + if (Options.verbose.getValue() > 2) { + Log.write("Collection "); Log.write(Stats.gcCount()); + Log.write(": "); + printUsedPages(); + Log.write(" Before Collection: "); + Space.printUsageMB(); + if (Options.verbose.getValue() >= 4) { + Log.write(" "); + Space.printUsagePages(); + } + if (Options.verbose.getValue() >= 5) { + Space.printVMMap(); + } + } + } + + /** + * Print out statistics at the end of a GC + */ + public final void printPostStats() { + if ((Options.verbose.getValue() == 1) || + (Options.verbose.getValue() == 2)) { + Log.write("-> "); + Log.writeDec(Conversions.pagesToBytes(getPagesUsed()).toWord().rshl(10)); + Log.write("KB "); + if (Options.verbose.getValue() == 1) { + totalTime.printLast(); + Log.writeln(" ms]"); + } else { + Log.write("End "); + totalTime.printTotal(); + Log.writeln(" ms]"); + } + } + if (Options.verbose.getValue() > 2) { + Log.write(" After Collection: "); + Space.printUsageMB(); + if (Options.verbose.getValue() >= 4) { + Log.write(" "); + Space.printUsagePages(); + } + if (Options.verbose.getValue() >= 5) { + Space.printVMMap(); + } + Log.write(" "); + printUsedPages(); + Log.write(" Collection time: "); + totalTime.printLast(); + Log.writeln(" ms"); + } + } + + public final void printUsedPages() { + Log.write("reserved = "); + Log.write(Conversions.pagesToMBytes(getPagesReserved())); + Log.write(" MB ("); + Log.write(getPagesReserved()); + Log.write(" pgs)"); + Log.write(" total = "); + Log.write(Conversions.pagesToMBytes(getTotalPages())); + Log.write(" MB ("); + Log.write(getTotalPages()); + Log.write(" pgs)"); + Log.writeln(); + } + + /** + * Set the collection trigger. + */ + public static void setCollectionTrigger(int trigger) { + collectionTrigger = trigger; + } + + /**************************************************************************** + * Harness + */ + protected static boolean insideHarness = false; + + /** + * Generic hook to allow benchmarks to be harnessed. A plan may use + * this to perform certain actions prior to the commencement of a + * benchmark, such as a full heap collection, turning on + * instrumentation, etc. By default we do a full heap GC, + * and then start stats collection. + */ + @Interruptible + public static void harnessBegin() { + // Save old values. + boolean oldFullHeap = Options.fullHeapSystemGC.getValue(); + boolean oldIgnore = Options.ignoreSystemGC.getValue(); + + // Set desired values. + Options.fullHeapSystemGC.setValue(true); + Options.ignoreSystemGC.setValue(false); + + // Trigger a full heap GC. + System.gc(); + + // Restore old values. + Options.ignoreSystemGC.setValue(oldIgnore); + Options.fullHeapSystemGC.setValue(oldFullHeap); + + // Start statistics + insideHarness = true; + Stats.startAll(); + } + + /** + * Generic hook to allow benchmarks to be harnessed. A plan may use + * this to perform certain actions after the completion of a + * benchmark, such as a full heap collection, turning off + * instrumentation, etc. By default we stop all statistics objects + * and print their values. + */ + @Interruptible + public static void harnessEnd() { + Stats.stopAll(); + insideHarness = false; + } + + /**************************************************************************** + * VM Accounting + */ + + /* Global accounting and static access */ + + /** + * Return the amount of free memory, in bytes (where free is + * defined as not in use). Note that this may overstate the amount + * of available memory, which must account for unused memory + * that is held in reserve for copying, and therefore unavailable + * for allocation. + * + * @return The amount of free memory, in bytes (where free is + * defined as not in use). + */ + public static Extent freeMemory() { + return totalMemory().minus(usedMemory()); + } + + /** + * Return the amount of available memory, in bytes. Note + * that this accounts for unused memory that is held in reserve + * for copying, and therefore unavailable for allocation. + * + * @return The amount of available memory, in bytes. + */ + public static Extent availableMemory() { + return totalMemory().minus(reservedMemory()); + } + + /** + * Return the amount of memory in use, in bytes. Note that + * this excludes unused memory that is held in reserve for copying, + * and therefore unavailable for allocation. + * + * @return The amount of memory in use, in bytes. + */ + public static Extent usedMemory() { + return Conversions.pagesToBytes(VM.activePlan.global().getPagesUsed()); + } + + + /** + * Return the amount of memory in use, in bytes. Note that + * this includes unused memory that is held in reserve for copying, + * and therefore unavailable for allocation. + * + * @return The amount of memory in use, in bytes. + */ + public static Extent reservedMemory() { + return Conversions.pagesToBytes(VM.activePlan.global().getPagesReserved()); + } + + /** + * Return the total amount of memory managed to the memory + * management system, in bytes. + * + * @return The total amount of memory managed to the memory + * management system, in bytes. + */ + public static Extent totalMemory() { + return HeapGrowthManager.getCurrentHeapSize(); + } + + /* Instance methods */ + + /** + * Return the total amount of memory managed to the memory + * management system, in pages. + * + * @return The total amount of memory managed to the memory + * management system, in pages. + */ + public final int getTotalPages() { + return totalMemory().toWord().rshl(LOG_BYTES_IN_PAGE).toInt(); + } + + /** + * Return the number of pages available for allocation. + * + * @return The number of pages available for allocation. + */ + public int getPagesAvail() { + return getTotalPages() - getPagesReserved(); + } + + /** + * Return the number of pages reserved for use given the pending + * allocation. Sub-classes must override the getCopyReserve method, + * as the arithmetic here is fixed. + * + * @return The number of pages reserved given the pending + * allocation, including space reserved for copying. + */ + public final int getPagesReserved() { + return getPagesUsed() + getCollectionReserve(); + } + + /** + * Return the number of pages reserved for collection. + * In most cases this is a copy reserve, all subclasses that + * manage a copying space must add the copying contribution. + * + * @return The number of pages reserved given the pending + * allocation, including space reserved for collection. + */ + public int getCollectionReserve() { + return 0; + } + + /** + * Return the number of pages reserved for use given the pending + * allocation. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public int getPagesUsed() { + return loSpace.reservedPages() + + immortalSpace.reservedPages() + metaDataSpace.reservedPages() + + nonMovingSpace.reservedPages(); + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return loSpace.requiredPages() + + metaDataSpace.requiredPages() + immortalSpace.requiredPages() + + nonMovingSpace.requiredPages(); + } + + /** + * The minimum number of pages a GC must have available after a collection + * for us to consider the collection successful. + */ + public int getHeapFullThreshold() { + int threshold = (getTotalPages() * HEAP_FULL_PERCENTAGE) / 100; + if (threshold < HEAP_FULL_MINIMUM) threshold = HEAP_FULL_MINIMUM; + return threshold; + } + + /** + * Return the number of metadata pages reserved for use given the pending + * allocation. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public int getMetaDataPagesUsed() { + return metaDataSpace.reservedPages(); + } + + /** + * Return the cycle time at which this GC should complete. + * + * @return The time cap for this GC (i.e. the time by which it + * should complete). + */ + public static long getTimeCap() { + return timeCap; + } + + /**************************************************************************** + * Internal read/write barriers. + */ + + /** + * Store an object reference + * + * @param slot The location of the reference + * @param value The value to store + */ + @Inline + public void storeObjectReference(Address slot, ObjectReference value) { + slot.store(value); + } + + /** + * Load an object reference + * + * @param slot The location of the reference + * @return the object reference loaded from slot + */ + @Inline + public ObjectReference loadObjectReference(Address slot) { + return slot.loadObjectReference(); + } + + /**************************************************************************** + * Collection. + */ + + /** + * This method is called periodically by the allocation subsystem + * (by default, each time a page is consumed), and provides the + * collector with an opportunity to collect. + * + * @param spaceFull Space request failed, must recover pages within 'space'. + * @param space The space that triggered the poll. + * @return true if a collection is required. + */ + @LogicallyUninterruptible + public final boolean poll(boolean spaceFull, Space space) { + if (isCollectionTriggered()) { + if (space == metaDataSpace) { + /* This is not, in general, in a GC safe point. */ + return false; + } + /* Someone else initiated a collection, we should join it */ + logPoll(space, "Joining collection"); + VM.collection.joinCollection(); + return true; + } + + if (collectionRequired(spaceFull)) { + if (space == metaDataSpace) { + /* In general we must not trigger a GC on metadata allocation since + * this is not, in general, in a GC safe point. Instead we initiate + * an asynchronous GC, which will occur at the next safe point. + */ + logPoll(space, "Asynchronous collection requested"); + setAwaitingAsyncCollection(); + return false; + } + logPoll(space, "Triggering collection"); + VM.collection.triggerCollection(Collection.RESOURCE_GC_TRIGGER); + return true; + } + + if (concurrentCollectionRequired()) { + logPoll(space, "Triggering collection"); + VM.collection.triggerCollection(Collection.INTERNAL_PHASE_GC_TRIGGER); + return true; + } + + return false; + } + + /** + * Check whether an asynchronous collection is pending.

+ * + * This is decoupled from the poll() mechanism because the + * triggering of asynchronous collections can trigger write + * barriers, which can trigger an asynchronous collection. Thus, if + * the triggering were tightly coupled with the request to alloc() + * within the write buffer code, then inifinite regress could + * result. There is no race condition in the following code since + * there is no harm in triggering the collection more than once, + * thus it is unsynchronized. + */ + @Inline + public static void checkForAsyncCollection() { + if (awaitingAsyncCollection && VM.collection.noThreadsInGC()) { + awaitingAsyncCollection = false; + VM.collection.triggerAsyncCollection(Collection.RESOURCE_GC_TRIGGER); + } + } + + /** Request an async GC */ + protected static void setAwaitingAsyncCollection() { + awaitingAsyncCollection = true; + } + + /** + * Log a message from within 'poll' + * @param space + * @param message + */ + private void logPoll(Space space, String message) { + if (Options.verbose.getValue() >= 3) { + Log.write(" [POLL] "); + Log.write(space.getName()); + Log.write(": "); + Log.writeln(message); + } + } + + /** + * This method controls the triggering of a GC. It is called periodically + * during allocation. Returns true to trigger a collection. + * + * @param spaceFull Space request failed, must recover pages within 'space'. + * @return True if a collection is requested by the plan. + */ + protected boolean collectionRequired(boolean spaceFull) { + boolean stressForceGC = stressTestGCRequired(); + boolean heapFull = getPagesReserved() > getTotalPages(); + + return spaceFull || stressForceGC || heapFull; + } + + /** + * This method controls the triggering of an atomic phase of a concurrent + * collection. It is called periodically during allocation. + * + * @return True if a collection is requested by the plan. + */ + protected boolean concurrentCollectionRequired() { + return false; + } + + /** + * Start GCspy server. + * + * @param port The port to listen on, + * @param wait Should we wait for a client to connect? + */ + @Interruptible + public void startGCspyServer(int port, boolean wait) { + VM.assertions.fail("startGCspyServer called on non GCspy plan"); + } + + /** + * Can this object ever move. Used by the VM to make decisions about + * whether it needs to copy IO buffers etc. + * + * @param object The object in question + * @return True if it is not possible that the object will ever move. + */ + public boolean willNeverMove(ObjectReference object) { + if (!VM.activePlan.constraints().movesObjects()) + return true; + if (Space.isInSpace(LOS, object)) + return true; + if (Space.isInSpace(IMMORTAL, object)) + return true; + if (Space.isInSpace(VM_SPACE, object)) + return true; + if (Space.isInSpace(NON_MOVING, object)) + return true; + if (USE_CODE_SPACE && Space.isInSpace(SMALL_CODE, object)) + return true; + if (USE_CODE_SPACE && Space.isInSpace(LARGE_CODE, object)) + return true; + /* + * Default to false- this preserves correctness over efficiency. + * Individual plans should override for non-moving spaces they define. + */ + return false; + } + + /**************************************************************************** + * Support for logging bits (this is cross-cutting). + */ + + /** + * Return true if the specified object needs to be logged. + * + * @param src The object in question + * @return True if the object in question needs to be logged (remembered). + */ + public static final boolean logRequired(ObjectReference src) { + int value = VM.objectModel.readAvailableByte(src); + return !((value & LOG_SET_MASK.toInt()) == 0); + } + + /** + * Mark an object as logged. Since duplicate logging does + * not raise any correctness issues, we do not worry + * about synchronization and allow threads to race to log the + * object, potentially including it twice (unlike reference + * counting where duplicates would lead to incorrect reference + * counts). + * + * @param object The object to be marked as logged + */ + public static final void markAsLogged(ObjectReference object) { + int value = VM.objectModel.readAvailableByte(object); + VM.objectModel.writeAvailableByte(object, (byte) (value & LOG_CLEAR_MASK.toInt())); + } + + /** + * Mark an object as unlogged. + * + * @param object The object to be marked as unlogged + */ + public static final void markAsUnlogged(ObjectReference object) { + int value = VM.objectModel.readAvailableByte(object); + VM.objectModel.writeAvailableByte(object, (byte) (value | UNLOGGED_BIT.toInt())); + } + + /**************************************************************************** + * Specialized Methods + */ + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + } + + /** + * Get the specialized scan with the given id. + */ + public final Class getSpecializedScanClass(int id) { + return TransitiveClosure.getSpecializedScanClass(id); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,92 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.policy.SegregatedFreeListSpace; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Word; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible public abstract class PlanConstraints { + /** @return True if this Plan requires write barriers. */ + public boolean needsWriteBarrier() { return false; } + + /** @return True of this Plan requires read barriers on reference types. */ + public boolean needsReferenceTypeReadBarrier() { return false; } + + /** @return True of this Plan requires read barriers. */ + public boolean needsReadBarrier() { return false; } + + /** @return True if this Plan requires static write barriers. */ + public boolean needsStaticWriteBarrier() { return false;} + + /** @return True if this Plan requires static read barriers. */ + public boolean needsStaticReadBarrier() { return false; } + + /** @return True if this Plan requires linear scanning. */ + public boolean needsLinearScan() { return org.mmtk.utility.Constants.SUPPORT_CARD_SCANNING;} + + /** @return True if this Plan does not support parallel collection. */ + public boolean noParallelGC() { return false;} + + /** @return True if this Plan moves objects. */ + public boolean movesObjects() { return false;} + + /** @return Size (in bytes) beyond which new regular objects must be allocated to the LOS */ + public int maxNonLOSDefaultAllocBytes() { return org.mmtk.utility.Constants.MAX_INT;} + + /** @return Size (in bytes) beyond which new non-moving objects must be allocated to the LOS */ + public int maxNonLOSNonMovingAllocBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;} + + /** @return Size (in bytes) beyond which copied objects must be copied to the LOS */ + public int maxNonLOSCopyBytes() { return org.mmtk.utility.Constants.MAX_INT;} + + /** @return True if this object forwards objects after + * determining global object liveness (e.g. many compacting collectors). */ + public boolean needsForwardAfterLiveness() { return false;} + + /** @return Is this plan generational in nature. */ + public boolean generational() { return false;} + + /** @return The number of header bits that are required. */ + public abstract int gcHeaderBits(); + + /** @return The number of header words that are required. */ + public abstract int gcHeaderWords(); + + /** @return True if this plan contains GCspy. */ + public boolean withGCspy() { return false; } + + /** @return True if this plan contains GCTrace. */ + public boolean generateGCTrace() { return false; } + + /** @return The specialized scan methods required */ + public int numSpecializedScans() { return 0; } + + /** @return True if this plan requires concurrent worker threads */ + public boolean needsConcurrentWorkers() { return false; } + + /** @return True if this Plan requires a header bit for object logging */ + public boolean needsLogBitInHeader() { return false; } + + /** @return A bit which represents that a header is unlogged */ + public Word unloggedBit() {return Word.zero(); } + + /** @return A bit which represents that a header is unlogged */ + public Word logSetBitMask() {return Word.zero(); } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,286 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.policy.Space; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.*; +import org.mmtk.utility.statistics.Timer; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This abstract class implements the core functionality for + * simple collectors.

+ * + * This class defines the collection phases, and provides base + * level implementations of them. Subclasses should provide + * implementations for the spaces that they introduce, and + * delegate up the class hierarchy.

+ * + * For details of the split between global and thread-local operations + * @see org.mmtk.plan.Plan + */ + at Uninterruptible +public abstract class Simple extends Plan implements Constants { + /**************************************************************************** + * Constants + */ + + /* Shared Timers */ + private static final Timer refTypeTime = new Timer("refType", false, true); + private static final Timer scanTime = new Timer("scan", false, true); + private static final Timer finalizeTime = new Timer("finalize", false, true); + + /* Phases */ + public static final short SET_COLLECTION_KIND = Phase.createSimple("set-collection-kind", null); + public static final short INITIATE = Phase.createSimple("initiate", null); + public static final short PREPARE = Phase.createSimple("prepare"); + public static final short PRECOPY = Phase.createSimple("precopy"); + public static final short PREPARE_STACKS = Phase.createSimple("prepare-stacks", null); + public static final short STACK_ROOTS = Phase.createSimple("stacks"); + public static final short ROOTS = Phase.createSimple("root"); + public static final short CLOSURE = Phase.createSimple("closure", scanTime); + public static final short SOFT_REFS = Phase.createSimple("soft-ref", refTypeTime); + public static final short WEAK_REFS = Phase.createSimple("weak-ref", refTypeTime); + public static final short FINALIZABLE = Phase.createSimple("finalize", finalizeTime); + public static final short WEAK_TRACK_REFS = Phase.createSimple("weak-track-ref", refTypeTime); + public static final short PHANTOM_REFS = Phase.createSimple("phantom-ref", refTypeTime); + public static final short FORWARD = Phase.createSimple("forward"); + public static final short FORWARD_REFS = Phase.createSimple("forward-ref", refTypeTime); + public static final short FORWARD_FINALIZABLE = Phase.createSimple("forward-finalize", finalizeTime); + public static final short RELEASE = Phase.createSimple("release"); + public static final short COMPLETE = Phase.createSimple("complete", null); + + /* Sanity placeholder */ + public static final short PRE_SANITY_PLACEHOLDER = Phase.createSimple("pre-sanity-placeholder", null); + public static final short POST_SANITY_PLACEHOLDER = Phase.createSimple("post-sanity-placeholder", null); + + /* Sanity phases */ + public static final short SANITY_SET_PREGC = Phase.createSimple("sanity-setpre", null); + public static final short SANITY_SET_POSTGC = Phase.createSimple("sanity-setpost", null); + public static final short SANITY_PREPARE = Phase.createSimple("sanity-prepare", null); + public static final short SANITY_ROOTS = Phase.createSimple("sanity-roots", null); + public static final short SANITY_COPY_ROOTS = Phase.createSimple("sanity-copy-roots", null); + public static final short SANITY_BUILD_TABLE = Phase.createSimple("sanity-build-table", null); + public static final short SANITY_CHECK_TABLE = Phase.createSimple("sanity-check-table", null); + public static final short SANITY_RELEASE = Phase.createSimple("sanity-release", null); + + // CHECKSTYLE:OFF + + /** Ensure stacks are ready to be scanned */ + protected static final short prepareStacks = Phase.createComplex("prepare-stacks", null, + Phase.scheduleCollector (PREPARE_STACKS), + Phase.scheduleMutator (PREPARE_STACKS), + Phase.scheduleGlobal (PREPARE_STACKS)); + + /** Trace and set up a sanity table */ + protected static final short sanityBuildPhase = Phase.createComplex("sanity-build", null, + Phase.scheduleGlobal (SANITY_PREPARE), + Phase.scheduleCollector (SANITY_PREPARE), + Phase.scheduleComplex (prepareStacks), + Phase.scheduleCollector (SANITY_ROOTS), + Phase.scheduleGlobal (SANITY_ROOTS), + Phase.scheduleCollector (SANITY_COPY_ROOTS), + Phase.scheduleGlobal (SANITY_BUILD_TABLE)); + + /** Validate a sanity table */ + protected static final short sanityCheckPhase = Phase.createComplex("sanity-check", null, + Phase.scheduleGlobal (SANITY_CHECK_TABLE), + Phase.scheduleCollector (SANITY_RELEASE), + Phase.scheduleGlobal (SANITY_RELEASE)); + + /** Start the collection, including preparation for any collected spaces. */ + protected static final short initPhase = Phase.createComplex("init", + Phase.scheduleGlobal (SET_COLLECTION_KIND), + Phase.scheduleGlobal (INITIATE), + Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER)); + + /** + * Perform the initial determination of liveness from the roots. + */ + protected static final short rootClosurePhase = Phase.createComplex("initial-closure", null, + Phase.scheduleMutator (PREPARE), + Phase.scheduleGlobal (PREPARE), + Phase.scheduleCollector (PREPARE), + Phase.scheduleComplex (prepareStacks), + Phase.scheduleCollector (PRECOPY), + Phase.scheduleCollector (STACK_ROOTS), + Phase.scheduleCollector (ROOTS), + Phase.scheduleGlobal (ROOTS), + Phase.scheduleGlobal (CLOSURE), + Phase.scheduleCollector (CLOSURE)); + + /** + * Complete closure including reference types and finalizable objects. + */ + protected static final short refTypeClosurePhase = Phase.createComplex("refType-closure", null, + Phase.scheduleCollector (SOFT_REFS), + Phase.scheduleGlobal (CLOSURE), + Phase.scheduleCollector (CLOSURE), + Phase.scheduleCollector (WEAK_REFS), + Phase.scheduleCollector (FINALIZABLE), + Phase.scheduleGlobal (CLOSURE), + Phase.scheduleCollector (CLOSURE), + Phase.schedulePlaceholder(WEAK_TRACK_REFS), + Phase.scheduleCollector (PHANTOM_REFS)); + + /** + * Ensure that all references in the system are correct. + */ + protected static final short forwardPhase = Phase.createComplex("forward-all", null, + /* Finish up */ + Phase.schedulePlaceholder(FORWARD), + Phase.scheduleCollector (FORWARD_REFS), + Phase.scheduleCollector (FORWARD_FINALIZABLE)); + + /** + * Complete closure including reference types and finalizable objects. + */ + protected static final short completeClosurePhase = Phase.createComplex("release", null, + Phase.scheduleMutator (RELEASE), + Phase.scheduleCollector (RELEASE), + Phase.scheduleGlobal (RELEASE)); + + + /** + * The collection scheme - this is a small tree of complex phases. + */ + protected static final short finishPhase = Phase.createComplex("finish", + Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER), + Phase.scheduleCollector (COMPLETE), + Phase.scheduleGlobal (COMPLETE)); + + /** + * This is the phase that is executed to perform a collection. + */ + public short collection = Phase.createComplex("collection", null, + Phase.scheduleComplex(initPhase), + Phase.scheduleComplex(rootClosurePhase), + Phase.scheduleComplex(refTypeClosurePhase), + Phase.scheduleComplex(forwardPhase), + Phase.scheduleComplex(completeClosurePhase), + Phase.scheduleComplex(finishPhase)); + + // CHECKSTYLE:ON + + /** + * The current collection attempt. + */ + protected int collectionAttempt; + + /**************************************************************************** + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId The unique of the phase to perform. + */ + @Inline + public void collectionPhase(short phaseId) { + if (phaseId == SET_COLLECTION_KIND) { + requiredAtStart = getPagesRequired(); + collectionAttempt = VM.collection.maximumCollectionAttempt(); + emergencyCollection = lastCollectionWasExhaustive() && collectionAttempt > 1; + if (collectionAttempt > MAX_COLLECTION_ATTEMPTS) { + VM.assertions.fail("Too many collection attempts. Suspect plan is not setting FullHeap flag"); + } + if (emergencyCollection) { + if (Options.verbose.getValue() >= 1) Log.write("[Emergency]"); + forceFullHeapCollection(); + } + return; + } + + if (phaseId == INITIATE) { + setGCStatus(GC_PREPARE); + return; + } + + if (phaseId == PREPARE_STACKS) { + stacksPrepared = true; + return; + } + + if (phaseId == PREPARE) { + loSpace.prepare(true); + nonMovingSpace.prepare(true); + if (USE_CODE_SPACE) { + smallCodeSpace.prepare(true); + largeCodeSpace.prepare(true); + } + immortalSpace.prepare(); + VM.memory.globalPrepareVMSpace(); + return; + } + + if (phaseId == ROOTS) { + VM.scanning.resetThreadCounter(); + setGCStatus(GC_PROPER); + return; + } + + if (phaseId == RELEASE) { + loSpace.release(true); + nonMovingSpace.release(); + if (USE_CODE_SPACE) { + smallCodeSpace.release(); + largeCodeSpace.release(true); + } + immortalSpace.release(); + VM.memory.globalReleaseVMSpace(); + return; + } + + if (phaseId == COMPLETE) { + setGCStatus(NOT_IN_GC); + Space.clearAllAllocationFailed(); + awaitingAsyncCollection = false; + return; + } + + if (Options.sanityCheck.getValue() && sanityChecker.collectionPhase(phaseId)) { + return; + } + + Log.write("Global phase "); Log.write(Phase.getName(phaseId)); + Log.writeln(" not handled."); + VM.assertions.fail("Global phase not handled!"); + } + + /** + * Replace a scheduled phase. Used for example to replace a placeholder. + * + * @param oldScheduledPhase The scheduled phase to replace. + * @param newScheduledPhase The new scheduled phase. + */ + public void replacePhase(int oldScheduledPhase, int newScheduledPhase) { + ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection); + cp.replacePhase(oldScheduledPhase, newScheduledPhase); + } + + /** + * Replace a placeholder phase. + * + * @param placeHolderPhase The placeholder phase + * @param newScheduledPhase The new scheduled phase. + */ + public void replacePlaceholderPhase(short placeHolderPhase, int newScheduledPhase) { + ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection); + cp.replacePhase(Phase.schedulePlaceholder(placeHolderPhase), newScheduledPhase); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,174 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class (and its sub-classes) implement per-collector thread + * behavior and state. + * + * MMTk assumes that the VM instantiates instances of CollectorContext + * in thread local storage (TLS) for each thread participating in + * collection. Accesses to this state are therefore assumed to be + * low-cost during mutator time.

+ * + * @see CollectorContext + */ + at Uninterruptible +public abstract class SimpleCollector extends CollectorContext { + + /**************************************************************************** + * Instance fields + */ + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The unique phase identifier + * @param primary Should this thread be used to execute any single-threaded + * local operations? + */ + @Inline + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == Simple.PREPARE_STACKS) { + if (!Plan.stacksPrepared()) { + VM.collection.prepareCollector(this); + } + return; + } + + if (phaseId == Simple.PREPARE) { + // Nothing to do + return; + } + + if (phaseId == Simple.PRECOPY) { + if (VM.activePlan.constraints().movesObjects()) { + VM.scanning.preCopyGCInstances(getCurrentTrace()); + } + return; + } + + if (phaseId == Simple.STACK_ROOTS) { + VM.scanning.computeThreadRoots(getCurrentTrace()); + return; + } + + if (phaseId == Simple.ROOTS) { + VM.scanning.computeGlobalRoots(getCurrentTrace()); + VM.scanning.computeStaticRoots(getCurrentTrace()); + if (Plan.SCAN_BOOT_IMAGE) { + VM.scanning.computeBootImageRoots(getCurrentTrace()); + } + return; + } + + if (phaseId == Simple.SOFT_REFS) { + if (primary) { + if (Options.noReferenceTypes.getValue()) + VM.softReferences.clear(); + else + VM.softReferences.scan(getCurrentTrace(),global().isCurrentGCNursery()); + } + return; + } + + if (phaseId == Simple.WEAK_REFS) { + if (primary) { + if (Options.noReferenceTypes.getValue()) + VM.weakReferences.clear(); + else + VM.weakReferences.scan(getCurrentTrace(),global().isCurrentGCNursery()); + } + return; + } + + if (phaseId == Simple.FINALIZABLE) { + if (primary) { + if (Options.noFinalizer.getValue()) + VM.finalizableProcessor.clear(); + else + VM.finalizableProcessor.scan(getCurrentTrace(),global().isCurrentGCNursery()); + } + return; + } + + if (phaseId == Simple.PHANTOM_REFS) { + if (primary) { + if (Options.noReferenceTypes.getValue()) + VM.phantomReferences.clear(); + else + VM.phantomReferences.scan(getCurrentTrace(),global().isCurrentGCNursery()); + } + return; + } + + if (phaseId == Simple.FORWARD_REFS) { + if (primary && !Options.noReferenceTypes.getValue() && + VM.activePlan.constraints().needsForwardAfterLiveness()) { + VM.softReferences.forward(getCurrentTrace(),global().isCurrentGCNursery()); + VM.weakReferences.forward(getCurrentTrace(),global().isCurrentGCNursery()); + VM.phantomReferences.forward(getCurrentTrace(),global().isCurrentGCNursery()); + } + return; + } + + if (phaseId == Simple.FORWARD_FINALIZABLE) { + if (primary && !Options.noFinalizer.getValue() && + VM.activePlan.constraints().needsForwardAfterLiveness()) { + VM.finalizableProcessor.forward(getCurrentTrace(),global().isCurrentGCNursery()); + } + return; + } + + if (phaseId == Simple.COMPLETE) { + // Nothing to do + return; + } + + if (phaseId == Simple.RELEASE) { + // Nothing to do + return; + } + + if (Options.sanityCheck.getValue() && sanityLocal.collectionPhase(phaseId, primary)) { + return; + } + + Log.write("Per-collector phase "); Log.write(Phase.getName(phaseId)); + Log.writeln(" not handled."); + VM.assertions.fail("Per-collector phase not handled!"); + } + + /**************************************************************************** + * + * Miscellaneous. + */ + + /** @return The active global plan as a Simple instance. */ + @Inline + private static Simple global() { + return (Simple) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,22 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.vmmagic.pragma.*; + +/** + * Constraints specific to simple collectors. + */ + at Uninterruptible +public abstract class SimpleConstraints extends PlanConstraints { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,73 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.Log; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class (and its sub-classes) implement per-mutator thread + * behavior and state. + * + * MMTk assumes that the VM instantiates instances of MutatorContext + * in thread local storage (TLS) for each application thread. Accesses + * to this state are therefore assumed to be low-cost during mutator + * time.

+ * + * @see MutatorContext + */ + at Uninterruptible +public abstract class SimpleMutator extends MutatorContext { + + /**************************************************************************** + * + * Collection. + */ + + /** + * Perform a per-mutator collection phase. This is executed by + * one collector thread on behalf of a mutator thread. + * + * @param phaseId The unique phase identifier + * @param primary Should this thread be used to execute any single-threaded + * local operations? + */ + @Inline + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == Simple.PREPARE_STACKS) { + if (!Plan.stacksPrepared()) { + VM.collection.prepareMutator(this); + } + flushRememberedSets(); + return; + } + + if (phaseId == Simple.PREPARE) { + los.prepare(true); + VM.memory.collectorPrepareVMSpace(); + return; + } + + if (phaseId == Simple.RELEASE) { + los.release(true); + VM.memory.collectorReleaseVMSpace(); + return; + } + + Log.write("Per-mutator phase \""); Phase.getPhase(phaseId).logPhase(); + Log.writeln("\" not handled."); + VM.assertions.fail("Per-mutator phase not handled!"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,60 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.Constants; +import org.mmtk.utility.statistics.Timer; +import org.mmtk.utility.Log; + +import org.vmmagic.pragma.*; + +/** + * Phases of a garbage collection. + * + */ + at Uninterruptible +public final class SimplePhase extends Phase + implements Constants { + /**************************************************************************** + * Instance fields + */ + + /** + * Construct a phase given just a name and a global/local ordering + * scheme. + * + * @param name The name of the phase + */ + protected SimplePhase(String name) { + super(name); + } + + /** + * Construct a phase, re-using a specified timer. + * + * @param name Display name of the phase + * @param timer Timer for this phase to contribute to + */ + protected SimplePhase(String name, Timer timer) { + super(name, timer); + } + + /** + * Display a phase for debugging purposes. + */ + protected void logPhase() { + Log.write("SimplePhase("); + Log.write(name); + Log.write(")"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,69 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; +import org.vmmagic.pragma.*; + +/** + * This abstract class implements the core functionality for + * stop-the-world collectors. Stop-the-world collectors should + * inherit from this class.

+ * + * This class defines the collection phases, and provides base + * level implementations of them. Subclasses should provide + * implementations for the spaces that they introduce, and + * delegate up the class hierarchy.

+ * + * For details of the split between global and thread-local operations + * @see org.mmtk.plan.Plan + */ + at Uninterruptible +public abstract class StopTheWorld extends Simple { + + // CHECKSTYLE:OFF + + /** Build and validate a sanity table */ + protected static final short preSanityPhase = Phase.createComplex("pre-sanity", null, + Phase.scheduleGlobal (SANITY_SET_PREGC), + Phase.scheduleComplex (sanityBuildPhase), + Phase.scheduleComplex (sanityCheckPhase)); + + /** Build and validate a sanity table */ + protected static final short postSanityPhase = Phase.createComplex("post-sanity", null, + Phase.scheduleGlobal (SANITY_SET_POSTGC), + Phase.scheduleComplex (sanityBuildPhase), + Phase.scheduleComplex (sanityCheckPhase)); + + // CHECKSTYLE:ON + + /**************************************************************************** + * Collection + */ + + /** + * The boot method is called early in the boot process before any + * allocation. + */ + @Interruptible + public void postBoot() { + super.postBoot(); + + if (Options.sanityCheck.getValue()) { + Log.writeln("Collection sanity checking enabled."); + replacePhase(Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER), Phase.scheduleComplex(preSanityPhase)); + replacePhase(Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER), Phase.scheduleComplex(postSanityPhase)); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,66 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.vm.VM; +import org.vmmagic.pragma.*; + +/** + * This class (and its sub-classes) implement per-collector thread + * behavior and state. + * + * MMTk assumes that the VM instantiates instances of CollectorContext + * in thread local storage (TLS) for each thread participating in + * collection. Accesses to this state are therefore assumed to be + * low-cost during mutator time.

+ * + * @see CollectorContext + */ + at Uninterruptible +public abstract class StopTheWorldCollector extends SimpleCollector { + + /**************************************************************************** + * + * Collection. + */ + + /** Perform garbage collection */ + public void collect() { + Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection)); + } + + /** Perform some concurrent garbage collection */ + public final void concurrentCollect() { + VM.assertions.fail("concurrentCollect called on StopTheWorld collector"); + } + + /** + * Perform some concurrent collection work. + * + * @param phaseId The unique phase identifier + */ + public void concurrentCollectionPhase(short phaseId) { + VM.assertions.fail("concurrentCollectionPhase triggered on StopTheWorld collector"); + } + + /**************************************************************************** + * + * Miscellaneous. + */ + + /** @return The active global plan as a StopTheWorld instance. */ + @Inline + private static StopTheWorld global() { + return (StopTheWorld) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,22 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.vmmagic.pragma.*; + +/** + * Constraints specific to Stop-the-world collectors. + */ + at Uninterruptible +public abstract class StopTheWorldConstraints extends SimpleConstraints { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,30 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.vmmagic.pragma.*; + +/** + * This class (and its sub-classes) implement per-mutator thread + * behavior and state. + * + * MMTk assumes that the VM instantiates instances of MutatorContext + * in thread local storage (TLS) for each application thread. Accesses + * to this state are therefore assumed to be low-cost during mutator + * time.

+ * + * @see MutatorContext + */ + at Uninterruptible +public abstract class StopTheWorldMutator extends SimpleMutator { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,72 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.Constants; +import org.mmtk.utility.deque.SharedDeque; +import org.mmtk.policy.RawPageSpace; + +import org.vmmagic.pragma.*; + +/** + * This abstract class implements the core functionality for a transitive + * closure over the heap. This class holds the global state, TraceLocal + * and its super-classes handle per-thread state. + */ + at Uninterruptible +public class Trace implements Constants { + + // Global pools for load-balancing deques + final SharedDeque valuePool; + final SharedDeque rootLocationPool; + + /** + * Constructor + */ + public Trace(RawPageSpace metaDataSpace) { + valuePool = new SharedDeque("valuePool",metaDataSpace, 1); + rootLocationPool = new SharedDeque("rootLocations", metaDataSpace, 1); + } + + /** + * Prepare for a new collection pass. + */ + public void prepareNonBlocking() { + valuePool.prepareNonBlocking(); + rootLocationPool.prepareNonBlocking(); + } + + /** + * Prepare for a new collection pass. + * All active GC threads take part. + */ + public void prepare() { + valuePool.prepare(); + rootLocationPool.prepareNonBlocking(); + } + + /** + * Release resources after completing a collection pass. + */ + public void release() { + valuePool.reset(); + rootLocationPool.reset(); + } + + /** + * Is there any work outstanding in this trace. That is are there any pages in the pools. + */ + public boolean hasWork() { + return (valuePool.enqueuedPages() + rootLocationPool.enqueuedPages()) > 0; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,571 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.policy.Space; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; +import org.mmtk.utility.deque.*; +import org.mmtk.utility.options.Options; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This abstract class and its global counterpart implement the core + * functionality for a transitive closure over the heap graph. This class + * specifically implements the unsynchronized thread-local component + * (ie the 'fast path') of the trace mechanism.

+ * + * @see org.mmtk.plan.Plan + * @see org.mmtk.plan.Trace + */ + at Uninterruptible +public abstract class TraceLocal extends TransitiveClosure implements Constants { + /**************************************************************************** + * + * Instance variables + */ + /* gray object */ + protected final ObjectReferenceDeque values; + /* delayed root slots */ + protected final AddressDeque rootLocations; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param trace The global trace class to use. + */ + public TraceLocal(Trace trace) { + this(-1, trace); + } + + /** + * Constructor + * + * @param specializedScan The specialized scan id. + * @param trace The global trace class to use. + */ + public TraceLocal(int specializedScan, Trace trace) { + super(specializedScan); + values = new ObjectReferenceDeque("value", trace.valuePool); + rootLocations = new AddressDeque("roots", trace.rootLocationPool); + } + + /**************************************************************************** + * + * Internally visible Object processing and tracing + */ + + /** + * Trace a reference during GC. This involves determining which + * collection policy applies and calling the appropriate + * trace method. + * + * @param source The source of the reference. + * @param slot The location containing the object reference to be + * traced. The object reference is NOT an interior pointer. + */ + @Inline + public final void processEdge(ObjectReference source, Address slot) { + ObjectReference object = VM.activePlan.global().loadObjectReference(slot); + ObjectReference newObject = traceObject(object, false); + VM.activePlan.global().storeObjectReference(slot, newObject); + } + + /** + * Report a root edge to be processed during GC. As the given reference + * may theoretically point to an object required during root scanning, + * the caller has requested processing be delayed. + * + * NOTE: delayed roots are assumed to be raw. + * + * @param slot The location containing the object reference to be + * traced. The object reference is NOT an interior pointer. + */ + @Inline + public final void reportDelayedRootEdge(Address slot) { + rootLocations.push(slot); + } + + /** + * Trace a reference during GC. This involves determining which + * collection policy applies and calling the appropriate + * trace method. + * + * @param slot The location containing the object reference to be + * traced. The object reference is NOT an interior pointer. + * @param untraced True if objLoc is an untraced root. + */ + @Inline + public final void processRootEdge(Address slot, boolean untraced) { + ObjectReference object; + if (untraced) object = slot.loadObjectReference(); + else object = VM.activePlan.global().loadObjectReference(slot); + ObjectReference newObject = traceObject(object, true); + if (untraced) slot.store(newObject); + else VM.activePlan.global().storeObjectReference(slot, newObject); + } + + /** + * Trace a reference during GC. This involves determining which + * collection policy applies and calling the appropriate + * trace method. + * + * @param target The object the interior edge points within. + * @param slot The location of the interior edge. + * @param root True if this is a root edge. + */ + public final void processInteriorEdge(ObjectReference target, Address slot, boolean root) { + Address interiorRef = slot.loadAddress(); + Offset offset = interiorRef.diff(target.toAddress()); + ObjectReference newTarget = traceObject(target, root); + if (VM.VERIFY_ASSERTIONS) { + if (offset.sLT(Offset.zero()) || offset.sGT(Offset.fromIntSignExtend(1<<24))) { + // There is probably no object this large + Log.writeln("ERROR: Suspiciously large delta to interior pointer"); + Log.write(" object base = "); Log.writeln(target); + Log.write(" interior reference = "); Log.writeln(interiorRef); + Log.write(" delta = "); Log.writeln(offset); + VM.assertions._assert(false); + } + } + slot.store(newTarget.toAddress().plus(offset)); + } + + /** + * Collectors that move objects must override this method. + * It performs the deferred scanning of objects which are forwarded + * during bootstrap of each copying collection. Because of the + * complexities of the collection bootstrap (such objects are + * generally themselves gc-critical), the forwarding and scanning of + * the objects must be dislocated. It is an error for a non-moving + * collector to call this method. + * + * @param object The forwarded object to be scanned + */ + @Inline + protected void scanObject(ObjectReference object) { + if (specializedScan >= 0) { + VM.scanning.specializedScanObject(specializedScan, this, object); + } else { + VM.scanning.scanObject(this, object); + } + } + + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Add a gray object + * + * @param object The object to be enqueued + */ + @Inline + public final void processNode(ObjectReference object) { + values.push(object); + } + + /** + * Flush the local buffers of all deques. + */ + public final void flush() { + values.flushLocal(); + rootLocations.flushLocal(); + } + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + @Inline + public boolean isLive(ObjectReference object) { + Space space = Space.getSpaceForObject(object); + if (space == Plan.loSpace) + return Plan.loSpace.isLive(object); + else if (space == Plan.nonMovingSpace) + return Plan.nonMovingSpace.isLive(object); + else if (Plan.USE_CODE_SPACE && space == Plan.smallCodeSpace) + return Plan.smallCodeSpace.isLive(object); + else if (Plan.USE_CODE_SPACE && space == Plan.largeCodeSpace) + return Plan.largeCodeSpace.isLive(object); + else if (space == null) { + if (VM.VERIFY_ASSERTIONS) { + Log.write("space failure: "); Log.writeln(object); + } + } + return true; + } + + /** + * Is the specified object reachable? Used for GC Trace + * + * @param object The object. + * @return True if the object is live. + */ + @Inline + public boolean isReachable(ObjectReference object) { + return Space.getSpaceForObject(object).isReachable(object); + } + + /** + * Is the specified referent of a reference type object live? + * + * @param object The object. + * @return True if the reference object is live. + */ + @Inline + public boolean isReferentLive(ObjectReference object) { + return isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (Space.isInSpace(Plan.VM_SPACE, object)) + return (Plan.SCAN_BOOT_IMAGE) ? object : Plan.vmSpace.traceObject(this, object); + if (Space.isInSpace(Plan.IMMORTAL, object)) + return Plan.immortalSpace.traceObject(this, object); + if (Space.isInSpace(Plan.LOS, object)) + return Plan.loSpace.traceObject(this, object); + if (Space.isInSpace(Plan.NON_MOVING, object)) + return Plan.nonMovingSpace.traceObject(this, object); + if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.SMALL_CODE, object)) + return Plan.smallCodeSpace.traceObject(this, object); + if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.LARGE_CODE, object)) + return Plan.largeCodeSpace.traceObject(this, object); + if (VM.VERIFY_ASSERTIONS) { + Log.write("Failing object => "); Log.writeln(object); + Space.printVMMap(); + VM.assertions._assert(false, "No special case for space in traceObject"); + } + return ObjectReference.nullReference(); + } + + + /** + * Ensure that this object will not move for the rest of the GC. + * + * @param object The object that must not move + * @return The new object, guaranteed stable for the rest of the GC. + */ + @Inline + public ObjectReference precopyObject(ObjectReference object) { + return traceObject(object); + } + + /** + * This method traces an object with knowledge of the fact that object + * is a root or not. In simple collectors the fact it is a root is not + * important so this is the default implementation given here. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object, boolean root) { + return traceObject(object); + } + + /** + * Ensure that the referenced object will not move from this point through + * to the end of the collection. This can involve forwarding the object + * if necessary. + * + * Non-copying collectors do nothing, copying collectors must + * override this method in each of their trace classes. + * + * @param object The object that must not move during the collection. + * @return True If the object will not move during collection + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (!VM.activePlan.constraints().movesObjects()) + return true; + if (Space.isInSpace(Plan.LOS, object)) + return true; + if (Space.isInSpace(Plan.IMMORTAL, object)) + return true; + if (Space.isInSpace(Plan.VM_SPACE, object)) + return true; + if (Space.isInSpace(Plan.NON_MOVING, object)) + return true; + if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.SMALL_CODE, object)) + return true; + if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.LARGE_CODE, object)) + return true; + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(false, "willNotMove not defined properly in subclass"); + return false; + } + + /** + * If a Finalizable object has moved, return the new location. + * + * @param object The object which may have been forwarded. + * @return The new location of object. + */ + public ObjectReference getForwardedFinalizable(ObjectReference object) { + return getForwardedReference(object); + } + + /** + * If the reference object (from a Reference Type) has object has moved, + * return the new location. + * + * @param object The object which may have been forwarded. + * @return The new location of object. + */ + @Inline + public ObjectReference getForwardedReferent(ObjectReference object) { + return getForwardedReference(object); + } + + /** + * If the Reference Type object has moved, return the new location. + * + * @param object The object which may have been forwarded. + * @return The new location of object. + */ + @Inline + public ObjectReference getForwardedReferenceType(ObjectReference object) { + return getForwardedReference(object); + } + + /** + * If the referenced object has moved, return the new location. + * + * Some copying collectors will need to override this method. + * + * @param object The object which may have been forwarded. + * @return The new location of object. + */ + @Inline + public ObjectReference getForwardedReference(ObjectReference object) { + return traceObject(object); + } + + /** + * Make alive a referent object that is known not to be live + * (isLive is false). This is used by the ReferenceProcessor. + * + * For many collectors these semantics relfect those of + * traceObject, which is implemented here. Other + * collectors must override this method. + * + * @param object The object which is to be made alive. + * @return The possibly forwarded address of the object. + */ + @Inline + public ObjectReference retainReferent(ObjectReference object) { + return traceObject(object); + } + + /** + * An object is unreachable and is about to be added to the + * finalizable queue. The collector must ensure the object is not + * collected (despite being otherwise unreachable), and should + * return its forwarded address if keeping the object alive involves + * forwarding. This is only ever called once for an object.

+ * + * For many collectors these semantics relfect those of + * traceObject, which is implemented here. Other + * collectors must override this method. + * + * @param object The object which may have been forwarded. + * @return The forwarded value for object. In this + * case return object, copying collectors must override + * this method. + */ + public ObjectReference retainForFinalize(ObjectReference object) { + return traceObject(object); + } + + /** + * Return true if an object is ready to move to the finalizable + * queue, i.e. it has no regular references to it. This method may + * (and in some cases is) be overridden by subclasses. If this method + * returns true then it can be assumed that retainForFinalize will be + * called during the current collection. + * + * For many collectors these semantics relfect those of + * isLive, which is implemented here. Other + * collectors must override this method. + * + * @param object The object being queried. + * @return true if the object has no regular references + * to it. + */ + public boolean readyToFinalize(ObjectReference object) { + return !isLive(object); + } + + /**************************************************************************** + * + * Collection + * + * Important notes: + * . Global actions are executed by only one thread + * . Thread-local actions are executed by all threads + * . The following order is guaranteed by BasePlan, with each + * separated by a synchronization barrier. + * 1. globalPrepare() + * 2. threadLocalPrepare() + * 3. threadLocalRelease() + * 4. globalRelease() + */ + public void prepare() { + // Nothing to do + } + + public void release() { + values.reset(); + rootLocations.reset(); + } + + /** + * Process any roots for which processing was delayed. + */ + @Inline + public void processRoots() { + logMessage(5, "processing delayed root objects"); + while (!rootLocations.isEmpty()) { + processRootEdge(rootLocations.pop(), true); + } + } + + /** + * Finishing processing all GC work. This method iterates until all work queues + * are empty. + */ + @Inline + public void completeTrace() { + logMessage(4, "Processing GC in parallel"); + if (!rootLocations.isEmpty()) { + processRoots(); + } + logMessage(5, "processing gray objects"); + assertMutatorRemsetsFlushed(); + do { + while (!values.isEmpty()) { + ObjectReference v = values.pop(); + scanObject(v); + } + processRememberedSets(); + } while (!values.isEmpty()); + assertMutatorRemsetsFlushed(); + } + + /** + * Process GC work until either complete or workLimit + * units of work are completed. + * + * @param workLimit The maximum units of work to perform. + * @return True if all work was completed within workLimit. + */ + @Inline + public boolean incrementalTrace(int workLimit) { + logMessage(4, "Continuing GC in parallel (incremental)"); + logMessage(5, "processing gray objects"); + int units = 0; + do { + while (!values.isEmpty() && units < workLimit) { + ObjectReference v = values.pop(); + scanObject(v); + units++; + } + } while (!values.isEmpty() && units < workLimit); + return values.isEmpty(); + } + + /** + * Flush any remembered sets pertaining to the current collection. + * Non-generational collectors do nothing. + */ + + protected void processRememberedSets() {} + + /** + * Assert that the remsets have been flushed. This is critical to + * correctness. We need to maintain the invariant that remset entries + * do not accrue during GC. If the host JVM generates barrier entires + * it is its own responsibility to ensure that they are flushed before + * returning to MMTk. + */ + private void assertMutatorRemsetsFlushed() { + /* FIXME: PNT + if (VM.VERIFY_ASSERTIONS) { + for (int m = 0; m < VM.activePlan.mutatorCount(); m++) { + VM.activePlan.mutator(m).assertRemsetsFlushed(); + } + } + */ + } + + /** + * This method logs a message with preprended thread id, if the + * verbosity level is greater or equal to the passed level. + * + * @param minVerbose The required verbosity level + * @param message The message to display + */ + @Inline + protected final void logMessage(int minVerbose, String message) { + if (Options.verbose.getValue() >= minVerbose) { + Log.prependThreadId(); + Log.write(" "); + Log.writeln(message); + } + } + + /** + * Given a slot (ie the address of an ObjectReference), ensure that the + * referent will not move for the rest of the GC. This is achieved by + * calling the precopyObject method. + * + * @param slot The slot to check + * @param untraced Is this is an untraced reference? + */ + @Inline + public final void processPrecopyEdge(Address slot, boolean untraced) { + ObjectReference child; + if (untraced) child = slot.loadObjectReference(); + else child = VM.activePlan.global().loadObjectReference(slot); + if (!child.isNull()) { + child = precopyObject(child); + if (untraced) slot.store(child); + else VM.activePlan.global().storeObjectReference(slot, child); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,72 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.utility.deque.WriteBuffer; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is used to push values in one direction during a trace. It + * was designed for use in mutators that use write barriers to push + * work to collector threads during concurrent tracing. + * + * @see org.mmtk.plan.TraceLocal + */ + at Uninterruptible +public final class TraceWriteBuffer extends TransitiveClosure { + /**************************************************************************** + * + * Instance variables + */ + private final WriteBuffer buffer; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param trace The global trace class to use. + */ + public TraceWriteBuffer(Trace trace) { + buffer = new WriteBuffer(trace.valuePool); + } + + /** + * Flush the buffer to the trace. + */ + public void flush() { + buffer.flushLocal(); + } + + + /** + * @return True if the buffer is flushed. + */ + public boolean isFlushed() { + return buffer.isFlushed(); + } + + /** + * Enqueue an object during a trace. + * + * @param object The object to enqueue + */ + @Inline + public void processNode(ObjectReference object) { + buffer.insert(object.toAddress()); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,94 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan; + +import org.mmtk.vm.VM; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This abstract class is the fundamental mechanism for performing a + * transitive closure over an object graph.

+ * + * Some mechanisms only operate on nodes or edges, but due to limitations + * of inheritance we have combined these two here. + * + * @see org.mmtk.plan.TraceLocal + */ + at Uninterruptible +public abstract class TransitiveClosure { + + /** Database of specialized scan classes. */ + private static final Class[] specializedScans = new Class[VM.activePlan.constraints().numSpecializedScans()]; + + /** + * A transitive closure has been created that is designed to work with a specialized scan method. We must + * register it here so the specializer can return the class when queried. + * + * @param id The method id to register. + * @param specializedScanClass The class to register. + */ + @Interruptible + public static synchronized void registerSpecializedScan(int id, Class specializedScanClass) { + specializedScans[id] = specializedScanClass; + } + + /** + * Get the specialized scan with the given id. + */ + public static Class getSpecializedScanClass(int id) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(specializedScans[id] != null); + return specializedScans[id]; + } + + /** The specialized scan identifier */ + protected final int specializedScan; + + /** + * Constructor + */ + protected TransitiveClosure() { + this(-1); + } + + /** + * Constructor + * + * @param specializedScan The specialized scan for this trace. + */ + protected TransitiveClosure(int specializedScan) { + this.specializedScan = specializedScan; + if (specializedScan >= 0) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(getClass() == getSpecializedScanClass(specializedScan)); + } + } + + /** + * Trace an edge during GC. + * + * @param source The source of the reference. + * @param slot The location containing the object reference. + */ + public void processEdge(ObjectReference source, Address slot) { + VM.assertions.fail("processEdge not implemented."); + } + + /** + * Trace a node during GC. + * + * @param object The object to be processed. + */ + public void processNode(ObjectReference object) { + VM.assertions.fail("processNode not implemented."); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,204 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.copyms; + +import org.mmtk.plan.*; +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.MarkSweepSpace; +import org.mmtk.policy.Space; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.sanitychecker.SanityChecker; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the global state of a full-heap collector + * with a copying nursery and mark-sweep mature space. Unlike a full + * generational collector, there is no write barrier, no remembered set, and + * every collection is full-heap. + * + * All plans make a clear distinction between global and + * thread-local activities, and divides global and local state + * into separate class hierarchies. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. There is a single instance of Plan (or the + * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel + * threads" (aka CPUs). Thus instance + * methods of PlanLocal allow fast, unsychronized access to functions such as + * allocation and collection. + * + * The global instance defines and manages static resources + * (such as memory and virtual memory resources). This mapping of threads to + * instances is crucial to understanding the correctness and + * performance properties of MMTk plans. + */ + at Uninterruptible +public class CopyMS extends StopTheWorld { + + /**************************************************************************** + * Constants + */ + + /**************************************************************************** + * Class variables + */ + public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, VMRequest.create(0.15f, true)); + public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + public static final int NURSERY = nurserySpace.getDescriptor(); + public static final int MARK_SWEEP = msSpace.getDescriptor(); + + public static final int ALLOC_NURSERY = ALLOC_DEFAULT; + public static final int ALLOC_MS = StopTheWorld.ALLOCATORS + 1; + + public static final int SCAN_COPYMS = 0; + + /**************************************************************************** + * Instance variables + */ + + public final Trace trace; + + /** + * Constructor. + */ + public CopyMS() { + trace = new Trace(metaDataSpace); + } + + + /***************************************************************************** + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase to execute. + */ + @Inline + public final void collectionPhase(short phaseId) { + if (phaseId == PREPARE) { + super.collectionPhase(phaseId); + trace.prepare(); + msSpace.prepare(true); + nurserySpace.prepare(true); + return; + } + if (phaseId == CLOSURE) { + trace.prepare(); + return; + } + if (phaseId == RELEASE) { + trace.release(); + msSpace.release(); + nurserySpace.release(); + super.collectionPhase(phaseId); + return; + } + + super.collectionPhase(phaseId); + } + + /** + * This method controls the triggering of a GC. It is called periodically + * during allocation. Returns true to trigger a collection. + * + * @param spaceFull Space request failed, must recover pages within 'space'. + * @return True if a collection is requested by the plan. + */ + public final boolean collectionRequired(boolean spaceFull) { + boolean nurseryFull = nurserySpace.reservedPages() > Options.nurserySize.getMaxNursery(); + + return super.collectionRequired(spaceFull) || nurseryFull; + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public int getPagesUsed() { + return super.getPagesUsed() + + msSpace.reservedPages() + + nurserySpace.reservedPages(); + } + + /** + * Return the number of pages reserved for collection. + * For mark sweep this is a fixed fraction of total pages. + * + * @return The number of pages reserved given the pending + * allocation, including space reserved for collection. + */ + public int getCollectionReserve() { + return nurserySpace.reservedPages() + super.getCollectionReserve(); + } + + /** + * @return The number of pages available for allocation, assuming + * all future allocation is to the nursery. + */ + public final int getPagesAvail() { + return (getTotalPages() - getPagesReserved()) >> 1; + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return super.getPagesRequired() + msSpace.requiredPages() + + (nurserySpace.requiredPages() << 1); + } + + /** + * Return the expected reference count. For non-reference counting + * collectors this becomes a true/false relationship. + * + * @param object The object to check. + * @param sanityRootRC The number of root references to the object. + * @return The expected (root excluded) reference count. + */ + public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { + Space space = Space.getSpaceForObject(object); + + // Nursery + if (space == CopyMS.nurserySpace) { + return SanityChecker.DEAD; + } + + return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD; + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_COPYMS, CopyMSTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,159 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.copyms; + +import org.mmtk.plan.*; +import org.mmtk.policy.LargeObjectLocal; +import org.mmtk.policy.MarkSweepLocal; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-collector thread behavior + * and state for the CopyMS plan.

+ * + * Specifically, this class defines CopyMS + * collection behavior (through trace and + * the collectionPhase method), and + * collection-time allocation into the mature space. + * + * @see CopyMS + * @see CopyMSMutator + * @see StopTheWorldCollector + * @see CollectorContext + */ + at Uninterruptible +public class CopyMSCollector extends StopTheWorldCollector { + + /**************************************************************************** + * Instance fields + */ + + private MarkSweepLocal mature; + private CopyMSTraceLocal trace; + + protected final LargeObjectLocal los; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Create a new (local) instance. + */ + public CopyMSCollector() { + los = new LargeObjectLocal(Plan.loSpace); + mature = new MarkSweepLocal(CopyMS.msSpace); + trace = new CopyMSTraceLocal(global().trace); + } + + /**************************************************************************** + * + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @return The address of the first byte of the allocated region + */ + @Inline + public final Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + if (allocator == Plan.ALLOC_LOS) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES); + return los.alloc(bytes, align, offset); + } else { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES); + VM.assertions._assert(allocator == CopyMS.ALLOC_MS); + } + return mature.alloc(bytes, align, offset); + } + } + + /** + * Perform any post-copy actions. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + */ + @Inline + public final void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == Plan.ALLOC_LOS) + Plan.loSpace.initializeHeader(object, false); + else + CopyMS.msSpace.postCopy(object, true); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Use this thread for single-threaded local activities. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == CopyMS.PREPARE) { + super.collectionPhase(phaseId, primary); + mature.prepare(); + trace.prepare(); + return; + } + + if (phaseId == CopyMS.CLOSURE) { + trace.completeTrace(); + return; + } + + if (phaseId == CopyMS.RELEASE) { + mature.release(); + trace.release(); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return the active global plan as an MS instance. */ + @Inline + private static CopyMS global() { + return (CopyMS) VM.activePlan.global(); + } + + /** @return The current trace instance. */ + public final TraceLocal getCurrentTrace() { return trace; } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,41 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.copyms; + +import org.mmtk.plan.StopTheWorldConstraints; + +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.SegregatedFreeListSpace; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class CopyMSConstraints extends StopTheWorldConstraints { + + @Override + public int gcHeaderBits() { return CopySpace.LOCAL_GC_BITS_REQUIRED; } + @Override + public int gcHeaderWords() { return CopySpace.GC_HEADER_WORDS_REQUIRED; } + @Override + public int numSpecializedScans() { return 1; } + @Override + public boolean movesObjects() { return true; } + @Override + public int maxNonLOSCopyBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;} +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,163 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.copyms; + +import org.mmtk.plan.StopTheWorldMutator; +import org.mmtk.policy.CopyLocal; +import org.mmtk.policy.MarkSweepLocal; +import org.mmtk.policy.Space; + +import org.mmtk.utility.alloc.Allocator; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior + * and state for the CopyMS plan.

+ * + * Specifically, this class defines CopyMS mutator-time + * allocation into the nursery and mature space (through pre-tenuring). + * Per-mutator thread collection semantics are also defined (flushing + * and restoring per-mutator allocator state). + * + * @see CopyMS + * @see CopyMSCollector + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + */ + at Uninterruptible +public class CopyMSMutator extends StopTheWorldMutator { + + /**************************************************************************** + * Instance fields + */ + + private final MarkSweepLocal mature; + private final CopyLocal nursery; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public CopyMSMutator() { + mature = new MarkSweepLocal(CopyMS.msSpace); + nursery = new CopyLocal(CopyMS.nurserySpace); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. This class handles the default allocator + * from the mark sweep space, and delegates everything else to the + * superclass. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @return The low address of the allocated memory. + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == CopyMS.ALLOC_DEFAULT) + return nursery.alloc(bytes, align, offset); + if (allocator == CopyMS.ALLOC_MS) + return mature.alloc(bytes, align, offset); + + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. Initialize the object header for + * objects in the mark-sweep space, and delegate to the superclass for + * other objects. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @SuppressWarnings({"UnnecessaryReturnStatement"}) + @Inline + public void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == CopyMS.ALLOC_DEFAULT) + return; + else if (allocator == CopyMS.ALLOC_MS) + CopyMS.msSpace.initializeHeader(ref, true); + else + super.postAlloc(ref, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == CopyMS.nurserySpace) return nursery; + if (space == CopyMS.msSpace) return mature; + return super.getAllocatorFromSpace(space); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Use this thread for single-threaded local activities. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == CopyMS.PREPARE) { + super.collectionPhase(phaseId, primary); + mature.prepare(); + return; + } + + if (phaseId == CopyMS.RELEASE) { + nursery.reset(); + mature.release(); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /** + * Flush mutator context, in response to a requestMutatorFlush. + * Also called by the default implementation of deinitMutator. + */ + @Override + public void flush() { + super.flush(); + mature.flush(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,111 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.copyms; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local functionality for a + * transitive closure over a coping/mark-sweep hybrid collector. + */ + at Uninterruptible +public final class CopyMSTraceLocal extends TraceLocal { + + /** + * Constructor + */ + public CopyMSTraceLocal(Trace trace) { + super(CopyMS.SCAN_COPYMS, trace); + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object reachable? + * + * @param object The object. + * @return True if the object is live. + */ + @Override + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(CopyMS.NURSERY, object)) { + return CopyMS.nurserySpace.isLive(object); + } + if (Space.isInSpace(CopyMS.MARK_SWEEP, object)) { + return CopyMS.msSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * msSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + @Override + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(CopyMS.NURSERY, object)) + return CopyMS.nurserySpace.traceObject(this, object, CopyMS.ALLOC_MS); + if (Space.isInSpace(CopyMS.MARK_SWEEP, object)) + return CopyMS.msSpace.traceObject(this, object); + return super.traceObject(object); + } + + + /** + * Ensure that this object will not move for the rest of the GC. + * + * @param object The object that must not move + * @return The new object, guaranteed stable for the rest of the GC. + */ + @Inline + @Override + public ObjectReference precopyObject(ObjectReference object) { + if (object.isNull()) return object; + else if (Space.isInSpace(CopyMS.NURSERY, object)) + return CopyMS.nurserySpace.traceObject(this, object, CopyMS.ALLOC_MS); + else + return object; + } + + /** + * Will this object move from this point on, during the current collection ? + * + * @param object The object to query. + * @return True if the object will not move during this collection. + */ + @Override + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + return !Space.isInSpace(CopyMS.NURSERY, object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,468 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational; + +import org.mmtk.plan.*; +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.Space; + +import org.mmtk.utility.deque.*; +import org.mmtk.utility.heap.Map; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.sanitychecker.SanityChecker; +import org.mmtk.utility.statistics.*; + +import org.mmtk.vm.Collection; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This abstract class implements the core functionality of generic + * two-generationa copying collectors. Nursery collections occur when + * either the heap is full or the nursery is full. The nursery size + * is determined by an optional command line argument. If undefined, + * the nursery size is "infinite", so nursery collections only occur + * when the heap is full (this is known as a flexible-sized nursery + * collector). Thus both fixed and flexible nursery sizes are + * supported. Full heap collections occur when the nursery size has + * dropped to a statically defined threshold, + * NURSERY_THRESHOLD

+ * + * See also Plan.java for general comments on local vs global plan + * classes. + */ + at Uninterruptible +public abstract class Gen extends StopTheWorld { + + /***************************************************************************** + * + * Constants + */ + protected static final float SURVIVAL_ESTIMATE = 0.8f; // est yield + protected static final float MATURE_FRACTION = 0.5f; // est yield + private static final float WORST_CASE_COPY_EXPANSION = 1.5f; // worst case for addition of one word overhead due to address based hashing + public static final boolean IGNORE_REMSETS = false; + public static final boolean USE_STATIC_WRITE_BARRIER = false; + public static final boolean USE_OBJECT_BARRIER_FOR_AASTORE = false; // choose between slot and object barriers + public static final boolean USE_OBJECT_BARRIER_FOR_PUTFIELD = false; // choose between slot and object barriers + public static final boolean USE_OBJECT_BARRIER = USE_OBJECT_BARRIER_FOR_AASTORE || USE_OBJECT_BARRIER_FOR_PUTFIELD; + private static final boolean USE_DISCONTIGUOUS_NURSERY = false; + + // Allocators + public static final int ALLOC_NURSERY = ALLOC_DEFAULT; + public static final int ALLOC_MATURE = StopTheWorld.ALLOCATORS + 1; + public static final int ALLOC_MATURE_MINORGC = StopTheWorld.ALLOCATORS + 2; + public static final int ALLOC_MATURE_MAJORGC = StopTheWorld.ALLOCATORS + 3; + + public static final int SCAN_NURSERY = 0; + public static final int SCAN_MATURE = 1; + + /***************************************************************************** + * + * Class fields + */ + + /* Statistics */ + protected static final BooleanCounter fullHeap = new BooleanCounter("majorGC", true, true); + private static final Timer fullHeapTime = new Timer("majorGCTime", false, true); + protected static final EventCounter wbFast; + protected static final EventCounter wbSlow; + public static final SizeCounter nurseryMark; + public static final SizeCounter nurseryCons; + + /** The nursery space is where all new objects are allocated by default */ + private static final VMRequest vmRequest = USE_DISCONTIGUOUS_NURSERY ? VMRequest.create() : VMRequest.create(0.15f, true); + public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, vmRequest); + + public static final int NURSERY = nurserySpace.getDescriptor(); + private static final Address NURSERY_START = nurserySpace.getStart(); + protected static final int MAX_NURSERY_ALLOC_BYTES = USE_DISCONTIGUOUS_NURSERY ? org.mmtk.utility.Constants.MAX_INT : nurserySpace.getExtent().toInt(); + + /***************************************************************************** + * + * Instance fields + */ + /* status fields */ + public boolean gcFullHeap = false; + public boolean nextGCFullHeap = false; + + /* The trace object */ + public final Trace nurseryTrace = new Trace(metaDataSpace); + + /** + * Remset pools + */ + public final SharedDeque modbufPool = new SharedDeque("modBufs",metaDataSpace, 1); + public final SharedDeque remsetPool = new SharedDeque("remSets",metaDataSpace, 1); + public final SharedDeque arrayRemsetPool = new SharedDeque("arrayRemSets",metaDataSpace, 2); + + /* + * Class initializer + */ + static { + if (GATHER_WRITE_BARRIER_STATS) { + wbFast = new EventCounter("wbFast"); + wbSlow = new EventCounter("wbSlow"); + } else { + wbFast = null; + wbSlow = null; + } + if (Stats.GATHER_MARK_CONS_STATS) { + nurseryMark = new SizeCounter("nurseryMark", true, true); + nurseryCons = new SizeCounter("nurseryCons", true, true); + } else { + nurseryMark = null; + nurseryCons = null; + } + } + + /***************************************************************************** + * + * Collection + */ + + /** + * Force the next collection to be full heap. + */ + public void forceFullHeapCollection() { + nextGCFullHeap = true; + } + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase to execute. + */ + @NoInline + public void collectionPhase(short phaseId) { + if (phaseId == SET_COLLECTION_KIND) { + super.collectionPhase(phaseId); + gcFullHeap = requiresFullHeapCollection(); + return; + } + + if (phaseId == PREPARE) { + nurserySpace.prepare(true); + if (traceFullHeap()){ + if (gcFullHeap) { + if (Stats.gatheringStats()) fullHeap.set(); + fullHeapTime.start(); + } + super.collectionPhase(phaseId); + + // we can throw away the remsets (but not modbuf) for a full heap GC + remsetPool.clearDeque(1); + arrayRemsetPool.clearDeque(2); + } + return; + } + + if (phaseId == CLOSURE) { + if (!traceFullHeap()) { + nurseryTrace.prepare(); + } + return; + } + if (phaseId == RELEASE) { + nurserySpace.release(); + modbufPool.clearDeque(1); + remsetPool.clearDeque(1); + arrayRemsetPool.clearDeque(2); + if (!traceFullHeap()) { + nurseryTrace.release(); + } else { + super.collectionPhase(phaseId); + if (gcFullHeap) fullHeapTime.stop(); + } + nextGCFullHeap = (getPagesAvail() < Options.nurserySize.getMinNursery()); + return; + } + + super.collectionPhase(phaseId); + } + + /** + * This method controls the triggering of a GC. It is called periodically + * during allocation. Returns true to trigger a collection. + * + * @param spaceFull Space request failed, must recover pages within 'space'. + * @return True if a collection is requested by the plan. + */ + public final boolean collectionRequired(boolean spaceFull) { + int nurseryPages = nurserySpace.reservedPages(); + + if (nurseryPages > Options.nurserySize.getMaxNursery()) { + return true; + } + + if (virtualMemoryExhausted()) + return true; + + return super.collectionRequired(spaceFull); + } + + /** + * Determine if this GC should be a full heap collection. + * + * @return True is this GC should be a full heap collection. + */ + protected boolean requiresFullHeapCollection() { + if (collectionTrigger == Collection.EXTERNAL_GC_TRIGGER && Options.fullHeapSystemGC.getValue()) { + return true; + } + + if (nextGCFullHeap || collectionAttempt > 1) { + // Forces full heap collection + return true; + } + + if (loSpace.allocationFailed() || + nonMovingSpace.allocationFailed() || + (USE_CODE_SPACE && (largeCodeSpace.allocationFailed() || smallCodeSpace.allocationFailed()))) { + // We need space from the nursery + return true; + } + + if (virtualMemoryExhausted()) + return true; + + int smallNurseryPages = nurserySpace.committedPages(); + int smallNurseryYield = (int)((smallNurseryPages << 1) * SURVIVAL_ESTIMATE); + + if (smallNurseryYield < getPagesRequired()) { + // Our total yield is insufficent. + return true; + } + + if (nurserySpace.allocationFailed()) { + if (smallNurseryYield < (nurserySpace.requiredPages() << 1)) { + // We have run out of VM pages in the nursery + return true; + } + } + + + return false; + } + + /** + * Independent of how many pages remain in the page budget (a function of + * heap size), we must ensure we never exhaust virtual memory. Therefore + * we must never let the nursery grow to the extent that it can't be + * copied into the mature space. + * + * @return True if the nursery has grown to the extent that it may not be + * able to be copied into the mature space. + */ + private boolean virtualMemoryExhausted() { + return ((int) (nurserySpace.reservedPages()*WORST_CASE_COPY_EXPANSION) >= getMaturePhysicalPagesAvail()); + } + + /***************************************************************************** + * + * Correctness + */ + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages in use given the pending + * allocation. Simply add the nursery's contribution to that of + * the superclass. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + @Override + public int getPagesUsed() { + return (nurserySpace.reservedPages() + super.getPagesUsed()); + } + + /** + * Return the number of pages available for allocation, assuming + * all future allocation is to the nursery. + * + * @return The number of pages available for allocation, assuming + * all future allocation is to the nursery. + */ + @Override + public int getPagesAvail() { + return super.getPagesAvail() >> 1; + } + + /** + * Return the number of pages reserved for copying. + * + * @return The number of pages reserved given the pending + * allocation, including space reserved for copying. + */ + @Override + public int getCollectionReserve() { + return nurserySpace.reservedPages() + super.getCollectionReserve(); + } + + /** + * Return the number of pages available for allocation into the mature + * space. + * + * @return The number of pages available for allocation into the mature + * space. + */ + public abstract int getMaturePhysicalPagesAvail(); + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + @Override + public int getPagesRequired() { + /* We don't currently pretenure, so mature space must be zero */ + return super.getPagesRequired() + (nurserySpace.requiredPages() << 1); + } + + /***************************************************************************** + * + * Miscellaneous + */ + + /** + * Return true if the address resides within the nursery + * + * @param addr The object to be tested + * @return true if the address resides within the nursery + */ + @Inline + static boolean inNursery(Address addr) { + if (USE_DISCONTIGUOUS_NURSERY) + return Map.getDescriptorForAddress(addr) == NURSERY; + else + return addr.GE(NURSERY_START); + } + + /** + * Return true if the object resides within the nursery + * + * @param obj The object to be tested + * @return true if the object resides within the nursery + */ + @Inline + static boolean inNursery(ObjectReference obj) { + return inNursery(obj.toAddress()); + } + + /** + * @return Does the mature space do copying ? + */ + protected boolean copyMature() { + return false; + } + + /** + * Print pre-collection statistics. In this class we prefix the output + * indicating whether the collection was full heap or not. + */ + public void printPreStats() { + if ((Options.verbose.getValue() >= 1) && (gcFullHeap)) + Log.write("[Full heap]"); + super.printPreStats(); + } + + /** + * @return The mature space, set by each subclass of Gen. + */ + protected abstract Space activeMatureSpace(); + + /** + * @return True if we should trace the whole heap during collection. True if + * we're ignorning remsets or if we're doing a full heap GC. + */ + public final boolean traceFullHeap() { + return IGNORE_REMSETS || gcFullHeap; + } + + /** + * @return Is current GC only collecting objects allocated since last GC. + */ + public final boolean isCurrentGCNursery() { + return !gcFullHeap; + } + + /** + * @return Is last GC a full collection? + */ + public final boolean lastCollectionFullHeap() { + return gcFullHeap; + } + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return True if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(NURSERY, object)) + return false; + return super.willNeverMove(object); + } + + /** + * Return the expected reference count. For non-reference counting + * collectors this becomes a true/false relationship. + * + * @param object The object to check. + * @param sanityRootRC The number of root references to the object. + * @return The expected (root excluded) reference count. + */ + public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { + Space space = Space.getSpaceForObject(object); + + // Nursery + if (space == Gen.nurserySpace) { + return SanityChecker.DEAD; + } + + // Immortal spaces + if (space == Gen.immortalSpace || space == Gen.vmSpace) { + return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD; + } + + // Mature space (nursery collection) + if (VM.activePlan.global().isCurrentGCNursery()) { + return SanityChecker.UNSURE; + } + + // Mature space (full heap collection) + return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD; + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, GenNurseryTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,147 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational; + +import org.mmtk.plan.*; +import org.mmtk.policy.LargeObjectLocal; +import org.mmtk.utility.deque.*; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This abstract class implements per-collector thread + * behavior and state for generational copying collectors.

+ * + * Specifically, this class defines nursery collection behavior (through + * nurseryTrace and the collectionPhase method). + * Per-collector thread remset consumers are instantiated here (used by + * sub-classes). + * + * @see Gen + * @see GenMutator + * @see StopTheWorldCollector + * @see CollectorContext + */ + at Uninterruptible public abstract class GenCollector extends StopTheWorldCollector { + + /***************************************************************************** + * Instance fields + */ + + protected final GenNurseryTraceLocal nurseryTrace; + + protected final LargeObjectLocal los; + + // remembered set consumers + protected final ObjectReferenceDeque modbuf; + protected final AddressDeque remset; + protected final AddressPairDeque arrayRemset; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * Note that the collector is a consumer of remsets, while the + * mutator is a producer. The GenMutator class is + * responsible for construction of the WriteBuffer (producer). + * @see GenMutator + */ + public GenCollector() { + los = new LargeObjectLocal(Plan.loSpace); + arrayRemset = new AddressPairDeque(global().arrayRemsetPool); + remset = new AddressDeque("remset", global().remsetPool); + modbuf = new ObjectReferenceDeque("modbuf", global().modbufPool); + nurseryTrace = new GenNurseryTraceLocal(global().nurseryTrace, this); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Use this thread for single-threaded local activities. + */ + @NoInline + public void collectionPhase(short phaseId, boolean primary) { + + if (phaseId == Gen.PREPARE) { + los.prepare(true); + global().arrayRemsetPool.prepareNonBlocking(); + global().remsetPool.prepareNonBlocking(); + global().modbufPool.prepareNonBlocking(); + nurseryTrace.prepare(); + return; + } + + if (phaseId == StopTheWorld.ROOTS) { + VM.scanning.computeGlobalRoots(getCurrentTrace()); + if (!Gen.USE_STATIC_WRITE_BARRIER || global().traceFullHeap()) { + VM.scanning.computeStaticRoots(getCurrentTrace()); + } + if (Plan.SCAN_BOOT_IMAGE && global().traceFullHeap()) { + VM.scanning.computeBootImageRoots(getCurrentTrace()); + } + return; + } + + if (phaseId == Gen.CLOSURE) { + if (!global().gcFullHeap) { + nurseryTrace.completeTrace(); + } + return; + } + + if (phaseId == Gen.RELEASE) { + los.release(true); + if (!global().traceFullHeap()) { + nurseryTrace.release(); + global().arrayRemsetPool.reset(); + global().remsetPool.reset(); + global().modbufPool.reset(); + } + return; + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a Gen instance. */ + @Inline + private static Gen global() { + return (Gen) VM.activePlan.global(); + } + + public final TraceLocal getCurrentTrace() { + if (global().traceFullHeap()) return getFullHeapTrace(); + return nurseryTrace; + } + + /** @return The trace to use when collecting the mature space */ + public abstract TraceLocal getFullHeapTrace(); + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,72 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational; + +import org.mmtk.plan.StopTheWorldConstraints; + +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.MarkSweepSpace; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Word; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class GenConstraints extends StopTheWorldConstraints { + + /** @return True if this plan is generational. */ + @Override + public boolean generational() { return true; } + + /** @return True if this plan moves objects. */ + @Override + public boolean movesObjects() { return true; } + + /** @return The number of header bits that are required. */ + @Override + public int gcHeaderBits() { return CopySpace.LOCAL_GC_BITS_REQUIRED; } + + /** @return The number of header words that are required. */ + @Override + public int gcHeaderWords() { return CopySpace.GC_HEADER_WORDS_REQUIRED; } + + /** @return True if this plan requires a write barrier */ + @Override + public boolean needsWriteBarrier() { return true; } + + /** @return True if this plan requires a static barrier */ + @Override + public boolean needsStaticWriteBarrier() { return Gen.USE_STATIC_WRITE_BARRIER; } + + /** @return The specialized scan methods required */ + @Override + public int numSpecializedScans() { return 2; } + + /** @return True if this Plan requires a header bit for object logging */ + @Override + public boolean needsLogBitInHeader() { return Gen.USE_OBJECT_BARRIER; } + + /** @return A bit which represents that a header is unlogged */ + @Override + public Word unloggedBit() {return MarkSweepSpace.UNLOGGED_BIT; } + + /** @return The maximum size of an object that may be allocated directly into the nursery */ + @Override + public int maxNonLOSDefaultAllocBytes() { return Gen.MAX_NURSERY_ALLOC_BYTES; } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,140 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.utility.deque.*; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This abstract class implments the core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public abstract class GenMatureTraceLocal extends TraceLocal { + + /**************************************************************************** + * + * Instance fields. + */ + private final ObjectReferenceDeque modbuf; + private final AddressDeque remset; + private final AddressPairDeque arrayRemset; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public GenMatureTraceLocal(int specializedScan, Trace trace, GenCollector plan) { + super(specializedScan, trace); + this.modbuf = plan.modbuf; + this.remset = plan.remset; + this.arrayRemset = plan.arrayRemset; + } + + /** + * Constructor + */ + public GenMatureTraceLocal(Trace trace, GenCollector plan) { + super(Gen.SCAN_MATURE, trace); + this.modbuf = plan.modbuf; + this.remset = plan.remset; + this.arrayRemset = plan.arrayRemset; + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + @Inline + public boolean isLive(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull()); + if (Gen.inNursery(object)) { + return Gen.nurserySpace.isLive(object); + } + return super.isLive(object); + } + + /** + * Return true if this object is guaranteed not to move during this + * collection (i.e. this object is defintely not an unforwarded + * object). + * + * @param object + * @return True if this object is guaranteed not to move during this + * collection. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (Gen.inNursery(object)) + return false; + else + return super.willNotMoveInCurrentCollection(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull()); + if (Gen.inNursery(object)) + return Gen.nurserySpace.traceObject(this, object, Gen.ALLOC_MATURE_MAJORGC); + return super.traceObject(object); + } + + /** + * Process any remembered set entries. + */ + protected void processRememberedSets() { + logMessage(5, "clearing modbuf"); + ObjectReference obj; + while (!(obj = modbuf.pop()).isNull()) { + Plan.markAsUnlogged(obj); + } + logMessage(5, "clearing remset"); + while (!remset.isEmpty()) { + remset.pop(); + } + logMessage(5, "clearing array remset"); + while (!arrayRemset.isEmpty()) { + arrayRemset.pop1(); + arrayRemset.pop2(); + } + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,315 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational; + +import org.mmtk.plan.*; +import org.mmtk.policy.CopyLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.*; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.statistics.Stats; +import org.mmtk.vm.VM; +import static org.mmtk.plan.generational.Gen.USE_OBJECT_BARRIER_FOR_AASTORE; +import static org.mmtk.plan.generational.Gen.USE_OBJECT_BARRIER_FOR_PUTFIELD; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This abstract class implements per-mutator thread behavior + * and state for generational copying collectors.

+ * + * Specifically, this class defines mutator-time allocation into the nursery; + * write barrier semantics, and per-mutator thread collection semantics + * (flushing and restoring per-mutator allocator and remset state). + * + * @see Gen + * @see GenCollector + * @see StopTheWorldMutator + * @see MutatorContext + */ + at Uninterruptible public class GenMutator extends StopTheWorldMutator { + + /***************************************************************************** + * + * Instance fields + */ + protected final CopyLocal nursery = new CopyLocal(Gen.nurserySpace); + + private final ObjectReferenceDeque modbuf; /* remember modified scalars */ + protected final WriteBuffer remset; /* remember modified array fields */ + protected final AddressPairDeque arrayRemset; /* remember modified array ranges */ + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * Note that each mutator is a producer of remsets, while each + * collector is a consumer. The GenCollector class + * is responsible for construction of the consumer. + * @see GenCollector + */ + public GenMutator() { + modbuf = new ObjectReferenceDeque("modbuf", global().modbufPool); + remset = new WriteBuffer(global().remsetPool); + arrayRemset = new AddressPairDeque(global().arrayRemsetPool); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The low address of the allocated memory. + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == Gen.ALLOC_NURSERY) { + if (Stats.GATHER_MARK_CONS_STATS) Gen.nurseryCons.inc(bytes); + return nursery.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator != Gen.ALLOC_NURSERY) { + super.postAlloc(ref, typeRef, bytes, allocator); + } + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == Gen.nurserySpace) return nursery; + return super.getAllocatorFromSpace(space); + } + + /**************************************************************************** + * + * Barriers + */ + + /** + * Perform the write barrier fast path, which may involve remembering + * a reference if necessary. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param mode The mode of the store (eg putfield, putstatic etc) + */ + @Inline + private void fastPath(ObjectReference src, Address slot, ObjectReference tgt, int mode) { + if (Gen.GATHER_WRITE_BARRIER_STATS) Gen.wbFast.inc(); + if ((mode == AASTORE_WRITE_BARRIER && USE_OBJECT_BARRIER_FOR_AASTORE) || + (mode == PUTFIELD_WRITE_BARRIER && USE_OBJECT_BARRIER_FOR_PUTFIELD)) { + if (Plan.logRequired(src)) { + if (Gen.GATHER_WRITE_BARRIER_STATS) Gen.wbSlow.inc(); + Plan.markAsLogged(src); + modbuf.insert(src); + } + } else { + if (!Gen.inNursery(slot) && Gen.inNursery(tgt)) { + if (Gen.GATHER_WRITE_BARRIER_STATS) Gen.wbSlow.inc(); + remset.insert(slot); + } + } + } + + /** + * A new reference is about to be created. Take appropriate write + * barrier actions.

+ * + * In this case, we remember the address of the source of the + * pointer if the new reference points into the nursery from + * non-nursery space. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The mode of the store (eg putfield, putstatic etc) + */ + @Inline + public final void writeBarrier(ObjectReference src, Address slot, + ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + fastPath(src, slot, tgt, mode); + VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode); + } + + /** + * Attempt to atomically exchange the value in the given slot + * with the passed replacement value. If a new reference is + * created, we must then take appropriate write barrier actions.

+ * + * In this case, we remember the address of the source of the + * pointer if the new reference points into the nursery from + * non-nursery space. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param old The old reference to be swapped out + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occured + * @return True if the swap was successful. + */ + @Inline + public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot, + ObjectReference old, ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + boolean result = VM.barriers.tryCompareAndSwapWriteInBarrier(src, slot, old, tgt, metaDataA, metaDataB, mode); + if (result) + fastPath(src, slot, tgt, mode); + return result; + } + + /** + * A number of references are about to be copied from object + * src to object dst (as in an array + * copy). Thus, dst is the mutated object. Take + * appropriate write barrier actions.

+ * + * In this case, we remember the mutated source address range and + * will scan that address range at GC time. + * + * @param src The source of the values to copied + * @param srcOffset The offset of the first source address, in + * bytes, relative to src (in principle, this could be + * negative). + * @param dst The mutated object, i.e. the destination of the copy. + * @param dstOffset The offset of the first destination address, in + * bytes relative to tgt (in principle, this could be + * negative). + * @param bytes The size of the region being copied, in bytes. + * @return True if the update was performed by the barrier, false if + * left to the caller (always false in this case). + */ + @Inline + public final boolean writeBarrier(ObjectReference src, Offset srcOffset, + ObjectReference dst, Offset dstOffset, + int bytes) { + // We can ignore when src is in old space, right? + if (!Gen.inNursery(dst)) + arrayRemset.insert(dst.toAddress().plus(dstOffset), + dst.toAddress().plus(dstOffset.plus(bytes))); + return false; + } + + /** + * Flush per-mutator remembered sets into the global remset pool. + */ + public final void flushRememberedSets() { + modbuf.flushLocal(); + remset.flushLocal(); + arrayRemset.flushLocal(); + assertRemsetsFlushed(); + } + + /** + * Assert that the remsets have been flushed. This is critical to + * correctness. We need to maintain the invariant that remset entries + * do not accrue during GC. If the host JVM generates barrier entires + * it is its own responsibility to ensure that they are flushed before + * returning to MMTk. + */ + public final void assertRemsetsFlushed() { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(modbuf.isFlushed()); + VM.assertions._assert(remset.isFlushed()); + VM.assertions._assert(arrayRemset.isFlushed()); + } + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + */ + @NoInline + public void collectionPhase(short phaseId, boolean primary) { + + if (phaseId == Gen.PREPARE) { + nursery.reset(); + if (global().traceFullHeap()) { + super.collectionPhase(phaseId, primary); + modbuf.flushLocal(); + remset.resetLocal(); + arrayRemset.resetLocal(); + } else { + flushRememberedSets(); + } + return; + } + + if (phaseId == Gen.RELEASE) { + if (global().traceFullHeap()) { + super.collectionPhase(phaseId, primary); + } + assertRemsetsFlushed(); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a Gen instance. */ + @Inline + private static Gen global() { + return (Gen) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,131 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.utility.deque.*; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implments the core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public final class GenNurseryTraceLocal extends TraceLocal { + + /**************************************************************************** + * + * Instance fields. + */ + private final ObjectReferenceDeque modbuf; + private final AddressDeque remset; + private final AddressPairDeque arrayRemset; + + + /** + * Constructor + */ + public GenNurseryTraceLocal(Trace trace, GenCollector plan) { + super(Gen.SCAN_NURSERY, trace); + this.modbuf = plan.modbuf; + this.remset = plan.remset; + this.arrayRemset = plan.arrayRemset; + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Gen.inNursery(object)) { + return Gen.nurserySpace.isLive(object); + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(super.isLive(object)); + return true; + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (Gen.inNursery(object)) { + return Gen.nurserySpace.traceObject(this, object, Gen.ALLOC_MATURE_MINORGC); + } + return object; + } + + /** + * Process any remembered set entries. + */ + @Inline + protected void processRememberedSets() { + logMessage(5, "processing modbuf"); + ObjectReference obj; + while (!(obj = modbuf.pop()).isNull()) { + if (VM.DEBUG) VM.debugging.modbufEntry(obj); + Plan.markAsUnlogged(obj); + scanObject(obj); + } + logMessage(5, "processing remset"); + while (!remset.isEmpty()) { + Address loc = remset.pop(); + if (VM.DEBUG) VM.debugging.remsetEntry(loc); + processRootEdge(loc, false); + } + logMessage(5, "processing array remset"); + arrayRemset.flushLocal(); + while (!arrayRemset.isEmpty()) { + Address start = arrayRemset.pop1(); + Address guard = arrayRemset.pop2(); + if (VM.DEBUG) VM.debugging.arrayRemsetEntry(start,guard); + while (start.LT(guard)) { + processRootEdge(start, false); + start = start.plus(BYTES_IN_ADDRESS); + } + } + } + + /** + * Will the object move from now on during the collection. + * + * @param object The object to query. + * @return True if the object is guaranteed not to move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (object.isNull()) return false; + return !Gen.inNursery(object); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,232 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.copying; + +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.Space; +import org.mmtk.plan.generational.*; +import org.mmtk.plan.Trace; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements the functionality of a standard + * two-generation copying collector. Nursery collections occur when + * either the heap is full or the nursery is full. The nursery size + * is determined by an optional command line argument. If undefined, + * the nursery size is "infinite", so nursery collections only occur + * when the heap is full (this is known as a flexible-sized nursery + * collector). Thus both fixed and flexible nursery sizes are + * supported. Full heap collections occur when the nursery size has + * dropped to a statically defined threshold, + * NURSERY_THRESHOLD

+ * + * See the Jones & Lins GC book, chapter 7 for a detailed discussion + * of generational collection and section 7.3 for an overview of the + * flexible nursery behavior ("The Standard ML of New Jersey + * collector"), or go to Appel's paper "Simple generational garbage + * collection and fast allocation." SP&E 19(2):171--183, 1989.

+ * + * All plans make a clear distinction between global and + * thread-local activities. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. Instances of Plan map 1:1 to "kernel + * threads" (aka CPUs). Thus instance + * methods allow fast, unsychronized access to Plan utilities such as + * allocation and collection. Each instance rests on static resources + * (such as memory and virtual memory resources) which are "global" + * and therefore "static" members of Plan. This mapping of threads to + * instances is crucial to understanding the correctness and + * performance proprties of this plan. + */ + at Uninterruptible public class GenCopy extends Gen { + + /**************************************************************************** + * + * Class variables + */ + + // GC state + static boolean hi = false; // True if copying to "higher" semispace + + /** + * The low half of the copying mature space. We allocate into this space + * when hi is false. + */ + static CopySpace matureSpace0 = new CopySpace("ss0", DEFAULT_POLL_FREQUENCY, false, VMRequest.create()); + static final int MS0 = matureSpace0.getDescriptor(); + + /** + * The high half of the copying mature space. We allocate into this space + * when hi is true. + */ + static CopySpace matureSpace1 = new CopySpace("ss1", DEFAULT_POLL_FREQUENCY, true, VMRequest.create()); + static final int MS1 = matureSpace1.getDescriptor(); + + + /**************************************************************************** + * + * Instance fields + */ + final Trace matureTrace; + + /** + * Constructor + */ + public GenCopy() { + super(); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!IGNORE_REMSETS); // Not supported for GenCopy + matureTrace = new Trace(metaDataSpace); + } + + /** + * @return Does the mature space do copying ? + */ + protected boolean copyMature() { + return true; + } + + /** + * @return The semispace we are currently allocating into + */ + static CopySpace toSpace() { + return hi ? matureSpace1 : matureSpace0; + } + + /** + * @return Space descriptor for to-space. + */ + static int toSpaceDesc() { return hi ? MS1 : MS0; } + + /** + * @return The semispace we are currently copying from + * (or copied from at last major GC) + */ + static CopySpace fromSpace() { + return hi ? matureSpace0 : matureSpace1; + } + + /** + * @return Space descriptor for from-space + */ + static int fromSpaceDesc() { return hi ? MS0 : MS1; } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a phase of the currently active collection. + * + * @param phaseId Collection phase to process + */ + @Inline + public void collectionPhase(short phaseId) { + if (traceFullHeap()) { + if (phaseId == PREPARE) { + super.collectionPhase(phaseId); + hi = !hi; // flip the semi-spaces + matureSpace0.prepare(hi); + matureSpace1.prepare(!hi); + matureTrace.prepare(); + return; + } + if (phaseId == CLOSURE) { + matureTrace.prepare(); + return; + } + if (phaseId == RELEASE) { + matureTrace.release(); + fromSpace().release(); + super.collectionPhase(phaseId); + return; + } + } + super.collectionPhase(phaseId); + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + @Inline + public int getPagesUsed() { + return toSpace().reservedPages() + super.getPagesUsed(); + } + + /** + * Return the number of pages reserved for copying. + * + * @return the number of pages reserved for copying. + */ + public final int getCollectionReserve() { + // we must account for the number of pages required for copying, + // which equals the number of semi-space pages reserved + return toSpace().reservedPages() + super.getCollectionReserve(); + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return super.getPagesRequired() + (toSpace().requiredPages() << 1); + } + + /** + * Return the number of pages available for allocation into the mature + * space. + * + * @return The number of pages available for allocation into the mature + * space. + */ + public int getMaturePhysicalPagesAvail() { + return toSpace().availablePhysicalPages() >> 1; + } + + /************************************************************************** + * Miscellaneous methods + */ + + /** + * @return The mature space we are currently allocating into + */ + @Inline + public Space activeMatureSpace() { + return toSpace(); + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_MATURE, GenCopyMatureTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,171 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.copying; + +import org.mmtk.plan.generational.Gen; +import org.mmtk.plan.generational.GenCollector; +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.policy.CopyLocal; +import org.mmtk.policy.CopySpace; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements per-collector thread behavior and state for + * the GenCopy two-generational copying collector.

+ * + * Specifically, this class defines semantics specific to the collection of + * the mature generation (GenCollector defines nursery semantics). + * In particular the mature space allocator is defined (for collection-time + * allocation into the mature space), and the mature space per-collector thread + * collection time semantics are defined.

+ * + * @see GenCopy for a description of the GenCopy algorithm. + * + * @see GenCopy + * @see GenCopyMutator + * @see GenCollector + * @see org.mmtk.plan.StopTheWorldCollector + * @see org.mmtk.plan.CollectorContext + */ + at Uninterruptible +public class GenCopyCollector extends GenCollector { + + /****************************************************************** + * Instance fields + */ + + /** The allocator for the mature space */ + private final CopyLocal mature; + + /** The trace object for full-heap collections */ + private final GenCopyMatureTraceLocal matureTrace; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public GenCopyCollector() { + mature = new CopyLocal(GenCopy.toSpace()); + matureTrace = new GenCopyMatureTraceLocal(global().matureTrace, this); + } + + /**************************************************************************** + * + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @return The address of the first byte of the allocated region + */ + @Inline + public Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + if (allocator == Plan.ALLOC_LOS) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES); + return los.alloc(bytes, align, offset); + } else { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES); + VM.assertions._assert(allocator == GenCopy.ALLOC_MATURE_MINORGC || + allocator == GenCopy.ALLOC_MATURE_MAJORGC); + } + return mature.alloc(bytes, align, offset); + } + } + + /** + * Perform any post-copy actions. In this case we clear any bits used + * for this object's GC metadata. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator to allocate from + */ + @Inline + public final void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + CopySpace.clearGCBits(object); + if (allocator == Plan.ALLOC_LOS) + Plan.loSpace.initializeHeader(object, false); + else if (GenCopy.IGNORE_REMSETS) + CopySpace.markObject(getCurrentTrace(),object, GenCopy.immortalSpace.getMarkState()); + if (Gen.USE_OBJECT_BARRIER) + Plan.markAsUnlogged(object); + } + + + /***************************************************************************** + * + * Collection + */ + + /** + * Execute a per-collector collection phase. + * + * @param phaseId The phase to execute. + * @param primary True if this thread should peform local single-threaded + * actions. + */ + public void collectionPhase(short phaseId, boolean primary) { + if (global().traceFullHeap()) { + if (phaseId == GenCopy.PREPARE) { + super.collectionPhase(phaseId, primary); + if (global().gcFullHeap) mature.rebind(GenCopy.toSpace()); + } + if (phaseId == GenCopy.CLOSURE) { + matureTrace.completeTrace(); + return; + } + if (phaseId == GenCopy.RELEASE) { + matureTrace.release(); + super.collectionPhase(phaseId, primary); + return; + } + } + super.collectionPhase(phaseId, primary); + } + + /***************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a GenCopy instance. */ + private static GenCopy global() { + return (GenCopy) VM.activePlan.global(); + } + + /** Show the status of the mature allocator. */ + protected final void showMature() { + mature.show(); + } + + public final TraceLocal getFullHeapTrace() { return matureTrace; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,22 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.copying; + +import org.mmtk.plan.generational.GenConstraints; +import org.vmmagic.pragma.*; + +/** + * GenCopy constants. + */ + at Uninterruptible public class GenCopyConstraints extends GenConstraints { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,105 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.copying; + +import org.mmtk.plan.generational.Gen; +import org.mmtk.plan.generational.GenCollector; +import org.mmtk.plan.generational.GenMatureTraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implments the core functionality for a transitive + * closure over the heap graph, specifically in a Generational copying + * collector. + */ + at Uninterruptible +public final class GenCopyMatureTraceLocal extends GenMatureTraceLocal { + + /** + * Constructor + */ + public GenCopyMatureTraceLocal(Trace global, GenCollector plan) { + super(global, plan); + } + + private static GenCopy global() { + return (GenCopy) VM.activePlan.global(); + } + + /** + * Trace a reference into the mature space during GC. This involves + * determining whether the instance is in from space, and if so, + * calling the traceObject method of the Copy + * collector. + * + * @param object The object reference to be traced. This is NOT an + * interior pointer. + * @return The possibly moved reference. + */ + public ObjectReference traceObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(global().traceFullHeap()); + if (object.isNull()) return object; + + if (Space.isInSpace(GenCopy.MS0, object)) + return GenCopy.matureSpace0.traceObject(this, object, Gen.ALLOC_MATURE_MAJORGC); + if (Space.isInSpace(GenCopy.MS1, object)) + return GenCopy.matureSpace1.traceObject(this, object, Gen.ALLOC_MATURE_MAJORGC); + return super.traceObject(object); + } + + /** + * Return true if obj is a live object. + * + * @param object The object in question + * @return True if obj is a live object. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(GenCopy.MS0, object)) + return GenCopy.hi ? GenCopy.matureSpace0.isLive(object) : true; + if (Space.isInSpace(GenCopy.MS1, object)) + return GenCopy.hi ? true : GenCopy.matureSpace1.isLive(object); + return super.isLive(object); + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + + /** + * Return true if this object is guaranteed not to move during this + * collection (i.e. this object is defintely not an unforwarded + * object). + * + * @param object + * @return True if this object is guaranteed not to move during this + * collection. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (Space.isInSpace(GenCopy.toSpaceDesc(), object)) { + return true; + } + if (Space.isInSpace(GenCopy.fromSpaceDesc(), object)) { + return false; + } + return super.willNotMoveInCurrentCollection(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,165 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.copying; + +import org.mmtk.plan.generational.GenMutator; +import org.mmtk.policy.CopyLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements per-mutator thread behavior and state for + * the GenCopy two-generational copying collector.

+ * + * Specifically, this class defines mutator-time semantics specific to the + * mature generation (GenMutator defines nursery semantics). + * In particular the mature space allocator is defined (for mutator-time + * allocation into the mature space via pre-tenuring), and the mature space + * per-mutator thread collection time semantics are defined (rebinding + * the mature space allocator).

+ * + * @see GenCopy for a description of the GenCopy algorithm. + * + * @see GenCopy + * @see GenCopyCollector + * @see GenMutator + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + */ + at Uninterruptible +public class GenCopyMutator extends GenMutator { + /****************************************************************** + * Instance fields + */ + + /** + * The allocator for the copying mature space (the mutator may + * "pretenure" objects into this space otherwise used only by + * the collector) + */ + private CopyLocal mature; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public GenCopyMutator() { + mature = new CopyLocal(); + } + + /** + * Called before the MutatorContext is used, but after the context has been + * fully registered and is visible to collection. + */ + public void initMutator(int id) { + super.initMutator(id); + mature.rebind(GenCopy.toSpace()); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate space (for an object) in the specified space + * + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @param allocator The allocator to allocate from + * @param site Allocation site + * @return The address of the first byte of the allocated region + */ + @Inline + public final Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == GenCopy.ALLOC_MATURE) { + return mature.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation initialization of an object + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param allocator The allocator to allocate from + * @param bytes The size of the space allocated (in bytes) + */ + @Inline + public final void postAlloc(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + // nothing to be done + if (allocator == GenCopy.ALLOC_MATURE) return; + super.postAlloc(object, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public final Allocator getAllocatorFromSpace(Space space) { + if (space == GenCopy.matureSpace0 || space == GenCopy.matureSpace1) return mature; + return super.getAllocatorFromSpace(space); + } + + + /***************************************************************************** + * + * Collection + */ + + /** + * Execute a per-mutator collection phase. + * + * @param phaseId The phase to execute. + * @param primary True if this thread should peform local single-threaded + * actions. + */ + public void collectionPhase(short phaseId, boolean primary) { + if (global().traceFullHeap()) { + if (phaseId == GenCopy.PREPARE) { + super.collectionPhase(phaseId, primary); + if (global().gcFullHeap) mature.rebind(GenCopy.toSpace()); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + /***************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a GenCopy instance. */ + private static GenCopy global() { + return (GenCopy) VM.activePlan.global(); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,196 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.immix; + +import org.mmtk.plan.generational.Gen; +import org.mmtk.plan.Trace; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.policy.immix.ImmixSpace; +import org.mmtk.policy.immix.ObjectHeader; +import org.mmtk.policy.Space; +import org.mmtk.utility.heap.VMRequest; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the functionality of a two-generation copying + * collector where the higher generation is an immix space. + * + * Nursery collections occur when either the heap is full or the nursery + * is full. The nursery size is determined by an optional command line + * argument. If undefined, the nursery size is "infinite", so nursery + * collections only occur when the heap is full (this is known as a + * flexible-sized nursery collector). Thus both fixed and flexible + * nursery sizes are supported. Full heap collections occur when the + * nursery size has dropped to a statically defined threshold, + * NURSERY_THRESHOLD

+ * + * See the PLDI'08 paper by Blackburn and McKinley for a description + * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586 + * + * See the Jones & Lins GC book, chapter 7 for a detailed discussion + * of generational collection and section 7.3 for an overview of the + * flexible nursery behavior ("The Standard ML of New Jersey + * collector"), or go to Appel's paper "Simple generational garbage + * collection and fast allocation." SP&E 19(2):171--183, 1989.

+ * + * + * For general comments about the global/local distinction among classes refer + * to Plan.java and PlanLocal.java. + */ + at Uninterruptible +public class GenImmix extends Gen { + + /***************************************************************************** + * + * Class fields + */ + + /** The mature space, which for GenImmix uses a mark sweep collection policy. */ + public static final ImmixSpace immixSpace = new ImmixSpace("immix", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + public static final int IMMIX = immixSpace.getDescriptor(); + + public static final int SCAN_IMMIX = 1; + public static final int SCAN_DEFRAG = 2; + + /**************************************************************************** + * + * Instance fields + */ + /* The trace class for a full-heap collection */ + public final Trace matureTrace = new Trace(metaDataSpace); + private boolean lastGCWasDefrag = false; + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a (global) collection phase. + */ + @Inline + @Override + public final void collectionPhase(short phaseId) { + if (phaseId == SET_COLLECTION_KIND) { + super.collectionPhase(phaseId); + if (gcFullHeap) + immixSpace.decideWhetherToDefrag(emergencyCollection, true, collectionAttempt, collectionTrigger); + return; + } + + if (traceFullHeap()) { + if (phaseId == PREPARE) { + super.collectionPhase(phaseId); + matureTrace.prepare(); + immixSpace.prepare(true); + return; + } + + if (phaseId == CLOSURE) { + matureTrace.prepare(); + return; + } + + if (phaseId == RELEASE) { + matureTrace.release(); + lastGCWasDefrag = immixSpace.release(true); + super.collectionPhase(phaseId); + return; + } + } else + lastGCWasDefrag = false; + + super.collectionPhase(phaseId); + } + + /** + * @return Whether last GC was an exhaustive attempt to collect the heap. For many collectors this is the same as asking whether the last GC was a full heap collection. + */ + @Override + public boolean lastCollectionWasExhaustive() { + return lastGCWasDefrag; + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + @Inline + @Override + public int getPagesUsed() { + return immixSpace.reservedPages() + super.getPagesUsed(); + } + + /** + * Return the number of pages available for allocation into the mature + * space. + * + * @return The number of pages available for allocation into the mature + * space. + */ + public int getMaturePhysicalPagesAvail() { + return immixSpace.availablePhysicalPages(); + } + + /***************************************************************************** + * + * Miscellaneous + */ + + /** + * Accessor method to allow the generic generational code in Gen.java + * to access the mature space. + * + * @return The active mature space + */ + @Inline + protected final Space activeMatureSpace() { + return immixSpace; + } + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return true if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(IMMIX, object)) { + ObjectHeader.pinObject(object); + return true; + } else + return super.willNeverMove(object); + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, GenImmixMatureTraceLocal.class); + TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, GenImmixMatureDefragTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,186 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.immix; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.generational.*; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.alloc.ImmixAllocator; +import org.mmtk.utility.statistics.Stats; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-collector thread behavior and state for + * the GenImmix two-generational copying collector.

+ * + * Specifically, this class defines semantics specific to the collection of + * the copy generation (GenCollector defines nursery semantics). + * In particular the copy space allocator is defined (for collection-time + * allocation into the copy space), and the copy space per-collector thread + * collection time semantics are defined.

+ * + * @see GenImmix for a description of the GenImmix algorithm. + * + * @see GenImmix + * @see GenImmixMutator + * @see GenCollector + * @see org.mmtk.plan.StopTheWorldCollector + * @see org.mmtk.plan.CollectorContext + */ + at Uninterruptible +public class GenImmixCollector extends GenCollector { + + /***************************************************************************** + * + * Instance fields + */ + private final GenImmixMatureTraceLocal matureTrace = new GenImmixMatureTraceLocal(global().matureTrace, this); + private final GenImmixMatureDefragTraceLocal defragTrace = new GenImmixMatureDefragTraceLocal(global().matureTrace, this); + + private final org.mmtk.policy.immix.CollectorLocal immix = new org.mmtk.policy.immix.CollectorLocal(GenImmix.immixSpace); + + private final ImmixAllocator copy = new ImmixAllocator(GenImmix.immixSpace, true, false); + private final ImmixAllocator defragCopy = new ImmixAllocator(GenImmix.immixSpace, true, true); + + /**************************************************************************** + * + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @param allocator The allocator to use. + * @return The address of the first byte of the allocated region + */ + @Inline + public final Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + + if (Stats.GATHER_MARK_CONS_STATS) { + if (Space.isInSpace(GenImmix.NURSERY, original)) GenImmix.nurseryMark.inc(bytes); + } + if (allocator == Plan.ALLOC_LOS) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES); + return los.alloc(bytes, align, offset); + } else { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES); + if (GenImmix.immixSpace.inImmixCollection()) + VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MAJORGC); + else + VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MINORGC); + } + if (GenImmix.immixSpace.inImmixDefragCollection()) { + return defragCopy.alloc(bytes, align, offset); + } else + return copy.alloc(bytes, align, offset); + } + } + + /** + * Perform any post-copy actions. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + */ + @Inline + public final void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == Plan.ALLOC_LOS) + Plan.loSpace.initializeHeader(object, false); + else { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert((!GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MINORGC) || + (GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MAJORGC)); + } + GenImmix.immixSpace.postCopy(object, bytes, allocator == GenImmix.ALLOC_MATURE_MAJORGC); + } + if (Gen.USE_OBJECT_BARRIER) + Plan.markAsUnlogged(object); + } + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a (local) collection phase. + * + * @param phaseId Collection phase to perform + * @param primary Is this thread to do the one-off thread-local tasks + */ + @NoInline + public void collectionPhase(short phaseId, boolean primary) { + TraceLocal trace = GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace; + + if (global().traceFullHeap()) { + if (phaseId == GenImmix.PREPARE) { + super.collectionPhase(phaseId, primary); + trace.prepare(); + copy.reset(); + if (global().gcFullHeap) { + immix.prepare(true); + defragCopy.reset(); + } + return; + } + + if (phaseId == GenImmix.CLOSURE) { + trace.completeTrace(); + return; + } + + if (phaseId == GenImmix.RELEASE) { + trace.release(); + if (global().gcFullHeap) { + immix.release(true); + copy.reset(); + } + super.collectionPhase(phaseId, primary); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + @Inline + public final TraceLocal getFullHeapTrace() { + return GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace; + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a GenImmix instance. */ + @Inline + private static GenImmix global() { + return (GenImmix) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,34 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.immix; + +import org.mmtk.plan.generational.GenConstraints; +import static org.mmtk.policy.immix.ImmixConstants.MAX_IMMIX_OBJECT_BYTES; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + * + */ + at Uninterruptible +public class GenImmixConstraints extends GenConstraints { + /** @return The specialized scan methods required */ + @Override + public int numSpecializedScans() { return 3; } + @Override + public int maxNonLOSCopyBytes() { return MAX_IMMIX_OBJECT_BYTES;} +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,125 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.immix; + +import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME; + +import org.mmtk.plan.generational.GenCollector; +import org.mmtk.plan.generational.GenMatureTraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implments the core functionality for a transitive + * closure over the heap graph, specifically in a defragmenting pass over + * a generational immix collector. + */ + at Uninterruptible +public final class GenImmixMatureDefragTraceLocal extends GenMatureTraceLocal{ + + /** + * Constructor + */ + public GenImmixMatureDefragTraceLocal(Trace global, GenCollector plan) { + super(GenImmix.SCAN_DEFRAG, global, plan); + } + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(GenImmix.immixSpace.inImmixDefragCollection()); + if (object.isNull()) return false; + if (Space.isInSpace(GenImmix.IMMIX, object)) { + return GenImmix.immixSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(GenImmix.immixSpace.inImmixDefragCollection()); + if (object.isNull()) return object; + if (Space.isInSpace(GenImmix.IMMIX, object)) + return GenImmix.immixSpace.traceObject(this, object, GenImmix.ALLOC_MATURE_MAJORGC); + return super.traceObject(object); + } + + @Inline + @Override + public ObjectReference precopyObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(GenImmix.immixSpace.inImmixDefragCollection()); + ObjectReference rtn = traceObject(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(willNotMoveInCurrentCollection(rtn)); + return rtn; + } + + /** + * Return true if this object is guaranteed not to move during this + * collection (i.e. this object is defintely not an unforwarded + * object). + * + * @param object + * @return True if this object is guaranteed not to move during this + * collection. + */ + @Override + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (Space.isInSpace(GenImmix.IMMIX, object)) { + return GenImmix.immixSpace.willNotMoveThisGC(object); + } + return super.willNotMoveInCurrentCollection(object); + } + + /** + * Collectors that move objects must override this method. + * It performs the deferred scanning of objects which are forwarded + * during bootstrap of each copying collection. Because of the + * complexities of the collection bootstrap (such objects are + * generally themselves gc-critical), the forwarding and scanning of + * the objects must be dislocated. It is an error for a non-moving + * collector to call this method. + * + * @param object The forwarded object to be scanned + */ + @Inline + @Override + protected void scanObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.write("SO["); Log.write(object); Log.writeln("]"); + } + super.scanObject(object); + if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(GenImmix.IMMIX, object)) + GenImmix.immixSpace.markLines(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,110 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.immix; + +import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME; + +import org.mmtk.plan.generational.GenCollector; +import org.mmtk.plan.generational.GenMatureTraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements the core functionality for a transitive + * closure over the heap graph, specifically in a generational immix + * collector. + */ + at Uninterruptible +public final class GenImmixMatureTraceLocal extends GenMatureTraceLocal{ + + /** + * Constructor + */ + public GenImmixMatureTraceLocal(Trace global, GenCollector plan) { + super(GenImmix.SCAN_IMMIX, global, plan); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + + if (Space.isInSpace(GenImmix.IMMIX, object)) { + return GenImmix.immixSpace.fastTraceObject(this, object); + } + return super.traceObject(object); + } + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(GenImmix.IMMIX, object)) { + return GenImmix.immixSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * Return true if this object is guaranteed not to move during this + * collection (i.e. this object is defintely not an unforwarded + * object). + * + * @param object + * @return True if this object is guaranteed not to move during this + * collection. + */ + @Override + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (Space.isInSpace(GenImmix.IMMIX, object)) { + return true; + } + return super.willNotMoveInCurrentCollection(object); + } + + /** + * Collectors that move objects must override this method. + * It performs the deferred scanning of objects which are forwarded + * during bootstrap of each copying collection. Because of the + * complexities of the collection bootstrap (such objects are + * generally themselves gc-critical), the forwarding and scanning of + * the objects must be dislocated. It is an error for a non-moving + * collector to call this method. + * + * @param object The forwarded object to be scanned + */ + @Inline + @Override + protected void scanObject(ObjectReference object) { + super.scanObject(object); + if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(GenImmix.IMMIX, object)) + GenImmix.immixSpace.markLines(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,169 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.immix; + +import org.mmtk.plan.generational.*; +import org.mmtk.policy.Space; +import org.mmtk.policy.immix.MutatorLocal; +import org.mmtk.utility.alloc.Allocator; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior and state for + * the GenImmix two-generational copying collector.

+ * + * Specifically, this class defines mutator-time semantics specific to the + * mature generation (GenMutator defines nursery semantics). + * In particular the mature space allocator is defined (for mutator-time + * allocation into the mature space via pre-tenuring), and the mature space + * per-mutator thread collection time semantics are defined (rebinding + * the mature space allocator).

+ * + * See {@link GenImmix} for a description of the GenImmix algorithm. + * + * @see GenImmix + * @see GenImmixCollector + * @see org.mmtk.plan.generational.GenMutator + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + * @see org.mmtk.plan.Phase + */ + at Uninterruptible +public class GenImmixMutator extends GenMutator { + + /****************************************************************** + * Instance fields + */ + + /** + * The allocator for the mark-sweep mature space (the mutator may + * "pretenure" objects into this space which is otherwise used + * only by the collector) + */ + private final MutatorLocal mature; + + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public GenImmixMutator() { + mature = new MutatorLocal(GenImmix.immixSpace, false); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The low address of the allocated memory. + */ + @Inline + public final Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == GenImmix.ALLOC_MATURE) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); // no pretenuring yet + return mature.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public final void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == GenImmix.ALLOC_MATURE) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); // no pretenuring yet + } else { + super.postAlloc(ref, typeRef, bytes, allocator); + } + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == GenImmix.immixSpace) return mature; + return super.getAllocatorFromSpace(space); + } + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId Collection phase to perform + * @param primary Is this thread to do the one-off thread-local tasks + */ + @NoInline + public void collectionPhase(short phaseId, boolean primary) { + if (global().traceFullHeap()) { + if (phaseId == GenImmix.PREPARE) { + super.collectionPhase(phaseId, primary); + if (global().gcFullHeap) mature.prepare(); + return; + } + + if (phaseId == GenImmix.RELEASE) { + if (global().gcFullHeap) mature.release(); + super.collectionPhase(phaseId, primary); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a GenImmix instance. */ + @Inline + private static GenImmix global() { + return (GenImmix) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,179 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.marksweep; + +import org.mmtk.plan.generational.Gen; +import org.mmtk.plan.Trace; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.policy.MarkSweepSpace; +import org.mmtk.policy.Space; +import org.mmtk.utility.heap.VMRequest; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the functionality of a two-generation copying + * collector where the higher generation is a mark-sweep space + * (free list allocation, mark-sweep collection). Nursery collections + * occur when either the heap is full or the nursery is full. The + * nursery size is determined by an optional command line argument. + * If undefined, the nursery size is "infinite", so nursery + * collections only occur when the heap is full (this is known as a + * flexible-sized nursery collector). Thus both fixed and flexible + * nursery sizes are supported. Full heap collections occur when the + * nursery size has dropped to a statically defined threshold, + * NURSERY_THRESHOLD

+ * + * See the Jones & Lins GC book, chapter 7 for a detailed discussion + * of generational collection and section 7.3 for an overview of the + * flexible nursery behavior ("The Standard ML of New Jersey + * collector"), or go to Appel's paper "Simple generational garbage + * collection and fast allocation." SP&E 19(2):171--183, 1989.

+ * + * + * For general comments about the global/local distinction among classes refer + * to Plan.java and PlanLocal.java. + */ + at Uninterruptible +public class GenMS extends Gen { + + /***************************************************************************** + * + * Class fields + */ + + /** The mature space, which for GenMS uses a mark sweep collection policy. */ + public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + public static final int MS = msSpace.getDescriptor(); + + /**************************************************************************** + * + * Instance fields + */ + + /* The trace class for a full-heap collection */ + public final Trace matureTrace = new Trace(metaDataSpace); + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a (global) collection phase. + */ + @Inline + @Override + public final void collectionPhase(short phaseId) { + if (traceFullHeap()) { + if (phaseId == PREPARE) { + super.collectionPhase(phaseId); + matureTrace.prepare(); + msSpace.prepare(true); + return; + } + + if (phaseId == CLOSURE) { + matureTrace.prepare(); + return; + } + if (phaseId == RELEASE) { + matureTrace.release(); + msSpace.release(); + super.collectionPhase(phaseId); + return; + } + } + super.collectionPhase(phaseId); + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + @Inline + @Override + public int getPagesUsed() { + return msSpace.reservedPages() + super.getPagesUsed(); + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return super.getPagesRequired() + msSpace.requiredPages(); + } + + /** + * Return the number of pages available for allocation into the mature + * space. + * + * @return The number of pages available for allocation into the mature + * space. + */ + public int getMaturePhysicalPagesAvail() { + return (int) (msSpace.availablePhysicalPages()/MarkSweepSpace.WORST_CASE_FRAGMENTATION); + } + + /***************************************************************************** + * + * Miscellaneous + */ + + /** + * Accessor method to allow the generic generational code in Gen.java + * to access the mature space. + * + * @return The active mature space + */ + @Inline + protected final Space activeMatureSpace() { + return msSpace; + } + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return True if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(MS, object)) + return true; + return super.willNeverMove(object); + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_MATURE, GenMSMatureTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,175 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.marksweep; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.generational.*; +import org.mmtk.policy.MarkSweepLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.statistics.Stats; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-collector thread behavior and state for + * the GenMS two-generational copying collector.

+ * + * Specifically, this class defines semantics specific to the collection of + * the mature generation (GenCollector defines nursery semantics). + * In particular the mature space allocator is defined (for collection-time + * allocation into the mature space), and the mature space per-collector thread + * collection time semantics are defined.

+ * + * @see GenMS for a description of the GenMS algorithm. + * + * @see GenMS + * @see GenMSMutator + * @see GenCollector + * @see org.mmtk.plan.StopTheWorldCollector + * @see org.mmtk.plan.CollectorContext + */ + at Uninterruptible +public class GenMSCollector extends GenCollector { + + /***************************************************************************** + * + * Instance fields + */ + + /** The allocator for the mature space */ + private final MarkSweepLocal mature; + private final GenMSMatureTraceLocal matureTrace; + + /** + * Constructor + */ + public GenMSCollector() { + mature = new MarkSweepLocal(GenMS.msSpace); + matureTrace = new GenMSMatureTraceLocal(global().matureTrace, this); + } + + /**************************************************************************** + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @param allocator The allocator to use. + * @return The address of the first byte of the allocated region + */ + @Inline + @Override + public final Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + if (Stats.GATHER_MARK_CONS_STATS) { + if (Space.isInSpace(GenMS.NURSERY, original)) GenMS.nurseryMark.inc(bytes); + } + + if (allocator == Plan.ALLOC_LOS) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES); + return los.alloc(bytes, align, offset); + } else { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES); + VM.assertions._assert(allocator == GenMS.ALLOC_MATURE_MINORGC || + allocator == GenMS.ALLOC_MATURE_MAJORGC); + } + return mature.alloc(bytes, align, offset); + } + } + + /** + * Perform any post-copy actions. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + */ + @Inline + @Override + public final void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == Plan.ALLOC_LOS) + Plan.loSpace.initializeHeader(object, false); + else + GenMS.msSpace.postCopy(object, allocator == GenMS.ALLOC_MATURE_MAJORGC); + if (Gen.USE_OBJECT_BARRIER) + Plan.markAsUnlogged(object); + } + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a (local) collection phase. + * + * @param phaseId Collection phase to perform + * @param primary Is this thread to do the one-off thread-local tasks + */ + @NoInline + public void collectionPhase(short phaseId, boolean primary) { + if (global().traceFullHeap()) { + if (phaseId == GenMS.PREPARE) { + super.collectionPhase(phaseId, primary); + matureTrace.prepare(); + if (global().gcFullHeap) mature.prepare(); + return; + } + + if (phaseId == GenMS.CLOSURE) { + matureTrace.completeTrace(); + return; + } + + if (phaseId == GenMS.RELEASE) { + matureTrace.release(); + if (global().gcFullHeap) { + mature.release(); + } + super.collectionPhase(phaseId, primary); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + @Inline + public final TraceLocal getFullHeapTrace() { + return matureTrace; + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a GenMS instance. */ + @Inline + private static GenMS global() { + return (GenMS) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,30 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.marksweep; + +import org.mmtk.plan.generational.GenConstraints; +import static org.mmtk.policy.SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class GenMSConstraints extends GenConstraints { + @Override + public int maxNonLOSCopyBytes() { return MAX_FREELIST_OBJECT_BYTES;} +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,88 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.marksweep; + +import org.mmtk.plan.generational.GenCollector; +import org.mmtk.plan.generational.GenMatureTraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implments the core functionality for a transitive + * closure over the heap graph, specifically in a Generational Mark-Sweep + * collector. + */ + at Uninterruptible +public final class GenMSMatureTraceLocal extends GenMatureTraceLocal{ + + /** + * Constructor + */ + public GenMSMatureTraceLocal(Trace global, GenCollector plan) { + super(global, plan); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + + if (Space.isInSpace(GenMS.MS, object)) { + return GenMS.msSpace.traceObject(this, object); + } + return super.traceObject(object); + } + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(GenMS.MS, object)) { + return GenMS.msSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * Return true if this object is guaranteed not to move during this + * collection (i.e. this object is defintely not an unforwarded + * object). + * + * @param object + * @return True if this object is guaranteed not to move during this + * collection. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (Space.isInSpace(GenMS.MS, object)) { + return true; + } + return super.willNotMoveInCurrentCollection(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,176 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.generational.marksweep; + +import org.mmtk.plan.generational.*; +import org.mmtk.policy.MarkSweepLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior and state for + * the GenMS two-generational copying collector.

+ * + * Specifically, this class defines mutator-time semantics specific to the + * mature generation (GenMutator defines nursery semantics). + * In particular the mature space allocator is defined (for mutator-time + * allocation into the mature space via pre-tenuring), and the mature space + * per-mutator thread collection time semantics are defined (rebinding + * the mature space allocator).

+ * + * See {@link GenMS} for a description of the GenMS algorithm. + * + * @see GenMS + * @see GenMSCollector + * @see GenMutator + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + */ + at Uninterruptible +public class GenMSMutator extends GenMutator { + /****************************************************************** + * Instance fields + */ + + /** + * The allocator for the mark-sweep mature space (the mutator may + * "pretenure" objects into this space which is otherwise used + * only by the collector) + */ + private final MarkSweepLocal mature; + + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public GenMSMutator() { + mature = new MarkSweepLocal(GenMS.msSpace); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The low address of the allocated memory. + */ + @Inline + public final Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == GenMS.ALLOC_MATURE) { + return mature.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public final void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == GenMS.ALLOC_MATURE) { + GenMS.msSpace.initializeHeader(ref, true); + } else { + super.postAlloc(ref, typeRef, bytes, allocator); + } + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == GenMS.msSpace) return mature; + return super.getAllocatorFromSpace(space); + } + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId Collection phase to perform + * @param primary Is this thread to do the one-off thread-local tasks + */ + @NoInline + public void collectionPhase(short phaseId, boolean primary) { + if (global().traceFullHeap()) { + if (phaseId == GenMS.PREPARE) { + super.collectionPhase(phaseId, primary); + if (global().gcFullHeap) mature.prepare(); + return; + } + + if (phaseId == GenMS.RELEASE) { + if (global().gcFullHeap) mature.release(); + super.collectionPhase(phaseId, primary); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + /** + * Flush mutator context, in response to a requestMutatorFlush. + * Also called by the default implementation of deinitMutator. + */ + @Override + public void flush() { + super.flush(); + mature.flush(); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a GenMS instance. */ + @Inline + private static GenMS global() { + return (GenMS) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,179 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.immix; + +import org.mmtk.plan.*; +import org.mmtk.policy.Space; +import org.mmtk.policy.immix.ImmixSpace; +import org.mmtk.policy.immix.ObjectHeader; +import org.mmtk.utility.heap.VMRequest; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the global state of an immix collector. + * + * See the PLDI'08 paper by Blackburn and McKinley for a description + * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586 + * + * All plans make a clear distinction between global and + * thread-local activities, and divides global and local state + * into separate class hierarchies. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. There is a single instance of Plan (or the + * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel + * threads" (aka CPUs or in Jikes RVM, Processors). Thus instance + * methods of PlanLocal allow fast, unsychronized access to functions such as + * allocation and collection. + * + * The global instance defines and manages static resources + * (such as memory and virtual memory resources). This mapping of threads to + * instances is crucial to understanding the correctness and + * performance properties of MMTk plans. + */ + at Uninterruptible +public class Immix extends StopTheWorld { + + /**************************************************************************** + * Constants + */ + + /**************************************************************************** + * Class variables + */ + public static final ImmixSpace immixSpace = new ImmixSpace("immix", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + public static final int IMMIX = immixSpace.getDescriptor(); + + public static final int SCAN_IMMIX = 0; + public static final int SCAN_DEFRAG = 1; + + /**************************************************************************** + * Instance variables + */ + + public final Trace immixTrace = new Trace(metaDataSpace); + /** will the next collection collect the whole heap? */ + public boolean nextGCWholeHeap = true; + /** will this collection collect the whole heap */ + public boolean collectWholeHeap = nextGCWholeHeap; + protected boolean lastGCWasDefrag = false; + + /** + * Constructor. + * + */ + public Immix() { + } + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase to execute. + */ + @Inline + public void collectionPhase(short phaseId) { + if (phaseId == SET_COLLECTION_KIND) { + super.collectionPhase(phaseId); + immixSpace.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, collectionTrigger); + return; + } + + if (phaseId == PREPARE) { + super.collectionPhase(phaseId); + immixTrace.prepare(); + immixSpace.prepare(true); + return; + } + + if (phaseId == CLOSURE) { + immixTrace.prepare(); + return; + } + + if (phaseId == RELEASE) { + immixTrace.release(); + lastGCWasDefrag = immixSpace.release(true); + super.collectionPhase(phaseId); + return; + } + + super.collectionPhase(phaseId); + } + + /** + * @return Whether last GC was an exhaustive attempt to collect the heap. For many collectors this is the same as asking whether the last GC was a full heap collection. + */ + @Override + public boolean lastCollectionWasExhaustive() { + return lastGCWasDefrag; + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. The superclass accounts for its spaces, we just + * augment this with the mark-sweep space's contribution. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public int getPagesUsed() { + return immixSpace.reservedPages() + super.getPagesUsed(); + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return super.getPagesRequired() + immixSpace.requiredPages(); + } + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return True if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(IMMIX, object)) { + ObjectHeader.pinObject(object); + return true; + } else + return super.willNeverMove(object); + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, ImmixTraceLocal.class); + TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, ImmixDefragTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,175 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.immix; + +import org.mmtk.plan.*; +import org.mmtk.policy.ImmortalLocal; +import org.mmtk.policy.immix.CollectorLocal; +import org.mmtk.utility.alloc.BumpPointer; +import org.mmtk.utility.alloc.ImmixAllocator; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements per-collector thread behavior + * and state for the Immix plan, which implements a full-heap + * immix collector.

+ * + * Specifically, this class defines Immix collection behavior + * (through fastTrace and the collectionPhase + * method).

+ * + * @see Immix for an overview of the immix algorithm.

+ * + * FIXME The SegregatedFreeList class (and its decendents such as + * MarkSweepLocal) does not properly separate mutator and collector + * behaviors, so the immix field below should really not exist in + * this class as there is no collection-time allocation in this + * collector. + * + * @see Immix + * @see org.mmtk.policy.immix.MutatorLocal + * @see StopTheWorldCollector + * @see CollectorContext + * @see Phase + */ + at Uninterruptible +public class ImmixCollector extends StopTheWorldCollector { + + /**************************************************************************** + * Instance fields + */ + protected ImmixTraceLocal fastTrace; + protected ImmixDefragTraceLocal defragTrace; + protected CollectorLocal immix; + protected final ImmixAllocator copy; + protected final BumpPointer immortal; + protected TraceLocal currentTrace; + + /**************************************************************************** + * Initialization + */ + + /** + * Constructor + */ + public ImmixCollector() { + fastTrace = new ImmixTraceLocal(global().immixTrace, null); + defragTrace = new ImmixDefragTraceLocal(global().immixTrace, null); + immix = new CollectorLocal(Immix.immixSpace); + copy = new ImmixAllocator(Immix.immixSpace, true, true); + immortal = new ImmortalLocal(Plan.immortalSpace); + } + + /**************************************************************************** + * + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @return The address of the first byte of the allocated region + */ + @Inline + public Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES); + VM.assertions._assert(allocator == Immix.ALLOC_DEFAULT); + } + return copy.alloc(bytes, align, offset); + } + + /** + * Perform any post-copy actions. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + */ + @Inline + public void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allocator == Immix.ALLOC_DEFAULT); + Immix.immixSpace.postCopy(object, bytes, true); + + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(getCurrentTrace().isLive(object)); + VM.assertions._assert(getCurrentTrace().willNotMoveInCurrentCollection(object)); + } + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public void collectionPhase(short phaseId, boolean primary) { + + if (phaseId == Immix.PREPARE) { + super.collectionPhase(phaseId, primary); + currentTrace = Immix.immixSpace.inImmixDefragCollection() ? defragTrace : fastTrace; + immix.prepare(true); + currentTrace.prepare(); + copy.reset(); + return; + } + + if (phaseId == Immix.CLOSURE) { + currentTrace.completeTrace(); + return; + } + + if (phaseId == Immix.RELEASE) { + currentTrace.release(); + immix.release(true); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an Immix instance. */ + @Inline + private static Immix global() { + return (Immix) VM.activePlan.global(); + } + + /** @return The current fastTrace instance. */ + @Inline + public final TraceLocal getCurrentTrace() { + return currentTrace; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,53 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.immix; + +import org.mmtk.plan.StopTheWorldConstraints; +import org.mmtk.policy.immix.ObjectHeader; +import static org.mmtk.policy.immix.ImmixConstants.MAX_IMMIX_OBJECT_BYTES; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class ImmixConstraints extends StopTheWorldConstraints { + + /** @return The number of header bits that are required. */ + @Override + public int gcHeaderBits() { return ObjectHeader.LOCAL_GC_BITS_REQUIRED; } + + /** @return The number of header words that are required. */ + @Override + public int gcHeaderWords() { return ObjectHeader.GC_HEADER_WORDS_REQUIRED; } + + /** @return True if this plan moves objects. */ + @Override + public boolean movesObjects() { return true;} + + /** @return The specialized scan methods required */ + @Override + public int numSpecializedScans() { return 2; } + + /** @return Size (in bytes) beyond which new regular objects must be allocated to the LOS */ + @Override + public int maxNonLOSDefaultAllocBytes() { return MAX_IMMIX_OBJECT_BYTES; } + + /** @return Size (in bytes) beyond which copied objects must be copied to the LOS */ + @Override + public int maxNonLOSCopyBytes() { return MAX_IMMIX_OBJECT_BYTES; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,152 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.immix; + +import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local functionality for a defragmenting + * transitive closure over an immix space. + */ + at Uninterruptible +public final class ImmixDefragTraceLocal extends TraceLocal { + + /**************************************************************************** + * + * Instance fields + */ + private final ObjectReferenceDeque modBuffer; + + /** + * Constructor + * @param modBuffer TODO + */ + public ImmixDefragTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) { + super(Immix.SCAN_DEFRAG, trace); + this.modBuffer = modBuffer; + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection()); + if (object.isNull()) return false; + if (Space.isInSpace(Immix.IMMIX, object)) { + return Immix.immixSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * immixSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection()); + if (object.isNull()) return object; + if (Space.isInSpace(Immix.IMMIX, object)) + return Immix.immixSpace.traceObject(this, object, Plan.ALLOC_DEFAULT); + return super.traceObject(object); + } + + @Inline + @Override + public ObjectReference precopyObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection()); + ObjectReference rtn = traceObject(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(willNotMoveInCurrentCollection(rtn)); + return rtn; + } + + /** + * Return true if this object is guaranteed not to move during this + * collection (i.e. this object is defintely not an unforwarded + * object). + * + * @param object + * @return True if this object is guaranteed not to move during this + * collection. + */ + @Override + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection()); + if (Space.isInSpace(Immix.IMMIX, object)) + return Immix.immixSpace.willNotMoveThisGC(object); + return true; + } + + /** + * Collectors that move objects must override this method. + * It performs the deferred scanning of objects which are forwarded + * during bootstrap of each copying collection. Because of the + * complexities of the collection bootstrap (such objects are + * generally themselves gc-critical), the forwarding and scanning of + * the objects must be dislocated. It is an error for a non-moving + * collector to call this method. + * + * @param object The forwarded object to be scanned + */ + @Inline + @Override + protected void scanObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection()); + super.scanObject(object); + if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(Immix.IMMIX, object)) + Immix.immixSpace.markLines(object); + } + + /** + * Process any remembered set entries. This means enumerating the + * mod buffer and for each entry, marking the object as unlogged + * (we don't enqueue for scanning since we're doing a full heap GC). + */ + protected void processRememberedSets() { + if (modBuffer != null) { + logMessage(5, "clearing modBuffer"); + while (!modBuffer.isEmpty()) { + ObjectReference src = modBuffer.pop(); + Plan.markAsUnlogged(src); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,142 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.immix; + +import org.mmtk.plan.*; +import org.mmtk.policy.Space; +import org.mmtk.policy.immix.MutatorLocal; + +import org.mmtk.utility.alloc.Allocator; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior + * and state for the Immix plan, which implements a full-heap + * immix collector.

+ * + * Specifically, this class defines Immix mutator-time allocation + * and per-mutator thread collection semantics (flushing and restoring + * per-mutator allocator state).

+ * + * @see Immix + * @see org.mmtk.policy.immix.CollectorLocal + * @see StopTheWorldMutator + * @see MutatorContext + */ + at Uninterruptible +public class ImmixMutator extends StopTheWorldMutator { + + /**************************************************************************** + * Instance fields + */ + protected final MutatorLocal immix; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public ImmixMutator() { + immix = new org.mmtk.policy.immix.MutatorLocal(Immix.immixSpace, false); + } + + /**************************************************************************** + * + * MutatorLocal-time allocation + */ + + /** + * Allocate memory for an object. This class handles the default allocator + * from the mark sweep space, and delegates everything else to the + * superclass. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @return The low address of the allocated memory. + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == Immix.ALLOC_DEFAULT) + return immix.alloc(bytes, align, offset); + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. Initialize the object header for + * objects in the mark-sweep space, and delegate to the superclass for + * other objects. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == Immix.ALLOC_DEFAULT) + Immix.immixSpace.postAlloc(ref, bytes); + else + super.postAlloc(ref, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == Immix.immixSpace) return immix; // FIXME is it not a problem that we have a 2:1 mapping? + return super.getAllocatorFromSpace(space); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public void collectionPhase(short phaseId, boolean primary) { + + if (phaseId == Immix.PREPARE) { + super.collectionPhase(phaseId, primary); + immix.prepare(); + return; + } + + if (phaseId == Immix.RELEASE) { + immix.release(); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,140 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.immix; + +import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local functionality for a transitive + * closure over an immix space. + */ + at Uninterruptible +public final class ImmixTraceLocal extends TraceLocal { + + /**************************************************************************** + * + * Instance fields + */ + private final ObjectReferenceDeque modBuffer; + + /** + * Constructor + * + * @param trace The trace associated with this trace local. + * @param modBuffer The modified objects buffer associated with this trace local. Possibly null. + */ + public ImmixTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) { + super(Immix.SCAN_IMMIX, trace); + this.modBuffer = modBuffer; + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(Immix.IMMIX, object)) { + return Immix.immixSpace.fastIsLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * immixSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(Immix.IMMIX, object)) + return Immix.immixSpace.fastTraceObject(this, object); + return super.traceObject(object); + } + + /** + * Ensure that the referenced object will not move from this point through + * to the end of the collection. This can involve forwarding the object + * if necessary. + * + * @param object The object that must not move during the collection. + * @return True If the object will not move during collection + */ + @Inline + @Override + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Immix.immixSpace.inImmixDefragCollection()); + return true; + } + + /** + * Collectors that move objects must override this method. + * It performs the deferred scanning of objects which are forwarded + * during bootstrap of each copying collection. Because of the + * complexities of the collection bootstrap (such objects are + * generally themselves gc-critical), the forwarding and scanning of + * the objects must be dislocated. It is an error for a non-moving + * collector to call this method. + * + * @param object The forwarded object to be scanned + */ + @Inline + @Override + protected void scanObject(ObjectReference object) { + super.scanObject(object); + if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(Immix.IMMIX, object)) + Immix.immixSpace.markLines(object); + } + + /** + * Process any remembered set entries. This means enumerating the + * mod buffer and for each entry, marking the object as unlogged + * (we don't enqueue for scanning since we're doing a full heap GC). + */ + protected void processRememberedSets() { + if (modBuffer != null) { + logMessage(5, "clearing modBuffer"); + while (!modBuffer.isEmpty()) { + ObjectReference src = modBuffer.pop(); + Plan.markAsUnlogged(src); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,229 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.markcompact; + +import org.mmtk.plan.*; +import org.mmtk.policy.MarkCompactSpace; +import org.mmtk.policy.Space; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.sanitychecker.SanityChecker; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the global state of a simple sliding mark-compact + * collector. + * + * FIXME Need algorithmic overview and references. + * + * All plans make a clear distinction between global and + * thread-local activities, and divides global and local state + * into separate class hierarchies. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. There is a single instance of Plan (or the + * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel + * threads" (aka CPUs). Thus instance + * methods of PlanLocal allow fast, unsychronized access to functions such as + * allocation and collection. + * + * The global instance defines and manages static resources + * (such as memory and virtual memory resources). This mapping of threads to + * instances is crucial to understanding the correctness and + * performance properties of MMTk plans. + */ + at Uninterruptible public class MC extends StopTheWorld { + + /**************************************************************************** + * Class variables + */ + + public static final MarkCompactSpace mcSpace = new MarkCompactSpace("mc", DEFAULT_POLL_FREQUENCY, VMRequest.create(0.6f)); + public static final int MARK_COMPACT = mcSpace.getDescriptor(); + + public static final int SCAN_MARK = 0; + public static final int SCAN_FORWARD = 1; + + /* Phases */ + public static final short PREPARE_FORWARD = Phase.createSimple("fw-prepare"); + public static final short FORWARD_CLOSURE = Phase.createSimple("fw-closure"); + public static final short RELEASE_FORWARD = Phase.createSimple("fw-release"); + + /* FIXME these two phases need to be made per-collector phases */ + public static final short CALCULATE_FP = Phase.createSimple("calc-fp"); + public static final short COMPACT = Phase.createSimple("compact"); + + // CHECKSTYLE:OFF + + /** + * This is the phase that is executed to perform a mark-compact collection. + * + * FIXME: Far too much duplication and inside knowledge of StopTheWorld + */ + public short mcCollection = Phase.createComplex("collection", null, + Phase.scheduleComplex (initPhase), + Phase.scheduleComplex (rootClosurePhase), + Phase.scheduleComplex (refTypeClosurePhase), + Phase.scheduleComplex (completeClosurePhase), + Phase.scheduleMutator (CALCULATE_FP), + Phase.scheduleGlobal (PREPARE_FORWARD), + Phase.scheduleCollector(PREPARE_FORWARD), + Phase.scheduleMutator (PREPARE), + Phase.scheduleCollector(STACK_ROOTS), + Phase.scheduleCollector(ROOTS), + Phase.scheduleGlobal (ROOTS), + Phase.scheduleComplex (forwardPhase), + Phase.scheduleCollector(FORWARD_CLOSURE), + Phase.scheduleMutator (RELEASE), + Phase.scheduleCollector(RELEASE_FORWARD), + Phase.scheduleGlobal (RELEASE_FORWARD), + Phase.scheduleMutator (COMPACT), + Phase.scheduleComplex (finishPhase)); + + // CHECKSTYLE:ON + + /**************************************************************************** + * Instance variables + */ + + public final Trace markTrace; + public final Trace forwardTrace; + + /** + * Constructor. + */ + public MC() { + markTrace = new Trace(metaDataSpace); + forwardTrace = new Trace(metaDataSpace); + collection = mcCollection; + } + + /***************************************************************************** + * + * Collection + */ + + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase to execute. + */ + @Inline + public final void collectionPhase(short phaseId) { + if (phaseId == PREPARE) { + super.collectionPhase(phaseId); + markTrace.prepare(); + mcSpace.prepare(); + return; + } + if (phaseId == CLOSURE) { + markTrace.prepare(); + return; + } + if (phaseId == RELEASE) { + markTrace.release(); + mcSpace.release(); + super.collectionPhase(phaseId); + return; + } + + if (phaseId == PREPARE_FORWARD) { + super.collectionPhase(PREPARE); + forwardTrace.prepare(); + mcSpace.prepare(); + return; + } + if (phaseId == RELEASE_FORWARD) { + forwardTrace.release(); + mcSpace.release(); + super.collectionPhase(RELEASE); + return; + } + + super.collectionPhase(phaseId); + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. The superclass accounts for its spaces, we just + * augment this with the mark-sweep space's contribution. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public int getPagesUsed() { + return (mcSpace.reservedPages() + super.getPagesUsed()); + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return super.getPagesRequired() + mcSpace.requiredPages(); + } + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return True if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(MARK_COMPACT, object)) + return false; + return super.willNeverMove(object); + } + + /** + * Return the expected reference count. For non-reference counting + * collectors this becomes a true/false relationship. + * @param object The object to check. + * @param sanityRootRC The number of root references to the object. + * + * @return The expected (root excluded) reference count. + */ + public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { + Space space = Space.getSpaceForObject(object); + + // Nursery + if (space == MC.mcSpace) { + // We are never sure about objects in MC. + // This is not very satisfying but allows us to use the sanity checker to + // detect dangling pointers. + return SanityChecker.UNSURE; + } else { + return super.sanityExpectedRC(object, sanityRootRC); + } + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_MARK, MCMarkTraceLocal.class); + TransitiveClosure.registerSpecializedScan(SCAN_FORWARD, MCForwardTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,176 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.markcompact; + +import org.mmtk.plan.*; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-collector thread behavior + * and state for the MC plan, which implements a full-heap + * mark-compact collector.

+ * + * Specifically, this class defines MC collection behavior + * (through trace and the collectionPhase + * method), and collection-time allocation.

+ * + * @see MC for an overview of the mark-compact algorithm.

+ * + * FIXME Currently MC does not properly separate mutator and collector + * behaviors, so some of the collection logic in MCMutator should + * really be per-collector thread, not per-mutator thread. + * + * @see MC + * @see MCMutator + * @see StopTheWorldCollector + * @see CollectorContext + */ + at Uninterruptible public class MCCollector extends StopTheWorldCollector { + + private static final boolean TRACE_MARK = false; + private static final boolean TRACE_FORWARD = true; + + /**************************************************************************** + * Instance fields + */ + + private final MCMarkTraceLocal markTrace; + private final MCForwardTraceLocal forwardTrace; + private boolean currentTrace; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public MCCollector() { + markTrace = new MCMarkTraceLocal(global().markTrace); + forwardTrace = new MCForwardTraceLocal(global().forwardTrace); + } + + + /**************************************************************************** + * + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @return The address of the first byte of the allocated region + */ + @Inline + public Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allocator == MC.ALLOC_IMMORTAL); + + return immortal.alloc(bytes, align, offset); + } + + /** + * Perform any post-copy actions. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + */ + @Inline + public void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + MC.immortalSpace.initializeHeader(object); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == MC.PREPARE) { + currentTrace = TRACE_MARK; + super.collectionPhase(phaseId, primary); + markTrace.prepare(); + return; + } + + if (phaseId == MC.CLOSURE) { + markTrace.completeTrace(); + return; + } + + if (phaseId == MC.RELEASE) { + markTrace.release(); + super.collectionPhase(phaseId, primary); + return; + } + + if (phaseId == MC.PREPARE_FORWARD) { + currentTrace = TRACE_FORWARD; + super.collectionPhase(MC.PREPARE, primary); + forwardTrace.prepare(); + return; + } + + if (phaseId == MC.FORWARD_CLOSURE) { + forwardTrace.completeTrace(); + return; + } + + if (phaseId == MC.RELEASE_FORWARD) { + forwardTrace.release(); + super.collectionPhase(MC.RELEASE, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The current trace instance. */ + public final TraceLocal getCurrentTrace() { + if (currentTrace == TRACE_MARK) { + return markTrace; + } else { + return forwardTrace; + } + } + + /** @return The active global plan as an MC instance. */ + @Inline + private static MC global() { + return (MC) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,41 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.markcompact; + +import org.mmtk.plan.StopTheWorldConstraints; + +import org.mmtk.policy.MarkCompactSpace; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class MCConstraints extends StopTheWorldConstraints { + @Override + public boolean movesObjects() { return true; } + @Override + public boolean needsForwardAfterLiveness() { return true; } + @Override + public boolean needsLinearScan() { return true; } + @Override + public int gcHeaderBits() { return MarkCompactSpace.LOCAL_GC_BITS_REQUIRED; } + @Override + public int gcHeaderWords() { return MarkCompactSpace.GC_HEADER_WORDS_REQUIRED; } + @Override + public int numSpecializedScans() { return 2; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,102 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.markcompact; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implments the thread-local functionality for a transitive + * closure over a mark-compact space during the forwarding phase. + */ + at Uninterruptible +public final class MCForwardTraceLocal extends TraceLocal { + /** + * Constructor + */ + public MCForwardTraceLocal(Trace trace) { + super(MC.SCAN_FORWARD, trace); + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(MC.MARK_COMPACT, object)) { + return MC.mcSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * msSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(MC.MARK_COMPACT, object)) + return MC.mcSpace.traceForwardObject(this, object); + return super.traceObject(object); + } + + /** + * Will this object move from this point on, during the current trace ? + * + * @param object The object to query. + * @return True if the object will not move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + return !Space.isInSpace(MC.MARK_COMPACT, object); + } + + /** + * Ensure that this object will not move for the rest of the GC. + * + * @param object The object that must not move + * @return The new object, guaranteed stable for the rest of the GC. + */ + @Inline + public ObjectReference precopyObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) { + // All precopying must occur during the initial trace. + VM.assertions._assert(!Space.isInSpace(MC.MARK_COMPACT, object)); + } + return super.precopyObject(object); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,113 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.markcompact; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.MarkCompactSpace; +import org.mmtk.policy.Space; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implments the thread-local functionality for a transitive + * closure over a mark-compact space during the initial marking phase. + */ + at Uninterruptible +public final class MCMarkTraceLocal extends TraceLocal { + /** + * Constructor + */ + public MCMarkTraceLocal(Trace trace) { + super(MC.SCAN_MARK, trace); + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(MC.MARK_COMPACT, object)) { + return MC.mcSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * msSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(MC.MARK_COMPACT, object)) + return MC.mcSpace.traceMarkObject(this, object); + return super.traceObject(object); + } + + /** + * Ensure that this object will not move for the rest of the GC. + * + * @param object The object that must not move + * @return The new object, guaranteed stable for the rest of the GC. + */ + @Inline + public ObjectReference precopyObject(ObjectReference object) { + if (Space.isInSpace(MC.MARK_COMPACT, object)) { + if (MarkCompactSpace.testAndMark(object)) { + // TODO: If precopy returns many different objects, this will cause a leak. + // Currently, Jikes RVM does not require many objects to be precopied. + ObjectReference newObject = VM.objectModel.copy(object, MC.ALLOC_IMMORTAL); + MarkCompactSpace.setForwardingPointer(object, newObject); + processNode(newObject); + return newObject; + } + // Somebody else got to it first + while (MarkCompactSpace.getForwardingPointer(object).isNull()); + return MarkCompactSpace.getForwardingPointer(object); + } + return super.precopyObject(object); + } + + /** + * Will this object move from this point on, during the current trace ? + * + * @param object The object to query. + * @return True if the object will not move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + // All objects in the MC space may move + return !Space.isInSpace(MC.MARK_COMPACT, object); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,159 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.markcompact; + +import org.mmtk.plan.StopTheWorldMutator; +import org.mmtk.policy.MarkCompactLocal; +import org.mmtk.policy.Space; + +import org.mmtk.utility.alloc.Allocator; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior + * and state for the MC plan, which implements a full-heap + * mark-compact collector.

+ * + * Specifically, this class defines MC mutator-time allocation + * and per-mutator thread collection semantics (flushing and restoring + * per-mutator allocator state). + * + * See {@link MC} for an overview of the mark-compact algorithm.

+ * + * FIXME Currently MC does not properly separate mutator and collector + * behaviors, so some of the collection logic here should really be + * per-collector thread, not per-mutator thread. + * + * @see MC + * @see MCCollector + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + */ + at Uninterruptible public class MCMutator extends StopTheWorldMutator { + + /**************************************************************************** + * Instance fields + */ + private MarkCompactLocal mc; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public MCMutator() { + mc = new MarkCompactLocal(MC.mcSpace); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. This class handles the default allocator + * from the mark sweep space, and delegates everything else to the + * superclass. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The low address of the allocated memory. + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == MC.ALLOC_DEFAULT) { + return mc.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. Initialize the object header for + * objects in the mark-sweep space, and delegate to the superclass for + * other objects. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == MC.ALLOC_DEFAULT) + MC.mcSpace.initializeHeader(ref); + else + super.postAlloc(ref, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == MC.mcSpace) return mc; + return super.getAllocatorFromSpace(space); + } + + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == MC.PREPARE) { + super.collectionPhase(phaseId, primary); + return; + } + + /* FIXME this needs to be made a per-collector phase */ + if (phaseId == MC.CALCULATE_FP) { + mc.calculateForwardingPointers(); + return; + } + + /* FIXME this needs to be made a per-collector phase */ + if (phaseId == MC.COMPACT) { + mc.compact(); + return; + } + + if (phaseId == MC.RELEASE) { + super.collectionPhase(phaseId, primary); + return; + } + super.collectionPhase(phaseId, primary); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,149 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.marksweep; + +import org.mmtk.plan.*; +import org.mmtk.policy.MarkSweepSpace; +import org.mmtk.policy.Space; +import org.mmtk.utility.heap.VMRequest; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the global state of a simple mark-sweep collector. + * + * All plans make a clear distinction between global and + * thread-local activities, and divides global and local state + * into separate class hierarchies. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. There is a single instance of Plan (or the + * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel + * threads" (aka CPUs). Thus instance + * methods of PlanLocal allow fast, unsychronized access to functions such as + * allocation and collection. + * + * The global instance defines and manages static resources + * (such as memory and virtual memory resources). This mapping of threads to + * instances is crucial to understanding the correctness and + * performance properties of MMTk plans. + */ + at Uninterruptible +public class MS extends StopTheWorld { + + /**************************************************************************** + * Class variables + */ + public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + public static final int MARK_SWEEP = msSpace.getDescriptor(); + + public static final int SCAN_MARK = 0; + + + /**************************************************************************** + * Instance variables + */ + public final Trace msTrace = new Trace(metaDataSpace); + + + /***************************************************************************** + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase to execute. + */ + @Inline + @Override + public void collectionPhase(short phaseId) { + + if (phaseId == PREPARE) { + super.collectionPhase(phaseId); + msTrace.prepare(); + msSpace.prepare(true); + return; + } + + if (phaseId == CLOSURE) { + msTrace.prepare(); + return; + } + if (phaseId == RELEASE) { + msTrace.release(); + msSpace.release(); + super.collectionPhase(phaseId); + return; + } + + super.collectionPhase(phaseId); + } + + /***************************************************************************** + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. The superclass accounts for its spaces, we just + * augment this with the mark-sweep space's contribution. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + @Override + public int getPagesUsed() { + return (msSpace.reservedPages() + super.getPagesUsed()); + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + @Override + public int getPagesRequired() { + return super.getPagesRequired() + msSpace.requiredPages(); + } + + + /***************************************************************************** + * Miscellaneous + */ + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return True if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(MARK_SWEEP, object)) + return true; + return super.willNeverMove(object); + } + + /** + * Register specialized methods. + */ + @Interruptible + @Override + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_MARK, MSTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,95 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.marksweep; + +import org.mmtk.plan.*; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements per-collector thread behavior + * and state for the MS plan, which implements a full-heap + * mark-sweep collector.

+ * + * Specifically, this class defines MS collection behavior + * (through trace and the collectionPhase + * method).

+ * + * @see MS for an overview of the mark-sweep algorithm.

+ * + * @see MS + * @see MSMutator + * @see StopTheWorldCollector + * @see CollectorContext + */ + at Uninterruptible +public class MSCollector extends StopTheWorldCollector { + + /**************************************************************************** + * Instance fields + */ + protected MSTraceLocal fullTrace = new MSTraceLocal(global().msTrace, null);; + protected TraceLocal currentTrace = fullTrace; + + + /**************************************************************************** + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + @Override + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == MS.PREPARE) { + super.collectionPhase(phaseId, primary); + fullTrace.prepare(); + return; + } + + if (phaseId == MS.CLOSURE) { + fullTrace.completeTrace(); + return; + } + + if (phaseId == MS.RELEASE) { + fullTrace.release(); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + + /**************************************************************************** + * Miscellaneous + */ + + /** @return The active global plan as an MS instance. */ + @Inline + private static MS global() { + return (MS) VM.activePlan.global(); + } + + /** @return The current trace instance. */ + @Override + public final TraceLocal getCurrentTrace() { + return currentTrace; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,38 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.marksweep; + +import org.mmtk.plan.StopTheWorldConstraints; + +import org.mmtk.policy.MarkSweepSpace; +import org.mmtk.policy.SegregatedFreeListSpace; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class MSConstraints extends StopTheWorldConstraints { + @Override + public int gcHeaderBits() { return MarkSweepSpace.LOCAL_GC_BITS_REQUIRED; } + @Override + public int gcHeaderWords() { return MarkSweepSpace.GC_HEADER_WORDS_REQUIRED; } + @Override + public int maxNonLOSDefaultAllocBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES; } + @Override + public int numSpecializedScans() { return 1; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,143 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.marksweep; + +import org.mmtk.plan.*; +import org.mmtk.policy.MarkSweepLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior + * and state for the MS plan, which implements a full-heap + * mark-sweep collector.

+ * + * Specifically, this class defines MS mutator-time allocation + * and per-mutator thread collection semantics (flushing and restoring + * per-mutator allocator state).

+ * + * @see MS + * @see MSCollector + * @see StopTheWorldMutator + * @see MutatorContext + */ + at Uninterruptible +public class MSMutator extends StopTheWorldMutator { + + /**************************************************************************** + * Instance fields + */ + protected MarkSweepLocal ms = new MarkSweepLocal(MS.msSpace); + + + /**************************************************************************** + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. This class handles the default allocator + * from the mark sweep space, and delegates everything else to the + * superclass. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @return The low address of the allocated memory. + */ + @Inline + @Override + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == MS.ALLOC_DEFAULT) { + return ms.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. Initialize the object header for + * objects in the mark-sweep space, and delegate to the superclass for + * other objects. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + @Override + public void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == MS.ALLOC_DEFAULT) + MS.msSpace.postAlloc(ref); + else + super.postAlloc(ref, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + @Override + public Allocator getAllocatorFromSpace(Space space) { + if (space == MS.msSpace) return ms; + return super.getAllocatorFromSpace(space); + } + + + /**************************************************************************** + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + @Override + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == MS.PREPARE) { + super.collectionPhase(phaseId, primary); + ms.prepare(); + return; + } + + if (phaseId == MS.RELEASE) { + ms.release(); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /** + * Flush mutator context, in response to a requestMutatorFlush. + * Also called by the default implementation of deinitMutator. + */ + @Override + public void flush() { + super.flush(); + ms.flush(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,100 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.marksweep; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.ObjectReferenceDeque; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local functionality for a transitive + * closure over a mark-sweep space. + */ + at Uninterruptible +public final class MSTraceLocal extends TraceLocal { + /**************************************************************************** + * Instance fields + */ + private final ObjectReferenceDeque modBuffer; + + /** + * Constructor + */ + public MSTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) { + super(MS.SCAN_MARK, trace); + this.modBuffer = modBuffer; + } + + + /**************************************************************************** + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return true if the object is live. + */ + @Override + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(MS.MARK_SWEEP, object)) { + return MS.msSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * msSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + @Override + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(MS.MARK_SWEEP, object)) + return MS.msSpace.traceObject(this, object); + return super.traceObject(object); + } + + /** + * Process any remembered set entries. This means enumerating the + * mod buffer and for each entry, marking the object as unlogged + * (we don't enqueue for scanning since we're doing a full heap GC). + */ + protected void processRememberedSets() { + if (modBuffer != null) { + logMessage(5, "clearing modBuffer"); + while (!modBuffer.isEmpty()) { + ObjectReference src = modBuffer.pop(); + Plan.markAsUnlogged(src); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,97 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.nogc; + +import org.mmtk.plan.*; +import org.mmtk.policy.ImmortalSpace; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + + +/** + * This class implements the global state of a a simple allocator + * without a collector. + */ + at Uninterruptible +public class NoGC extends Plan { + + /***************************************************************************** + * Class variables + */ + public static final ImmortalSpace noGCSpace = new ImmortalSpace("default", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + public static final int NOGC = noGCSpace.getDescriptor(); + + + /***************************************************************************** + * Instance variables + */ + public final Trace trace = new Trace(metaDataSpace); + + + /***************************************************************************** + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase + */ + @Inline + @Override + public final void collectionPhase(short phaseId) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + /* + if (phaseId == PREPARE) { + } + if (phaseId == CLOSURE) { + } + if (phaseId == RELEASE) { + } + super.collectionPhase(phaseId); + */ + } + + /***************************************************************************** + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. The superclass accounts for its spaces, we just + * augment this with the default space's contribution. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + @Override + public int getPagesUsed() { + return (noGCSpace.reservedPages() + super.getPagesUsed()); + } + + + /***************************************************************************** + * Miscellaneous + */ + + /** + * Register specialized methods. + */ + @Interruptible + @Override + protected void registerSpecializedMethods() { + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,111 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.nogc; + +import org.mmtk.plan.*; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements per-collector thread behavior and state + * for the NoGC plan, which simply allocates (without ever collecting + * until the available space is exhausted.

+ * + * Specifically, this class would define NoGC collection time semantics, + * however, since this plan never collects, this class consists only of stubs which + * may be useful as a template for implementing a basic collector. + * + * @see NoGC + * @see NoGCMutator + * @see CollectorContext + */ + at Uninterruptible +public class NoGCCollector extends CollectorContext { + + /************************************************************************ + * Instance fields + */ + private final NoGCTraceLocal trace = new NoGCTraceLocal(global().trace); + protected final TraceLocal currentTrace = trace; + + + /**************************************************************************** + * Collection + */ + + /** + * Perform a garbage collection + */ + @Override + public final void collect() { + VM.assertions.fail("GC Triggered in NoGC Plan. Is -X:gc:ignoreSystemGC=true ?"); + } + + /** Perform some concurrent garbage collection */ + @Override + public final void concurrentCollect() { + VM.assertions.fail("Concurrent GC Triggered in NoGC Plan."); + } + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + @Inline + @Override + public final void collectionPhase(short phaseId, boolean primary) { + VM.assertions.fail("GC Triggered in NoGC Plan."); + /* + if (phaseId == NoGC.PREPARE) { + } + + if (phaseId == NoGC.CLOSURE) { + } + + if (phaseId == NoGC.RELEASE) { + } + + super.collectionPhase(phaseId, primary); + */ + } + + /** + * Perform some concurrent collection work. + * + * @param phaseId The unique phase identifier + */ + @Override + public void concurrentCollectionPhase(short phaseId) { + VM.assertions.fail("GC Triggered in NoGC Plan."); + } + + + /**************************************************************************** + * Miscellaneous + */ + + /** @return The active global plan as a NoGC instance. */ + @Inline + private static NoGC global() { + return (NoGC) VM.activePlan.global(); + } + + /** @return The current trace instance. */ + @Override + public final TraceLocal getCurrentTrace() { + return currentTrace; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,31 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.nogc; + +import org.mmtk.plan.PlanConstraints; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class NoGCConstraints extends PlanConstraints { + @Override + public int gcHeaderBits() { return 0; } + @Override + public int gcHeaderWords() { return 0; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,128 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.nogc; + +import org.mmtk.plan.MutatorContext; +import org.mmtk.policy.ImmortalLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior and state + * for the NoGC plan, which simply allocates (without ever collecting + * until the available space is exhausted.

+ * + * Specifically, this class defines NoGC mutator-time allocation + * through a bump pointer (def) and includes stubs for + * per-mutator thread collection semantics (since there is no collection + * in this plan, these remain just stubs). + * + * @see NoGC + * @see NoGCCollector + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + */ + at Uninterruptible +public class NoGCMutator extends MutatorContext { + + /************************************************************************ + * Instance fields + */ + private final ImmortalLocal nogc = new ImmortalLocal(NoGC.noGCSpace); + + + /**************************************************************************** + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The address of the newly allocated memory. + */ + @Inline + @Override + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == NoGC.ALLOC_DEFAULT) { + return nogc.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + @Override + public void postAlloc(ObjectReference ref, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator != NoGC.ALLOC_DEFAULT) { + super.postAlloc(ref, typeRef, bytes, allocator); + } + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + @Override + public Allocator getAllocatorFromSpace(Space space) { + if (space == NoGC.noGCSpace) return nogc; + return super.getAllocatorFromSpace(space); + } + + + /**************************************************************************** + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + @Inline + @Override + public final void collectionPhase(short phaseId, boolean primary) { + VM.assertions.fail("GC Triggered in NoGC Plan."); + /* + if (phaseId == NoGC.PREPARE) { + } + + if (phaseId == NoGC.RELEASE) { + } + super.collectionPhase(phaseId, primary); + */ + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,75 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.nogc; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public final class NoGCTraceLocal extends TraceLocal { + + /** + * Constructor + */ + public NoGCTraceLocal(Trace trace) { + super(trace); + } + + + /**************************************************************************** + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return true if the object is live. + */ + @Override + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(NoGC.NOGC, object)) { + return NoGC.noGCSpace.isLive(object); + } + return super.isLive(object); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + @Override + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(NoGC.NOGC, object)) + return NoGC.noGCSpace.traceObject(this, object); + return super.traceObject(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,80 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.poisoned; + +import org.mmtk.plan.marksweep.MS; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.ObjectReference; +import org.vmmagic.unboxed.Word; + +/** + * This class implements a poisoned collector, that is essentially a test + * case for read and write barriers in the VM. + */ + at Uninterruptible +public class Poisoned extends MS { + /** + * Perform any required write barrier action when installing an object reference + * a boot time. + * + * @param reference the reference value that is to be stored + * @return The raw value to be + */ + public Word bootTimeWriteBarrier(Word reference) { + return reference.or(Word.one()); + } + + /** + * Poison a reference value. + */ + @Inline + public static Word poison(ObjectReference reference) { + return reference.toAddress().toWord().or(Word.one()); + } + + /** + * DePoison a reference value. + */ + @Inline + public static ObjectReference depoison(Word value) { + return value.and(Word.one().not()).toAddress().toObjectReference(); + } + + /**************************************************************************** + * Internal read/write barriers. + */ + + /** + * Store an object reference + * + * @param slot The location of the reference + * @param value The value to store + */ + @Inline + public void storeObjectReference(Address slot, ObjectReference value) { + slot.store(poison(value)); + } + + /** + * Load an object reference + * + * @param slot The location of the reference + * @return the object reference loaded from slot + */ + @Inline + public ObjectReference loadObjectReference(Address slot) { + return depoison(slot.loadWord()); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,25 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.poisoned; + +import org.mmtk.plan.marksweep.MSCollector; + +import org.vmmagic.pragma.Uninterruptible; + +/** + * This class implements a poisoned collector, that is essentially a test + * case for read and write barriers in the VM. + */ + at Uninterruptible +public class PoisonedCollector extends MSCollector { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,34 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.poisoned; + +import org.mmtk.plan.marksweep.MSConstraints; +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class PoisonedConstraints extends MSConstraints { + @Override + public boolean needsWriteBarrier() { return true; } + @Override + public boolean needsReadBarrier() { return true; } + @Override + public boolean needsStaticWriteBarrier() { return false; } + @Override + public boolean needsStaticReadBarrier() { return false; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,123 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.poisoned; + +import org.mmtk.plan.marksweep.MSMutator; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.ObjectReference; +import org.vmmagic.unboxed.Offset; +import org.vmmagic.unboxed.Word; + +/** + * This class implements a poisoned collector, that is essentially a test + * case for read and write barriers in the VM. + */ + at Uninterruptible +public class PoisonedMutator extends MSMutator { + + /**************************************************************************** + * + * Write and read barriers. By default do nothing, override if + * appropriate. + */ + + /** + * A new reference is about to be created. Take appropriate write + * barrier actions.

+ * + * By default do nothing, override if appropriate. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occurred + */ + @Inline + @Override + public void writeBarrier(ObjectReference src, Address slot, ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) { + VM.barriers.performRawWriteInBarrier(src, slot, Poisoned.poison(tgt), metaDataA, metaDataB, mode); + } + + /** + * Attempt to atomically exchange the value in the given slot + * with the passed replacement value. If a new reference is + * created, we must then take appropriate write barrier actions.

+ * + * By default do nothing, override if appropriate. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param old The old reference to be swapped out + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occurred + * @return True if the swap was successful. + */ + @Override + public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot, ObjectReference old, ObjectReference tgt, + Word metaDataA, Word metaDataB, int mode) { + return VM.barriers.tryRawCompareAndSwapWriteInBarrier(src, slot, Poisoned.poison(old), Poisoned.poison(tgt), metaDataA, metaDataB, mode); + } + + /** + * A number of references are about to be copied from object + * src to object dst (as in an array + * copy). Thus, dst is the mutated object. Take + * appropriate write barrier actions.

+ * + * @param src The source of the values to be copied + * @param srcOffset The offset of the first source address, in + * bytes, relative to src (in principle, this could be + * negative). + * @param dst The mutated object, i.e. the destination of the copy. + * @param dstOffset The offset of the first destination address, in + * bytes relative to tgt (in principle, this could be + * negative). + * @param bytes The size of the region being copied, in bytes. + * @return True if the update was performed by the barrier, false if + * left to the caller (always false in this case). + */ + @Override + public boolean writeBarrier(ObjectReference src, Offset srcOffset, ObjectReference dst, Offset dstOffset, int bytes) { + // TODO: Currently, read barriers implies that this is never used, perhaps + // we might want to use it sometime anyway? + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + return false; + } + + /** + * Read a reference. Take appropriate read barrier action, and + * return the value that was read.

This is a substituting + * barrier. The call to this barrier takes the place of a load.

+ * + * @param src The object reference holding the field being read. + * @param slot The address of the slot being read. + * @param metaDataA A value that assists the host VM in creating a load + * @param metaDataB A value that assists the host VM in creating a load + * @param mode The context in which the load occurred + * @return The reference that was read. + */ + @Inline + @Override + public ObjectReference readBarrier(ObjectReference src, Address slot, Word metaDataA, Word metaDataB, int mode) { + return Poisoned.depoison(VM.barriers.performRawReadInBarrier(src, slot, metaDataA, metaDataB, mode)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,299 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount; + +import org.mmtk.plan.Phase; +import org.mmtk.plan.StopTheWorld; +import org.mmtk.plan.Trace; +import org.mmtk.plan.refcount.backuptrace.BTFreeLargeObjectSweeper; +import org.mmtk.plan.refcount.backuptrace.BTScanLargeObjectSweeper; +import org.mmtk.plan.refcount.backuptrace.BTSweeper; +import org.mmtk.policy.ExplicitFreeListSpace; +import org.mmtk.policy.ExplicitLargeObjectSpace; +import org.mmtk.policy.Space; +import org.mmtk.utility.Log; +import org.mmtk.utility.alloc.LinearScan; +import org.mmtk.utility.deque.SharedDeque; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.sanitychecker.SanityChecker; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the global state of a a simple reference counting collector. + */ + at Uninterruptible +public class RCBase extends StopTheWorld { + public static final short PROCESS_OLDROOTBUFFER = Phase.createSimple("old-root"); + public static final short PROCESS_NEWROOTBUFFER = Phase.createSimple("new-root"); + public static final short PROCESS_MODBUFFER = Phase.createSimple("mods"); + public static final short PROCESS_DECBUFFER = Phase.createSimple("decs"); + + /** Is cycle collection enabled? */ + public static final boolean CC_ENABLED = true; + /** Force full cycle collection at each GC? */ + public static final boolean CC_FORCE_FULL = false; + /** Use backup tracing for cycle collection (currently the only option) */ + public static final boolean CC_BACKUP_TRACE = true; + + public static boolean performCycleCollection; + public static final short BT_CLOSURE = Phase.createSimple("closure-bt"); + + // CHECKSTYLE:OFF + + /** + * Reference counting specific collection steps. + */ + protected static final short refCountCollectionPhase = Phase.createComplex("release", null, + Phase.scheduleGlobal (PROCESS_OLDROOTBUFFER), + Phase.scheduleCollector (PROCESS_OLDROOTBUFFER), + Phase.scheduleGlobal (PROCESS_NEWROOTBUFFER), + Phase.scheduleCollector (PROCESS_NEWROOTBUFFER), + Phase.scheduleMutator (PROCESS_DECBUFFER), + Phase.scheduleGlobal (PROCESS_DECBUFFER), + Phase.scheduleCollector (PROCESS_DECBUFFER), + Phase.scheduleGlobal (BT_CLOSURE), + Phase.scheduleCollector (BT_CLOSURE)); + + /** + * Perform the initial determination of liveness from the roots. + */ + protected static final short rootClosurePhase = Phase.createComplex("initial-closure", null, + Phase.scheduleMutator (PREPARE), + Phase.scheduleGlobal (PREPARE), + Phase.scheduleCollector (PREPARE), + Phase.scheduleComplex (prepareStacks), + Phase.scheduleCollector (PRECOPY), + Phase.scheduleCollector (STACK_ROOTS), + Phase.scheduleCollector (ROOTS), + Phase.scheduleGlobal (ROOTS), + Phase.scheduleMutator (PROCESS_MODBUFFER), + Phase.scheduleGlobal (PROCESS_MODBUFFER), + Phase.scheduleCollector (PROCESS_MODBUFFER), + Phase.scheduleGlobal (CLOSURE), + Phase.scheduleCollector (CLOSURE)); + + /** + * This is the phase that is executed to perform a collection. + */ + public short collection = Phase.createComplex("collection", null, + Phase.scheduleComplex(initPhase), + Phase.scheduleComplex(rootClosurePhase), + Phase.scheduleComplex(refCountCollectionPhase), + Phase.scheduleComplex(completeClosurePhase), + Phase.scheduleComplex(finishPhase)); + + // CHECKSTYLE:ON + + /***************************************************************************** + * + * Class fields + */ + public static final ExplicitFreeListSpace rcSpace = new ExplicitFreeListSpace("rc", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + public static final ExplicitLargeObjectSpace rcloSpace = new ExplicitLargeObjectSpace("rclos", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + + public static final int REF_COUNT = rcSpace.getDescriptor(); + public static final int REF_COUNT_LOS = rcloSpace.getDescriptor(); + + public final SharedDeque modPool = new SharedDeque("mod", metaDataSpace, 1); + public final SharedDeque decPool = new SharedDeque("dec", metaDataSpace, 1); + public final SharedDeque newRootPool = new SharedDeque("newRoot", metaDataSpace, 1); + public final SharedDeque oldRootPool = new SharedDeque("oldRoot", metaDataSpace, 1); + + /***************************************************************************** + * + * Instance fields + */ + public final Trace rootTrace; + public final Trace backupTrace; + private final BTSweeper rcSweeper; + private final BTScanLargeObjectSweeper loScanSweeper; + private final BTFreeLargeObjectSweeper loFreeSweeper; + + /** + * Constructor + */ + public RCBase() { + Options.noReferenceTypes.setDefaultValue(true); + Options.noFinalizer.setDefaultValue(true); + + rootTrace = new Trace(metaDataSpace); + backupTrace = new Trace(metaDataSpace); + rcSweeper = new BTSweeper(); + loScanSweeper = new BTScanLargeObjectSweeper(); + loFreeSweeper = new BTFreeLargeObjectSweeper(); + } + + /** + * The boot method is called early in the boot process before any + * allocation. + */ + @Interruptible + public void postBoot() { + super.postBoot(); + + if (!Options.noReferenceTypes.getValue()) { + VM.assertions.fail("Reference Types are not supported by RC"); + } + if (!Options.noFinalizer.getValue()) { + VM.assertions.fail("Finalizers are not supported by RC"); + } + } + + /***************************************************************************** + * + * Collection + */ + + public static final boolean isRCObject(ObjectReference object) { + return !object.isNull() && !Space.isInSpace(VM_SPACE, object); + } + + /** + * @return Whether last GC is a full GC. + */ + public boolean lastCollectionFullHeap() { + return performCycleCollection; + } + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase + */ + public void collectionPhase(short phaseId) { + if (phaseId == SET_COLLECTION_KIND) { + super.collectionPhase(phaseId); + if (CC_ENABLED) { + performCycleCollection = (collectionAttempt > 1) || emergencyCollection || CC_FORCE_FULL; + if (performCycleCollection && Options.verbose.getValue() > 0) Log.write(" [CC] "); + } + return; + } + + if (phaseId == PREPARE) { + VM.finalizableProcessor.clear(); + VM.weakReferences.clear(); + VM.softReferences.clear(); + VM.phantomReferences.clear(); + rootTrace.prepare(); + rcSpace.prepare(); + if (CC_BACKUP_TRACE && performCycleCollection) { + backupTrace.prepare(); + } + return; + } + + if (phaseId == CLOSURE) { + rootTrace.prepare(); + return; + } + + if (phaseId == BT_CLOSURE) { + if (CC_BACKUP_TRACE && performCycleCollection) { + backupTrace.prepare(); + } + return; + } + + if (phaseId == PROCESS_OLDROOTBUFFER) { + oldRootPool.prepare(); + return; + } + + if (phaseId == PROCESS_NEWROOTBUFFER) { + newRootPool.prepare(); + return; + } + + + if (phaseId == PROCESS_MODBUFFER) { + modPool.prepare(); + return; + } + + if (phaseId == PROCESS_DECBUFFER) { + decPool.prepare(); + return; + } + + if (phaseId == RELEASE) { + rootTrace.release(); + if (CC_BACKUP_TRACE && performCycleCollection) { + backupTrace.release(); + rcSpace.sweepCells(rcSweeper); + rcloSpace.sweep(loScanSweeper); + rcloSpace.sweep(loFreeSweeper); + } else { + rcSpace.release(); + } + return; + } + + super.collectionPhase(phaseId); + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages used given the pending + * allocation. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public int getPagesUsed() { + return (rcSpace.reservedPages() + rcloSpace.reservedPages() + super.getPagesUsed()); + } + + /** + * Perform a linear scan across all objects in the heap to check for leaks. + */ + public void sanityLinearScan(LinearScan scan) { + //rcSpace.linearScan(scan); + } + + /** + * Return the expected reference count. For non-reference counting + * collectors this becomes a true/false relationship. + * + * @param object The object to check. + * @param sanityRootRC The number of root references to the object. + * @return The expected (root excluded) reference count. + */ + public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { + if (RCBase.isRCObject(object)) { + int fullRC = RCHeader.getRC(object); + if (fullRC == 0) { + return SanityChecker.DEAD; + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(fullRC >= sanityRootRC); + return fullRC - sanityRootRC; + } + return SanityChecker.ALIVE; + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,182 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount; + +import org.mmtk.plan.Phase; +import org.mmtk.plan.StopTheWorldCollector; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.refcount.backuptrace.BTTraceLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.Inline; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the collector context for a simple reference counting + * collector. + */ + at Uninterruptible +public abstract class RCBaseCollector extends StopTheWorldCollector { + + /************************************************************************ + * Initialization + */ + protected final ObjectReferenceDeque newRootBuffer; + private final BTTraceLocal backupTrace; + private final ObjectReferenceDeque modBuffer; + private final ObjectReferenceDeque oldRootBuffer; + private final RCDecBuffer decBuffer; + private final RCZero zero; + + /** + * Constructor. + */ + public RCBaseCollector() { + newRootBuffer = new ObjectReferenceDeque("new-root", global().newRootPool); + oldRootBuffer = new ObjectReferenceDeque("old-root", global().oldRootPool); + modBuffer = new ObjectReferenceDeque("mod buf", global().modPool); + decBuffer = new RCDecBuffer(global().decPool); + backupTrace = new BTTraceLocal(global().backupTrace); + zero = new RCZero(); + } + + /** + * Get the modified processor to use. + */ + protected abstract TransitiveClosure getModifiedProcessor(); + + /** + * Get the root trace to use. + */ + protected abstract TraceLocal getRootTrace(); + + /**************************************************************************** + * + * Collection + */ + + /** Perform garbage collection */ + public void collect() { + Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection)); + } + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == RCBase.PREPARE) { + getRootTrace().prepare(); + if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) backupTrace.prepare(); + return; + } + + if (phaseId == RCBase.CLOSURE) { + getRootTrace().completeTrace(); + newRootBuffer.flushLocal(); + return; + } + + if (phaseId == RCBase.BT_CLOSURE) { + if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { + backupTrace.completeTrace(); + } + return; + } + + if (phaseId == RCBase.PROCESS_OLDROOTBUFFER) { + ObjectReference current; + while(!(current = oldRootBuffer.pop()).isNull()) { + decBuffer.push(current); + } + return; + } + + if (phaseId == RCBase.PROCESS_NEWROOTBUFFER) { + ObjectReference current; + while(!(current = newRootBuffer.pop()).isNull()) { + RCHeader.incRC(current); + oldRootBuffer.push(current); + if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { + if (RCHeader.testAndMark(current)) { + backupTrace.processNode(current); + } + } + } + oldRootBuffer.flushLocal(); + return; + } + + if (phaseId == RCBase.PROCESS_MODBUFFER) { + ObjectReference current; + while(!(current = modBuffer.pop()).isNull()) { + RCHeader.makeUnlogged(current); + VM.scanning.scanObject(getModifiedProcessor(), current); + } + return; + } + + if (phaseId == RCBase.PROCESS_DECBUFFER) { + ObjectReference current; + while(!(current = decBuffer.pop()).isNull()) { + if (RCHeader.decRC(current) == RCHeader.DEC_KILL) { + decBuffer.processChildren(current); + if (Space.isInSpace(RCBase.REF_COUNT, current)) { + RCBase.rcSpace.free(current); + } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) { + RCBase.rcloSpace.free(current); + } else if (Space.isInSpace(RCBase.IMMORTAL, current)) { + VM.scanning.scanObject(zero, current); + } + } + } + return; + } + + if (phaseId == RCBase.RELEASE) { + if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { + backupTrace.release(); + } + getRootTrace().release(); + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(newRootBuffer.isEmpty()); + VM.assertions._assert(modBuffer.isEmpty()); + VM.assertions._assert(decBuffer.isEmpty()); + } + return; + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an RC instance. */ + @Inline + protected static RCBase global() { + return (RCBase) VM.activePlan.global(); + } + + /** @return The current trace instance. */ + public final TraceLocal getCurrentTrace() { + return getRootTrace(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,36 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount; + +import static org.mmtk.policy.SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES; +import org.mmtk.plan.StopTheWorldConstraints; + +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class RCBaseConstraints extends StopTheWorldConstraints { + @Override + public int gcHeaderBits() { return RCHeader.GLOBAL_GC_BITS_REQUIRED; } + @Override + public int gcHeaderWords() { return RCHeader.GC_HEADER_WORDS_REQUIRED; } + @Override + public boolean needsWriteBarrier() { return true; } + @Override + public int maxNonLOSDefaultAllocBytes() { return MAX_FREELIST_OBJECT_BYTES; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,334 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount; + +import org.mmtk.plan.StopTheWorldMutator; +import org.mmtk.plan.refcount.backuptrace.BTSweepImmortalScanner; +import org.mmtk.policy.ExplicitFreeListLocal; +import org.mmtk.policy.ExplicitFreeListSpace; +import org.mmtk.policy.LargeObjectLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the mutator context for a simple reference counting collector. + */ + at Uninterruptible +public class RCBaseMutator extends StopTheWorldMutator { + + /************************************************************************ + * Instance fields + */ + private final ExplicitFreeListLocal rc; + private final LargeObjectLocal rclos; + private final ObjectReferenceDeque modBuffer; + private final RCDecBuffer decBuffer; + private final BTSweepImmortalScanner btSweepImmortal; + + /************************************************************************ + * + * Initialization + */ + + /** + * Constructor. One instance is created per physical processor. + */ + public RCBaseMutator() { + rc = new ExplicitFreeListLocal(RCBase.rcSpace); + rclos = new LargeObjectLocal(RCBase.rcloSpace); + modBuffer = new ObjectReferenceDeque("mod", global().modPool); + decBuffer = new RCDecBuffer(global().decPool); + btSweepImmortal = new BTSweepImmortalScanner(); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The address of the newly allocated memory. + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + switch (allocator) { + case RCBase.ALLOC_DEFAULT: + case RCBase.ALLOC_NON_MOVING: + case RCBase.ALLOC_CODE: + return rc.alloc(bytes, align, offset); + case RCBase.ALLOC_LOS: + case RCBase.ALLOC_PRIMITIVE_LOS: + case RCBase.ALLOC_LARGE_CODE: + return rclos.alloc(bytes, align, offset); + case RCBase.ALLOC_IMMORTAL: + return super.alloc(bytes, align, offset, allocator, site); + default: + VM.assertions.fail("Allocator not understood by RC"); + return Address.zero(); + } + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference ref, ObjectReference typeRef, int bytes, int allocator) { + switch (allocator) { + case RCBase.ALLOC_DEFAULT: + case RCBase.ALLOC_NON_MOVING: + modBuffer.push(ref); + case RCBase.ALLOC_CODE: + decBuffer.push(ref); + RCHeader.initializeHeader(ref, true); + ExplicitFreeListSpace.unsyncSetLiveBit(ref); + break; + case RCBase.ALLOC_LOS: + modBuffer.push(ref); + case RCBase.ALLOC_PRIMITIVE_LOS: + case RCBase.ALLOC_LARGE_CODE: + decBuffer.push(ref); + RCHeader.initializeHeader(ref, true); + RCBase.rcloSpace.initializeHeader(ref, true); + return; + case RCBase.ALLOC_IMMORTAL: + modBuffer.push(ref); + decBuffer.push(ref); + RCHeader.initializeHeader(ref, true); + return; + default: + VM.assertions.fail("Allocator not understood by RC"); + return; + } + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == RCBase.rcSpace) return rc; + if (space == RCBase.rcloSpace) return rclos; + + return super.getAllocatorFromSpace(space); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == RCBase.PREPARE) { + rc.prepare(); + return; + } + + if (phaseId == RCBase.PROCESS_MODBUFFER) { + modBuffer.flushLocal(); + return; + } + + if (phaseId == RCBase.PROCESS_DECBUFFER) { + decBuffer.flushLocal(); + return; + } + + if (phaseId == RCBase.RELEASE) { + if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { + immortal.linearScan(btSweepImmortal); + } + rc.release(); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(modBuffer.isEmpty()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(decBuffer.isEmpty()); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /** + * Flush per-mutator remembered sets into the global remset pool. + */ + public final void flushRememberedSets() { + decBuffer.flushLocal(); + modBuffer.flushLocal(); + assertRemsetsFlushed(); + } + + /** + * Assert that the remsets have been flushed. This is critical to + * correctness. We need to maintain the invariant that remset entries + * do not accrue during GC. If the host JVM generates barrier entires + * it is its own responsibility to ensure that they are flushed before + * returning to MMTk. + */ + public final void assertRemsetsFlushed() { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(decBuffer.isFlushed()); + VM.assertions._assert(modBuffer.isFlushed()); + } + } + + /** + * Flush mutator context, in response to a requestMutatorFlush. + * Also called by the default implementation of deinitMutator. + */ + @Override + public void flush() { + super.flush(); + rc.flush(); + } + + /**************************************************************************** + * + * Write barriers. + */ + + /** + * A new reference is about to be created. Take appropriate write + * barrier actions.

+ * + * By default do nothing, override if appropriate. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occurred + */ + @Inline + public void writeBarrier(ObjectReference src, Address slot, + ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + if (RCHeader.logRequired(src)) { + coalescingWriteBarrierSlow(src); + } + VM.barriers.performWriteInBarrier(src,slot,tgt, metaDataA, metaDataB, mode); + } + + /** + * Attempt to atomically exchange the value in the given slot + * with the passed replacement value. If a new reference is + * created, we must then take appropriate write barrier actions.

+ * + * By default do nothing, override if appropriate. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param old The old reference to be swapped out + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occured + * @return True if the swap was successful. + */ + @Inline + public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot, + ObjectReference old, ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + if (RCHeader.logRequired(src)) { + coalescingWriteBarrierSlow(src); + } + return VM.barriers.tryCompareAndSwapWriteInBarrier(src,slot,old,tgt,metaDataA,metaDataB,mode); + } + + /** + * A number of references are about to be copied from object + * src to object dst (as in an array + * copy). Thus, dst is the mutated object. Take + * appropriate write barrier actions.

+ * + * @param src The source of the values to be copied + * @param srcOffset The offset of the first source address, in + * bytes, relative to src (in principle, this could be + * negative). + * @param dst The mutated object, i.e. the destination of the copy. + * @param dstOffset The offset of the first destination address, in + * bytes relative to tgt (in principle, this could be + * negative). + * @param bytes The size of the region being copied, in bytes. + * @return True if the update was performed by the barrier, false if + * left to the caller (always false in this case). + */ + @Inline + public boolean writeBarrier(ObjectReference src, Offset srcOffset, + ObjectReference dst, Offset dstOffset, int bytes) { + if (RCHeader.logRequired(dst)) { + coalescingWriteBarrierSlow(dst); + } + return false; + } + + /** + * Slow path of the coalescing write barrier. + * + *

Attempt to log the source object. If successful in racing for + * the log bit, push an entry into the modified buffer and add a + * decrement buffer entry for each referent object (in the RC space) + * before setting the header bit to indicate that it has finished + * logging (allowing others in the race to continue). + * + * @param srcObj The object being mutated + */ + @NoInline + private void coalescingWriteBarrierSlow(ObjectReference srcObj) { + if (RCHeader.attemptToLog(srcObj)) { + modBuffer.push(srcObj); + decBuffer.processChildren(srcObj); + RCHeader.makeLogged(srcObj); + } + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an RC instance. */ + @Inline + private static RCBase global() { + return (RCBase) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,53 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount; + +import org.mmtk.utility.Constants; +import org.mmtk.utility.deque.*; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements a dec-buffer for a reference counting collector + * + * @see org.mmtk.plan.TransitiveClosure + */ + at Uninterruptible +public final class RCDecBuffer extends ObjectReferenceBuffer implements Constants { + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param queue The shared deque that is used. + */ + public RCDecBuffer(SharedDeque queue) { + super("dec", queue); + } + + /** + * This is the method that ensures + * + * @param object The object to process. + */ + @Inline + protected void process(ObjectReference object) { + if (RCBase.isRCObject(object)) { + push(object); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,276 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount; + +import org.mmtk.utility.Constants; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.Inline; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.ObjectReference; +import org.vmmagic.unboxed.Offset; +import org.vmmagic.unboxed.Word; + + at Uninterruptible +public class RCHeader implements Constants { + /* Requirements */ + public static final int LOCAL_GC_BITS_REQUIRED = 0; + public static final int GLOBAL_GC_BITS_REQUIRED = 2; + public static final int GC_HEADER_WORDS_REQUIRED = 1; + + /**************************************************************************** + * Object Logging (applies to *all* objects) + */ + + /* Mask bits to signify the start/finish of logging an object */ + public static final int LOG_BIT = 0; + public static final Word LOGGED = Word.zero(); //...00000 + public static final Word UNLOGGED = Word.one(); //...00001 + public static final Word BEING_LOGGED = Word.one().lsh(2).minus(Word.one()); //...00011 + public static final Word LOGGING_MASK = LOGGED.or(UNLOGGED).or(BEING_LOGGED); //...00011 + + /** + * Return true if object is yet to be logged (for + * coalescing RC). + * + * @param object The object in question + * @return true if object needs to be logged. + */ + @Inline + @Uninterruptible + public static boolean logRequired(ObjectReference object) { + Word value = VM.objectModel.readAvailableBitsWord(object); + return value.and(LOGGING_MASK).EQ(UNLOGGED); + } + + /** + * Attempt to log object for coalescing RC. This is + * used to handle a race to log the object, and returns + * true if we are to log the object and + * false if we lost the race to log the object. + * + *

If this method returns true, it leaves the object + * in the BEING_LOGGED state. It is the responsibility + * of the caller to change the object to LOGGED once + * the logging is complete. + * + * @see #makeLogged(ObjectReference) + * @param object The object in question + * @return true if the race to log + * objectwas won. + */ + @Inline + @Uninterruptible + public static boolean attemptToLog(ObjectReference object) { + Word oldValue; + do { + oldValue = VM.objectModel.prepareAvailableBits(object); + if (oldValue.and(LOGGING_MASK).EQ(LOGGED)) { + return false; + } + } while ((oldValue.and(LOGGING_MASK).EQ(BEING_LOGGED)) || + !VM.objectModel.attemptAvailableBits(object, oldValue, oldValue.or(BEING_LOGGED))); + if (VM.VERIFY_ASSERTIONS) { + Word value = VM.objectModel.readAvailableBitsWord(object); + VM.assertions._assert(value.and(LOGGING_MASK).EQ(BEING_LOGGED)); + } + return true; + } + + + /** + * Signify completion of logging object. + * + * object is left in the LOGGED state. + * + * @see #attemptToLog(ObjectReference) + * @param object The object whose state is to be changed. + */ + @Inline + @Uninterruptible + public static void makeLogged(ObjectReference object) { + Word value = VM.objectModel.readAvailableBitsWord(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(LOGGING_MASK).NE(LOGGED)); + VM.objectModel.writeAvailableBitsWord(object, value.and(LOGGING_MASK.not())); + } + + /** + * Change object's state to UNLOGGED. + * + * @param object The object whose state is to be changed. + */ + @Inline + @Uninterruptible + public static void makeUnlogged(ObjectReference object) { + Word value = VM.objectModel.readAvailableBitsWord(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(LOGGING_MASK).EQ(LOGGED)); + VM.objectModel.writeAvailableBitsWord(object, value.or(UNLOGGED)); + } + + /************************************************************************ + * RC header word + */ + + /* Header offset */ + public static final Offset RC_HEADER_OFFSET = VM.objectModel.GC_HEADER_OFFSET(); + + /* Reserved to allow alignment hole filling to work */ + public static final int RESERVED_ALIGN_BIT = 0; + + /* The mark bit used for backup tracing. */ + public static final int MARK_BIT = 1; + public static final Word MARK_BIT_MASK = Word.one().lsh(MARK_BIT); + + /* Current not using any bits for cycle detection, etc */ + public static final int BITS_USED = 2; + + /* Reference counting increments */ + public static final int INCREMENT_SHIFT = BITS_USED; + public static final Word INCREMENT = Word.one().lsh(INCREMENT_SHIFT); + public static final int AVAILABLE_BITS = BITS_IN_ADDRESS - BITS_USED; + public static final Word INCREMENT_LIMIT = Word.one().lsh(BITS_IN_ADDRESS-1).not(); + public static final Word LIVE_THRESHOLD = INCREMENT; + + /* Return values from decRC */ + public static final int DEC_KILL = 0; + public static final int DEC_ALIVE = 1; + + /** + * Has this object been marked by the most recent backup trace. + */ + @Inline + public static boolean isMarked(ObjectReference object) { + return isHeaderMarked(object.toAddress().loadWord(RC_HEADER_OFFSET)); + } + + /** + * Has this object been marked by the most recent backup trace. + */ + @Inline + public static void clearMarked(ObjectReference object) { + Word oldValue, newValue; + do { + oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isHeaderMarked(oldValue)); + newValue = oldValue.and(MARK_BIT_MASK.not()); + } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET)); + /* + Word header = object.toAddress().loadWord(RC_HEADER_OFFSET); + object.toAddress().store(header.and(MARK_BIT_MASK.not()), RC_HEADER_OFFSET);*/ + } + + /** + * Has this object been marked by the most recent backup trace. + */ + @Inline + private static boolean isHeaderMarked(Word header) { + return header.and(MARK_BIT_MASK).EQ(MARK_BIT_MASK); + } + + /** + * Attempt to atomically mark this object. Return true if the mark was performed. + */ + @Inline + public static boolean testAndMark(ObjectReference object) { + Word oldValue, newValue; + do { + oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET); + if (isHeaderMarked(oldValue)) { + return false; + } + newValue = oldValue.or(MARK_BIT_MASK); + } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET)); + return true; + } + + /** + * Perform any required initialization of the GC portion of the header. + * + * @param object the object + * @param initialInc start with a reference count of 1 (0 if false) + */ + @Inline + public static void initializeHeader(ObjectReference object, boolean initialInc) { + Word initialValue = (initialInc) ? INCREMENT : Word.zero(); + object.toAddress().store(initialValue, RC_HEADER_OFFSET); + } + + /** + * Return true if given object is live + * + * @param object The object whose liveness is to be tested + * @return True if the object is alive + */ + @Inline + @Uninterruptible + public static boolean isLiveRC(ObjectReference object) { + return object.toAddress().loadWord(RC_HEADER_OFFSET).GE(LIVE_THRESHOLD); + } + + /** + * Return the reference count for the object. + * + * @param object The object whose liveness is to be tested + * @return True if the object is alive + */ + @Inline + @Uninterruptible + public static int getRC(ObjectReference object) { + return object.toAddress().loadWord(RC_HEADER_OFFSET).rshl(INCREMENT_SHIFT).toInt(); + } + + /** + * Increment the reference count of an object. + * + * @param object The object whose reference count is to be incremented. + */ + @Inline + public static void incRC(ObjectReference object) { + Word oldValue, newValue; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(RCBase.isRCObject(object)); + do { + oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET); + newValue = oldValue.plus(INCREMENT); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(newValue.LE(INCREMENT_LIMIT)); + } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET)); + } + + /** + * Decrement the reference count of an object. Return either + * DEC_KILL if the count went to zero, + * DEC_ALIVE if the count did not go to zero. + * + * @param object The object whose RC is to be decremented. + * @return DEC_KILL if the count went to zero, + * DEC_ALIVE if the count did not go to zero. + */ + @Inline + @Uninterruptible + public static int decRC(ObjectReference object) { + Word oldValue, newValue; + int rtn; + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(RCBase.isRCObject(object)); + VM.assertions._assert(isLiveRC(object)); + } + do { + oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET); + newValue = oldValue.minus(INCREMENT); + if (newValue.LT(LIVE_THRESHOLD)) { + rtn = DEC_KILL; + } else { + rtn = DEC_ALIVE; + } + } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET)); + return rtn; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,40 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount; + +import org.mmtk.plan.TransitiveClosure; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is the fundamental mechanism for performing a + * transitive closure over an object graph.

+ * + * @see org.mmtk.plan.TraceLocal + */ + at Uninterruptible +public final class RCZero extends TransitiveClosure { + + /** + * Trace an edge during GC. + * + * @param source The source of the reference. + * @param slot The location containing the object reference. + */ + @Inline + public void processEdge(ObjectReference source, Address slot) { + slot.store(ObjectReference.nullReference()); + } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,51 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.backuptrace; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.Space; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is the fundamental mechanism for performing a + * transitive closure over an object graph.

+ * + * @see org.mmtk.plan.TraceLocal + */ + at Uninterruptible +public final class BTDecMarked extends TransitiveClosure { + + /** + * Trace an edge during GC. + * + * @param source The source of the reference. + * @param slot The location containing the object reference. + */ + @Inline + public void processEdge(ObjectReference source, Address slot) { + ObjectReference object = slot.loadObjectReference(); + if (!object.isNull()) { + if ((Space.isInSpace(RCBase.REF_COUNT, object) && RCBase.rcSpace.isLive(object)) || + Space.isInSpace(RCBase.REF_COUNT_LOS, object) || + Space.isInSpace(RCBase.IMMORTAL, object)) { + int result = RCHeader.decRC(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(result != RCHeader.DEC_KILL || !RCHeader.isMarked(object)); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,52 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.backuptrace; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.Space; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is the fundamental mechanism for performing a + * transitive closure over an object graph.

+ * + * @see org.mmtk.plan.TraceLocal + */ + at Uninterruptible +public final class BTDecMarkedAndZero extends TransitiveClosure { + + /** + * Trace an edge during GC. + * + * @param source The source of the reference. + * @param slot The location containing the object reference. + */ + @Inline + public void processEdge(ObjectReference source, Address slot) { + ObjectReference object = slot.loadObjectReference(); + slot.store(ObjectReference.nullReference()); + if (!object.isNull()) { + if ((Space.isInSpace(RCBase.REF_COUNT, object) && RCBase.rcSpace.isLive(object)) || + Space.isInSpace(RCBase.REF_COUNT_LOS, object) || + Space.isInSpace(RCBase.IMMORTAL, object)) { + int result = RCHeader.decRC(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(result != RCHeader.DEC_KILL || !RCHeader.isMarked(object)); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,36 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.backuptrace; + +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.ExplicitLargeObjectSpace; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the freeing of large objects during a backup trace. + */ + at Uninterruptible +public final class BTFreeLargeObjectSweeper extends ExplicitLargeObjectSpace.Sweeper { + + public boolean sweepLargeObject(ObjectReference object) { + if (!RCHeader.isMarked(object)) { + // Free the object + return true; + } + // Clear the mark-bit and retain the object. + RCHeader.clearMarked(object); + return false; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,37 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.backuptrace; + +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.ExplicitLargeObjectSpace; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the scanning of dead large objects during a backup trace. + */ + at Uninterruptible +public final class BTScanLargeObjectSweeper extends ExplicitLargeObjectSpace.Sweeper { + + private final BTDecMarked sdm = new BTDecMarked(); + + public boolean sweepLargeObject(ObjectReference object) { + if (!RCHeader.isMarked(object)) { + VM.scanning.scanObject(sdm, object); + } + // Do not free any objects at this time + return false; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,43 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.backuptrace; + +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.utility.alloc.LinearScan; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is used in backup tracing to sweep and zero any dead 'immortal' objects. + */ + at Uninterruptible +public final class BTSweepImmortalScanner extends LinearScan { + + private final BTDecMarkedAndZero sdmAZ = new BTDecMarkedAndZero(); + + /** + * Scan an object during sweep. + * + * @param object The source of the reference. + */ + @Inline + public void scan(ObjectReference object) { + if (!RCHeader.isMarked(object)) { + VM.scanning.scanObject(sdmAZ, object); + } else { + RCHeader.clearMarked(object); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,40 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.backuptrace; + +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.ExplicitFreeListSpace; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public final class BTSweeper extends ExplicitFreeListSpace.Sweeper { + + private final BTDecMarked sdm = new BTDecMarked(); + + public boolean sweepCell(ObjectReference object) { + if (!RCHeader.isMarked(object)) { + VM.scanning.scanObject(sdm, object); + return true; + } else { + RCHeader.clearMarked(object); + } + return false; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,66 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.backuptrace; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.plan.refcount.RCHeader; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public final class BTTraceLocal extends TraceLocal { + /** + * Constructor + */ + public BTTraceLocal(Trace trace) { + super(trace); + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object reachable? + * + * @param object The object. + * @return true if the object is reachable. + */ + public boolean isLive(ObjectReference object) { + return !RCBase.isRCObject(object) || RCHeader.isMarked(object); + } + + /** + * When we trace a non-root object we do nothing. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (RCBase.isRCObject(object)) { + if (RCHeader.testAndMark(object)) { + processNode(object); + } + } + return object; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,23 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.fullheap; + +import org.mmtk.plan.refcount.RCBase; +import org.vmmagic.pragma.*; + +/** + * This class implements the global state of a a simple reference counting collector. + */ + at Uninterruptible +public class RC extends RCBase { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,53 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.fullheap; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.refcount.RCBaseCollector; +import org.vmmagic.pragma.*; + +/** + * This class implements the collector context for a simple reference counting + * collector. + */ + at Uninterruptible +public class RCCollector extends RCBaseCollector { + /************************************************************************ + * Initialization + */ + private final RCFindRootSetTraceLocal rootTrace; + private final RCModifiedProcessor modProcessor; + + /** + * Constructor. + */ + public RCCollector() { + rootTrace = new RCFindRootSetTraceLocal(global().rootTrace, newRootBuffer); + modProcessor = new RCModifiedProcessor(); + } + + /** + * Get the modified processor to use. + */ + protected final TransitiveClosure getModifiedProcessor() { + return modProcessor; + } + + /** + * Get the root trace to use. + */ + protected final TraceLocal getRootTrace() { + return rootTrace; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,26 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.fullheap; + +import org.mmtk.plan.refcount.RCBaseConstraints; +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class RCConstraints extends RCBaseConstraints { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,80 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.fullheap; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.utility.deque.ObjectReferenceDeque; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public final class RCFindRootSetTraceLocal extends TraceLocal { + + private final ObjectReferenceDeque rootBuffer; + + /** + * Constructor + */ + public RCFindRootSetTraceLocal(Trace trace, ObjectReferenceDeque rootBuffer) { + super(trace); + this.rootBuffer = rootBuffer; + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object reachable? + * + * @param object The object. + * @return true if the object is reachable. + */ + public boolean isLive(ObjectReference object) { + return RCBase.isRCObject(object) && RCHeader.isLiveRC(object) || super.isLive(object); + } + + /** + * When we trace a non-root object we do nothing. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + return object; + } + + /** + * When we trace a root object we remember it. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object, boolean root) { + if (root && RCBase.isRCObject(object)) { + rootBuffer.push(object); + } + return object; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,44 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.fullheap; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.plan.refcount.RCHeader; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is the fundamental mechanism for performing a + * transitive closure over an object graph.

+ * + * @see org.mmtk.plan.TraceLocal + */ + at Uninterruptible +public final class RCModifiedProcessor extends TransitiveClosure { + + /** + * Trace an edge during GC. + * + * @param source The source of the reference. + * @param slot The location containing the object reference. + */ + @Inline + public void processEdge(ObjectReference source, Address slot) { + ObjectReference object = slot.loadObjectReference(); + if (RCBase.isRCObject(object)) { + RCHeader.incRC(object); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,23 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.fullheap; + +import org.mmtk.plan.refcount.RCBaseMutator; +import org.vmmagic.pragma.*; + +/** + * This class implements the mutator context for a simple reference counting collector. + */ + at Uninterruptible +public class RCMutator extends RCBaseMutator { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,128 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.generational; + +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.Space; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.options.Options; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the global state of a a simple reference counting collector. + */ + at Uninterruptible +public class GenRC extends RCBase { + + public static final int ALLOC_NURSERY = ALLOC_DEFAULT; + public static final int ALLOC_RC = RCBase.ALLOCATORS + 1; + + /** The nursery space is where all new objects are allocated by default */ + public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, VMRequest.create(0.15f, true)); + + public static final int NURSERY = nurserySpace.getDescriptor(); + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase + */ + public final void collectionPhase(short phaseId) { + if (phaseId == PREPARE) { + nurserySpace.prepare(true); + super.collectionPhase(phaseId); + return; + } + + if (phaseId == RELEASE) { + super.collectionPhase(phaseId); + nurserySpace.release(); + return; + } + + super.collectionPhase(phaseId); + } + + /** + * This method controls the triggering of a GC. It is called periodically + * during allocation. Returns true to trigger a collection. + * + * @param spaceFull Space request failed, must recover pages within 'space'. + * @return True if a collection is requested by the plan. + */ + public final boolean collectionRequired(boolean spaceFull) { + boolean nurseryFull = nurserySpace.reservedPages() > Options.nurserySize.getMaxNursery(); + return super.collectionRequired(spaceFull) || nurseryFull; + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages available for allocation, assuming + * all future allocation is to the nursery. + * + * @return The number of pages available for allocation, assuming + * all future allocation is to the nursery. + */ + public int getPagesAvail() { + return super.getPagesAvail() >> 1; + } + + /** + * Return the number of pages reserved for copying. + * + * @return The number of pages reserved given the pending + * allocation, including space reserved for copying. + */ + public final int getCollectionReserve() { + return nurserySpace.reservedPages() + super.getCollectionReserve(); + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return super.getPagesRequired() + (nurserySpace.requiredPages() << 1); + } + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return True if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(NURSERY, object)) { + return false; + } + if (Space.isInSpace(REF_COUNT_LOS, object)) { + return true; + } + return super.willNeverMove(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,124 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.generational; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.plan.refcount.RCBaseCollector; +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.ExplicitFreeListLocal; +import org.mmtk.policy.ExplicitFreeListSpace; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the collector context for a simple reference counting + * collector. + */ + at Uninterruptible +public class GenRCCollector extends RCBaseCollector { + private final GenRCFindRootSetTraceLocal rootTrace; + private final GenRCModifiedProcessor modProcessor; + private final ExplicitFreeListLocal rc; + + public GenRCCollector() { + rc = new ExplicitFreeListLocal(GenRC.rcSpace); + rootTrace = new GenRCFindRootSetTraceLocal(global().rootTrace, newRootBuffer); + modProcessor = new GenRCModifiedProcessor(rootTrace); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == RCBase.PREPARE) { + super.collectionPhase(phaseId, primary); + rc.prepare(); + return; + } + + if (phaseId == RCBase.RELEASE) { + rc.release(); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment + * @param offset The alignment offset + * @return The address of the first byte of the allocated region + */ + @Inline + public final Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(allocator == GenRC.ALLOC_RC); + } + return rc.alloc(bytes, align, offset); + } + + /** + * Perform any post-copy actions. In this case nothing is required. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + */ + @Inline + public final void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + CopySpace.clearGCBits(object); + RCHeader.initializeHeader(object, false); + RCHeader.makeUnlogged(object); + ExplicitFreeListSpace.unsyncSetLiveBit(object); + } + + /** + * Get the modified processor to use. + */ + protected final TransitiveClosure getModifiedProcessor() { + return modProcessor; + } + + /** + * Get the root trace to use. + */ + protected final TraceLocal getRootTrace() { + return rootTrace; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.generational; + +import static org.mmtk.policy.SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES; + +import org.mmtk.plan.refcount.RCBaseConstraints; +import org.vmmagic.pragma.*; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class GenRCConstraints extends RCBaseConstraints { + @Override + public boolean movesObjects() { return true; } + @Override + public int maxNonLOSCopyBytes() { return MAX_FREELIST_OBJECT_BYTES;} +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,123 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.generational; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public final class GenRCFindRootSetTraceLocal extends TraceLocal { + + private final ObjectReferenceDeque rootBuffer; + + /** + * Constructor + */ + public GenRCFindRootSetTraceLocal(Trace trace, ObjectReferenceDeque rootBuffer) { + super(trace); + this.rootBuffer = rootBuffer; + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object reachable? + * + * @param object The object. + * @return true if the object is reachable. + */ + public boolean isLive(ObjectReference object) { + return GenRC.isRCObject(object) && RCHeader.isLiveRC(object) || + (!Space.isInSpace(GenRC.NURSERY, object) && super.isLive(object)); + } + + /** + * When we trace a non-root object we do nothing. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + return traceObject(object, false); + } + + /** + * When we trace a root object we remember it. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object, boolean root) { + if (object.isNull()) return object; + + if (Space.isInSpace(GenRC.NURSERY, object)) { + object = GenRC.nurserySpace.traceObject(this, object, GenRC.ALLOC_RC); + } else if (!GenRC.isRCObject(object)) { + return object; + } + + if (root) { + rootBuffer.push(object); + } else { + RCHeader.incRC(object); + } + + return object; + } + + /** + * Ensure that the referenced object will not move from this point through + * to the end of the collection. This can involve forwarding the object + * if necessary. + * + * Non-copying collectors do nothing, copying collectors must + * override this method in each of their trace classes. + * + * @param object The object that must not move during the collection. + * @return True If the object will not move during collection + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull()); + return !(Space.isInSpace(GenRC.NURSERY, object)); + } + + /** + * Ensure that this object will not move for the rest of the GC. + * + * @param object The object that must not move + * @return The new object, guaranteed stable for the rest of the GC. + */ + public ObjectReference precopyObject(ObjectReference object) { + if (Space.isInSpace(GenRC.NURSERY, object)) { + return GenRC.nurserySpace.traceObject(this, object, GenRC.ALLOC_RC); + } + return object; + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,56 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.generational; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.refcount.RCHeader; +import org.mmtk.policy.Space; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is the fundamental mechanism for performing a + * transitive closure over an object graph.

+ * + * @see org.mmtk.plan.TraceLocal + */ + at Uninterruptible +public final class GenRCModifiedProcessor extends TransitiveClosure { + + private final GenRCFindRootSetTraceLocal trace; + + public GenRCModifiedProcessor(GenRCFindRootSetTraceLocal trace) { + this.trace = trace; + } + + /** + * Trace an edge during GC. + * + * @param source The source of the reference. + * @param slot The location containing the object reference. + */ + @Inline + public void processEdge(ObjectReference source, Address slot) { + ObjectReference object = slot.loadObjectReference(); + if (!object.isNull()) { + if (Space.isInSpace(GenRC.NURSERY, object)) { + object = GenRC.nurserySpace.traceObject(trace, object, GenRC.ALLOC_RC); + RCHeader.incRC(object); + slot.store(object); + } else if (GenRC.isRCObject(object)) { + RCHeader.incRC(object); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,113 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.refcount.generational; + +import org.mmtk.plan.refcount.RCBase; +import org.mmtk.plan.refcount.RCBaseMutator; +import org.mmtk.policy.CopyLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the mutator context for a simple reference counting collector. + */ + at Uninterruptible +public class GenRCMutator extends RCBaseMutator { + /************************************************************************ + * Instance fields + */ + private final CopyLocal nursery; + + public GenRCMutator() { + nursery = new CopyLocal(GenRC.nurserySpace); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate memory for an object. + * + * @param bytes The number of bytes required for the object. + * @param align Required alignment for the object. + * @param offset Offset associated with the alignment. + * @param allocator The allocator associated with this request. + * @param site Allocation site + * @return The address of the newly allocated memory. + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == GenRC.ALLOC_NURSERY) { + return nursery.alloc(bytes, align, offset); + } + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param ref The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference ref, ObjectReference typeRef, int bytes, int allocator) { + if (allocator == GenRC.ALLOC_NURSERY) { + return; + } + super.postAlloc(ref, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == GenRC.nurserySpace) return nursery; + + return super.getAllocatorFromSpace(space); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == RCBase.PREPARE) { + nursery.rebind(GenRC.nurserySpace); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,206 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace; + +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.Space; +import org.mmtk.plan.*; +import org.mmtk.utility.heap.VMRequest; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements a simple semi-space collector. See the Jones + * & Lins GC book, section 2.2 for an overview of the basic + * algorithm. This implementation also includes a large object space + * (LOS), and an uncollected "immortal" space.

+ * + * All plans make a clear distinction between global and + * thread-local activities. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. Instances of Plan map 1:1 to "kernel + * threads" (aka CPUs). Thus instance + * methods allow fast, unsychronized access to Plan utilities such as + * allocation and collection. Each instance rests on static resources + * (such as memory and virtual memory resources) which are "global" + * and therefore "static" members of Plan. This mapping of threads to + * instances is crucial to understanding the correctness and + * performance proprties of this plan. + */ + at Uninterruptible +public class SS extends StopTheWorld { + + /**************************************************************************** + * + * Class variables + */ + + /** True if allocating into the "higher" semispace */ + public static boolean hi = false; // True if allocing to "higher" semispace + + /** One of the two semi spaces that alternate roles at each collection */ + public static final CopySpace copySpace0 = new CopySpace("ss0", DEFAULT_POLL_FREQUENCY, false, VMRequest.create()); + public static final int SS0 = copySpace0.getDescriptor(); + + /** One of the two semi spaces that alternate roles at each collection */ + public static final CopySpace copySpace1 = new CopySpace("ss1", DEFAULT_POLL_FREQUENCY, true, VMRequest.create()); + public static final int SS1 = copySpace1.getDescriptor(); + + public final Trace ssTrace; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Class variables + */ + public static final int ALLOC_SS = Plan.ALLOC_DEFAULT; + + public static final int SCAN_SS = 0; + + /** + * Constructor + */ + public SS() { + ssTrace = new Trace(metaDataSpace); + } + + /** + * @return The to space for the current collection. + */ + @Inline + public static CopySpace toSpace() { + return hi ? copySpace1 : copySpace0; + } + + /** + * @return The from space for the current collection. + */ + @Inline + public static CopySpace fromSpace() { + return hi ? copySpace0 : copySpace1; + } + + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase + */ + @Inline + public void collectionPhase(short phaseId) { + if (phaseId == SS.PREPARE) { + hi = !hi; // flip the semi-spaces + // prepare each of the collected regions + copySpace0.prepare(hi); + copySpace1.prepare(!hi); + ssTrace.prepare(); + super.collectionPhase(phaseId); + return; + } + if (phaseId == CLOSURE) { + ssTrace.prepare(); + return; + } + if (phaseId == SS.RELEASE) { + // release the collected region + fromSpace().release(); + + super.collectionPhase(phaseId); + return; + } + + super.collectionPhase(phaseId); + } + + /**************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for copying. + * + * @return The number of pages reserved given the pending + * allocation, including space reserved for copying. + */ + public final int getCollectionReserve() { + // we must account for the number of pages required for copying, + // which equals the number of semi-space pages reserved + return toSpace().reservedPages() + super.getCollectionReserve(); + } + + /** + * Return the number of pages reserved for use given the pending + * allocation. This is exclusive of space reserved for + * copying. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public int getPagesUsed() { + return super.getPagesUsed() + toSpace().reservedPages(); + } + + /** + * Return the number of pages available for allocation, assuming + * all future allocation is to the semi-space. + * + * @return The number of pages available for allocation, assuming + * all future allocation is to the semi-space. + */ + public final int getPagesAvail() { + return(super.getPagesAvail()) >> 1; + } + + /** + * Calculate the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + * + * @return the number of pages a collection is required to free to satisfy + * outstanding allocation requests. + */ + public int getPagesRequired() { + return super.getPagesRequired() + (toSpace().requiredPages() << 1); + } + + /** + * @see org.mmtk.plan.Plan#willNeverMove + * + * @param object Object in question + * @return True if the object will never move + */ + @Override + public boolean willNeverMove(ObjectReference object) { + if (Space.isInSpace(SS0, object) || Space.isInSpace(SS1, object)) + return false; + return super.willNeverMove(object); + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_SS, SSTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,188 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace; + +import org.mmtk.plan.*; +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.CopyLocal; +import org.mmtk.policy.LargeObjectLocal; +import org.mmtk.policy.Space; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements per-collector thread behavior + * and state for the SS plan, which implements a full-heap + * semi-space collector.

+ * + * Specifically, this class defines SS collection behavior + * (through trace and the collectionPhase + * method), and collection-time allocation (copying of objects).

+ * + * See {@link SS} for an overview of the semi-space algorithm.

+ * + * @see SS + * @see SSMutator + * @see StopTheWorldCollector + * @see CollectorContext + */ + at Uninterruptible +public class SSCollector extends StopTheWorldCollector { + + /**************************************************************************** + * Instance fields + */ + + protected final SSTraceLocal trace; + protected final CopyLocal ss; + protected final LargeObjectLocal los; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public SSCollector() { + this(new SSTraceLocal(global().ssTrace)); + } + + /** + * Constructor + * @param tr The trace to use + */ + protected SSCollector(SSTraceLocal tr) { + ss = new CopyLocal(); + los = new LargeObjectLocal(Plan.loSpace); + trace = tr; + } + + /**************************************************************************** + * + * Collection-time allocation + */ + + /** + * Allocate space for copying an object (this method does not + * copy the object, it only allocates space) + * + * @param original A reference to the original object + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @return The address of the first byte of the allocated region + */ + @Inline + public Address allocCopy(ObjectReference original, int bytes, + int align, int offset, int allocator) { + if (allocator == Plan.ALLOC_LOS) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bytes > Plan.MAX_NON_LOS_COPY_BYTES); + return los.alloc(bytes, align, offset); + } else { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES); + VM.assertions._assert(allocator == SS.ALLOC_SS); + } + return ss.alloc(bytes, align, offset); + } + } + + /** + * Perform any post-copy actions. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + */ + @Inline + public void postCopy(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + CopySpace.clearGCBits(object); + if (allocator == Plan.ALLOC_LOS) + Plan.loSpace.initializeHeader(object, false); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == SS.PREPARE) { + // rebind the copy bump pointer to the appropriate semispace. + ss.rebind(SS.toSpace()); + los.prepare(true); + super.collectionPhase(phaseId, primary); + return; + } + + if (phaseId == SS.CLOSURE) { + trace.completeTrace(); + return; + } + + if (phaseId == SS.RELEASE) { + trace.release(); + los.release(true); + super.collectionPhase(phaseId, primary); + return; + } + + super.collectionPhase(phaseId, primary); + } + + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Return true if the given reference is to an object that is within + * one of the semi-spaces. + * + * @param object The object in question + * @return True if the given reference is to an object that is within + * one of the semi-spaces. + */ + public static boolean isSemiSpaceObject(ObjectReference object) { + return Space.isInSpace(SS.SS0, object) || Space.isInSpace(SS.SS1, object); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an SS instance. */ + @Inline + private static SS global() { + return (SS) VM.activePlan.global(); + } + + /** @return the current trace object. */ + public TraceLocal getCurrentTrace() { + return trace; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace; + +import org.mmtk.plan.*; +import org.mmtk.policy.CopySpace; +import org.vmmagic.pragma.*; + +/** + * SemiSpace common constants. + */ + at Uninterruptible +public class SSConstraints extends StopTheWorldConstraints { + @Override + public boolean movesObjects() { return true; } + @Override + public int gcHeaderBits() { return CopySpace.LOCAL_GC_BITS_REQUIRED; } + @Override + public int gcHeaderWords() { return CopySpace.GC_HEADER_WORDS_REQUIRED; } + @Override + public int numSpecializedScans() { return 1; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,163 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace; + +import org.mmtk.plan.*; +import org.mmtk.policy.CopyLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.alloc.Allocator; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements per-mutator thread behavior + * and state for the SS plan, which implements a full-heap + * semi-space collector.

+ * + * Specifically, this class defines SS mutator-time allocation + * and per-mutator thread collection semantics (flushing and restoring + * per-mutator allocator state).

+ * + * See {@link SS} for an overview of the semi-space algorithm.

+ * + * @see SS + * @see SSCollector + * @see StopTheWorldMutator + * @see MutatorContext + */ + at Uninterruptible +public class SSMutator extends StopTheWorldMutator { + /**************************************************************************** + * Instance fields + */ + protected final CopyLocal ss; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public SSMutator() { + ss = new CopyLocal(); + } + + /** + * Called before the MutatorContext is used, but after the context has been + * fully registered and is visible to collection. + */ + public void initMutator(int id) { + super.initMutator(id); + ss.rebind(SS.toSpace()); + } + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate space (for an object) + * + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @param allocator The allocator number to be used for this allocation + * @param site Allocation site + * @return The address of the first byte of the allocated region + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == SS.ALLOC_SS) + return ss.alloc(bytes, align, offset); + else + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param object The newly allocated object + * @param typeRef The type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == SS.ALLOC_SS) return; + super.postAlloc(object, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == SS.copySpace0 || space == SS.copySpace1) return ss; + return super.getAllocatorFromSpace(space); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == SS.PREPARE) { + super.collectionPhase(phaseId, primary); + return; + } + + if (phaseId == SS.RELEASE) { + super.collectionPhase(phaseId, primary); + // rebind the allocation bump pointer to the appropriate semispace. + ss.rebind(SS.toSpace()); + return; + } + + super.collectionPhase(phaseId, primary); + } + + + /**************************************************************************** + * + * Miscellaneous + */ + + /** + * Show the status of each of the allocators. + */ + public final void show() { + ss.show(); + los.show(); + immortal.show(); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,110 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implments the core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public class SSTraceLocal extends TraceLocal { + /** + * Constructor + */ + public SSTraceLocal(Trace trace, boolean specialized) { + super(specialized ? SS.SCAN_SS : -1, trace); + } + + /** + * Constructor + */ + public SSTraceLocal(Trace trace) { + this(trace, true); + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Return true if obj is a live object. + * + * @param object The object in question + * @return True if obj is a live object. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(SS.SS0, object)) + return SS.hi ? SS.copySpace0.isLive(object) : true; + if (Space.isInSpace(SS.SS1, object)) + return SS.hi ? true : SS.copySpace1.isLive(object); + return super.isLive(object); + } + + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(SS.SS0, object)) + return SS.copySpace0.traceObject(this, object, SS.ALLOC_SS); + if (Space.isInSpace(SS.SS1, object)) + return SS.copySpace1.traceObject(this, object, SS.ALLOC_SS); + return super.traceObject(object); + } + + /** + * Ensure that this object will not move for the rest of the GC. + * + * @param object The object that must not move + * @return The new object, guaranteed stable for the rest of the GC. + */ + @Inline + public ObjectReference precopyObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(SS.SS0, object)) + return SS.copySpace0.traceObject(this, object, SS.ALLOC_SS); + if (Space.isInSpace(SS.SS1, object)) + return SS.copySpace1.traceObject(this, object, SS.ALLOC_SS); + return object; + } + + /** + * Will this object move from this point on, during the current trace ? + * + * @param object The object to query. + * @return True if the object will not move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + return (SS.hi && !Space.isInSpace(SS.SS0, object)) || + (!SS.hi && !Space.isInSpace(SS.SS1, object)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,353 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gcspy; + +import org.mmtk.plan.GCspyPlan; +import org.mmtk.plan.Phase; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.semispace.SS; +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.LargeObjectSpace; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver; +import org.mmtk.utility.gcspy.drivers.ImmortalSpaceDriver; +import org.mmtk.utility.gcspy.drivers.TreadmillDriver; +import org.mmtk.utility.gcspy.GCspy; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; + +import org.vmmagic.pragma.*; + +/** + * This class extends a simple semi-space collector to instrument it for + * GCspy.

+ * + * See the Jones & Lins GC book, section 2.2 for an overview of the basic + * algorithm. This implementation also includes a large object space + * (LOS), and an uncollected "immortal" space.

+ * + * All plans make a clear distinction between global and + * thread-local activities. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. Instances of Plan map 1:1 to "kernel + * threads" (aka CPUs). Thus instance + * methods allow fast, unsychronized access to Plan utilities such as + * allocation and collection. Each instance rests on static resources + * (such as memory and virtual memory resources) which are "global" + * and therefore "static" members of Plan. This mapping of threads to + * instances is crucial to understanding the correctness and + * performance proprties of this plan. + * + * FIXME This seems to have changed + * The order of phases and GCspy actions is important here. It is: + * PREPARE phase + * SSGCspyMutator.gcspyGatherData(SSGCspy.BEFORE_COLLECTION); // safepoint + * SSMutator.PREPARE // FIXME DOES NOT ss.rebind(SS.toSpace()); + * + * PREPARE phase + * SS.PREPARE // flip semispaces + * gcspySpace.prepare(); + * SSGCspyCollector.gcspyGatherData(SSGCspy.BEFORE_COLLECTION); + * SSCollector.PREPARE // ss.rebind(SS.toSpace()); + * + * + * FORWARD_FINALIZABLE phase + * SSCollector.FORWARD_FINALIZABLE + * SSGCspyCollector.gcspyGatherData(SSGCspy.SEMISPACE_COPIED); + * + * RELEASE phase + * SSGCspyMutator.gcspyGatherData(SSGCspy.SEMISPACE_COPIED); // safepoint + * SSMutator.RELEASE // FIXME ss.rebind(SS.toSpace()); + * SSGCspyMutator.gcspyGatherData(SSGCspy.AFTER_COLLECTION); + * + * RELEASE phase + * SSCollector.RELEASE + * SSGCspyCollector.gcspyGatherData(SSGCspy.AFTER_COLLECTION); + * SS.RELEASE + * gcspySpace.release(); + * SSGCspy.gcspyGatherData(); // safepoint + * + * Note that SSMutator has changed the point at which it rebinds toSpace + * from PREPARE (2.4.6) to after RELEASE (3.x.x). + * + --Phase Collector.initiate + --Phase Mutator.initiate-mutator + --Phase Mutator.prepare-mutator + SSGCspyMutator.gcspyGatherData, event=0 + --Phase Plan.prepare + --Phase Collector.prepare + SSGCspyCollector.gcspyGatherData, event=0 + --Phase Collector.precopy + --Phase Collector.bootimage-root + --Phase Collector.root + --Phase Plan.root + --Phase Collector.start-closure + --Phase Collector.soft-ref + --Phase Collector.complete-closure + --Phase Collector.weak-ref + --Phase Collector.finalize + --Phase Collector.complete-closure + --Phase Collector.phantom-ref + --Phase Collector.forward-ref + --Phase Collector.forward-finalize + SSGCspyCollector.gcspyGatherData, event=1 + --Phase Mutator.release-mutator + SSGCspyMutator.gcspyGatherData, event=1 + SSGCspyMutator.gcspyGatherData, event=2 + --Phase Collector.release + SSGCspyCollector.gcspyGatherData, event=2 + --Phase Plan.release + SSGCspy.gcspyGatherData, event=2 + --Phase Collector.complete + --Phase Plan.complete + */ + at Uninterruptible public class SSGCspy extends SS implements GCspyPlan { + + /**************************************************************************** + * + * Class variables + */ + + // The events, BEFORE_COLLECTION, SEMISPACE_COPIED or AFTER_COLLECTION + + /** + * Before a collection has started, + * i.e. before SS.collectionPhase(SS.PREPARE,..). + */ + static final int BEFORE_COLLECTION = 0; + + /** + * After the semispace has been copied and the large object space has been traced + * At this time the Large Object Space has not been swept. + */ + static final int SEMISPACE_COPIED = BEFORE_COLLECTION + 1; + + /** + * The collection is complete, + * i.e. immediately after SS.collectionPhase(SS.RELEASE,..). + * The Large Object Space has been swept. + */ + static final int AFTER_COLLECTION = SEMISPACE_COPIED + 1; + + static int gcspyEvent_ = BEFORE_COLLECTION; + + // The specific drivers for this collector + static LinearSpaceDriver ss0Driver; + static LinearSpaceDriver ss1Driver; + static ImmortalSpaceDriver immortalDriver; + static TreadmillDriver losNurseryDriver; + static TreadmillDriver losDriver; + static TreadmillDriver plosNurseryDriver; + static TreadmillDriver plosDriver; + + private static final boolean DEBUG = false; + + + static { + GCspy.createOptions(); + } + + /** + * Start the server and wait if necessary. + * This method has the following responsibilities. + *

    + *
  1. Create and initialise the GCspy server by calling. + *
    server = ServerInterpreter.init(name, portNumber, verbose);
    + *
  2. Add each event to the ServerInterpreter + *
    server.addEvent(eventID, eventName);
    + *
  3. Set some general information about the server (e.g. name of the collector, build, etc). + *
    server.setGeneralInfo(info); 
    + *
  4. Create new drivers for each component to be visualised. + *
    myDriver = new MyDriver(server, args...);
    + * Drivers extend AbstractDriver and register their spce with the + * ServerInterpreter. In addition to the server, drivers will take as + * arguments the name of the space, the MMTk space, the tilesize, and + * whether this space is to be the main space in the visualiser. + *
+ * + * WARNING: allocates memory. + * @param wait Whether to wait + * @param port The port to talk to the GCspy client (e.g. visualiser) + */ + @Interruptible + public final void startGCspyServer(int port, boolean wait) { + GCspy.server.init("SemiSpaceServerInterpreter", port, true/*verbose*/); + if (DEBUG) Log.writeln("SSGCspy: ServerInterpreter initialised"); + + GCspy.server.addEvent(BEFORE_COLLECTION, "Before collection"); + GCspy.server.addEvent(SEMISPACE_COPIED, "Semispace copied; LOS traced"); + GCspy.server.addEvent(AFTER_COLLECTION, "After collection; LOS swept"); + GCspy.server.setGeneralInfo( + "SSGCspy\n\nRichard Jones, October 2006\\http://www.cs.kent.ac.uk/~rej/"); + if (DEBUG) Log.writeln("SSGCspy: events added to ServerInterpreter"); + + // Initialise each driver + ss0Driver = newLinearSpaceDriver("Semispace 0 Space", copySpace0, true); + ss1Driver = newLinearSpaceDriver("Semispace 1 Space", copySpace1, false); + immortalDriver = new ImmortalSpaceDriver( + GCspy.server, "Immortal Space", immortalSpace, + Options.gcspyTileSize.getValue(), false); + losNurseryDriver = newTreadmillDriver("LOS Nursery", loSpace); + losDriver = newTreadmillDriver("LOS", loSpace); + + if (DEBUG) Log.write("SemiServerInterpreter initialised\n"); + + // Register drivers to allow immortal space to notify direct references + immortalDriver.registerDriversForReferenceNotification( + new AbstractDriver[] {ss0Driver, ss1Driver, immortalDriver, + losNurseryDriver, losDriver, + plosNurseryDriver, plosDriver}); + if (DEBUG) Log.writeln("SSGCspy: registered drivers"); + + gcspyEvent_ = BEFORE_COLLECTION; + + // Start the server + GCspy.server.startServer(wait); + } + + /** + * Create a new LinearSpaceDriver + * TODO is this the best name or should we call it LargeObjectSpaceDriver? + * @param name Name of the space + * @param space The space + * @return A new GCspy driver for this space + */ + @Interruptible + private LinearSpaceDriver newLinearSpaceDriver(String name, CopySpace space, boolean mainSpace) { + // TODO What if tileSize is too small (i.e. too many tiles for GCspy buffer) + // TODO stop the GCspy spaces in the visualiser from fluctuating in size + // so much as we resize them. + return new LinearSpaceDriver(GCspy.server, name, space, + Options.gcspyTileSize.getValue(), mainSpace); + } + + /** + * Create a new TreadmillDriver + * TODO is this the best name or should we call it LargeObjectSpaceDriver? + * @param name Name of the space + * @param space The space + * @return A new GCspy driver for this space + */ + @Interruptible + private TreadmillDriver newTreadmillDriver(String name, LargeObjectSpace space) { + return new TreadmillDriver(GCspy.server, name, space, + Options.gcspyTileSize.getValue(), MAX_NON_LOS_COPY_BYTES, false); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase + */ + @Inline + public void collectionPhase(short phaseId) { + if (DEBUG) { Log.write("--Phase Plan."); Log.writeln(Phase.getName(phaseId)); } + + if (phaseId == SSGCspy.PREPARE) { + super.collectionPhase(phaseId); + gcspySpace.prepare(); + return; + } + + if (phaseId == SSGCspy.RELEASE) { + super.collectionPhase(phaseId); + gcspySpace.release(); + //if (primary) + gcspyGatherData(SSGCspy.AFTER_COLLECTION); + return; + } + + super.collectionPhase(phaseId); + } + + /** + * Gather data for GCspy for the semispaces, the immortal space and the large + * object space. + *

+ * This method sweeps the semispace under consideration to gather data. + * Alternatively and more efficiently, 'used space' can obviously be + * discovered in constant time simply by comparing the start and the end + * addresses of the semispace. However, per-object information can only be + * gathered by sweeping through the space and we do this here for tutorial + * purposes. + * + * @param event + * The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or + * AFTER_COLLECTION + */ + private void gcspyGatherData(int event) { + if(DEBUG) { + Log.writeln("SSGCspy.gcspyGatherData, event=", event); + Log.writeln("SSGCspy.gcspyGatherData, port=", GCspy.getGCspyPort()); + } + + // If port = 0 there can be no GCspy client connected + if (GCspy.getGCspyPort() == 0) + return; + + // This is a safepoint for the server, i.e. it is a point at which + // the server can pause. + // The Mutator is called after the Collector so the Mutator must set the safepoint + if(DEBUG) Log.writeln("SSGCspy safepoint"); + GCspy.server.serverSafepoint(event); + } + + /**************************************************************************** + * + * Accounting + */ + + /** + * Return the number of pages reserved for use given the pending + * allocation. This is exclusive of space reserved for + * copying. + * + * @return The number of pages reserved given the pending + * allocation, excluding space reserved for copying. + */ + public final int getPagesUsed() { + return super.getPagesUsed() + gcspySpace.reservedPages(); + } + + + /** + * Report information on the semispaces + */ + static void reportSpaces() { + Log.write("\n Low semispace: "); + Log.write(SSGCspy.copySpace0.getStart()); + Log.write(" - "); + Log.write(SSGCspy.copySpace0.getStart() + .plus(SSGCspy.copySpace0.getExtent())); + Log.write("\n High semispace: "); + Log.write(SSGCspy.copySpace1.getStart()); + Log.write(" - "); + Log.write(SSGCspy.copySpace1.getStart() + .plus(SSGCspy.copySpace1.getExtent())); + Log.flush(); + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + super.registerSpecializedMethods(); + TransitiveClosure.registerSpecializedScan(SCAN_SS, SSGCspyTraceLocal.class); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,265 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gcspy; + +import org.mmtk.plan.Phase; +import org.mmtk.plan.semispace.SS; +import org.mmtk.plan.semispace.SSCollector; +import org.mmtk.policy.CopySpace; +import org.mmtk.utility.Log; +import org.mmtk.utility.gcspy.GCspy; +import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements per-collector thread behavior and state for the + * SSGCspy plan.

+ * + * See {@link SSGCspy} for an overview of the GC-spy mechanisms.

+ * + * @see SSCollector + * @see SSGCspy + * @see SSGCspyMutator + * @see org.mmtk.plan.StopTheWorldCollector + * @see org.mmtk.plan.CollectorContext + * @see org.mmtk.plan.SimplePhase + */ + at Uninterruptible public class SSGCspyCollector extends SSCollector { + + /**************************************************************************** + * + * Initialization + */ + + /***************************************************************************** + * Instance fields + */ + + private static final boolean DEBUG = false; + + /** + * Constructor + */ + public SSGCspyCollector() { + super(new SSGCspyTraceLocal(global().ssTrace)); + } + + + /**************************************************************************** + * + * Data gathering + */ + + /** + * Perform a (local) collection phase. + * Before a collection, we need to discover + *

    + *
  • the tospace objects copied by the collector in the last GC cycle + *
  • the semispace objects allocated since by the mutator. + *
  • all immortal objects allocated by the mutator + *
  • all large objects allocated by the mutator + *
+ * After the semispace has been copied, we need to discover + *
    + *
  • the tospace objects copied by the collector + *
  • all immortal objects allocated by the mutator + *
  • all large objects allocated by the mutator + *
+ */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (DEBUG) { Log.write("--Phase Collector."); Log.writeln(Phase.getName(phaseId)); } + + //TODO do we need to worry any longer about primary?? + if (phaseId == SS.PREPARE) { + //if (primary) + gcspyGatherData(SSGCspy.BEFORE_COLLECTION); + super.collectionPhase(phaseId, primary); + return; + } + + if (phaseId == SS.FORWARD_FINALIZABLE) { + super.collectionPhase(phaseId, primary); + //if (primary) + gcspyGatherData(SSGCspy.SEMISPACE_COPIED); + return; + } + + if (phaseId == SS.RELEASE) { + //if (primary) + //gcspyGatherData(SSGCspy.SEMISPACE_COPIED); + super.collectionPhase(phaseId, primary); + //if (primary) + gcspyGatherData(SSGCspy.AFTER_COLLECTION); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /** + * Gather data for GCspy for the semispaces only. + *

+ * This method sweeps the semispace under consideration to gather data. + * Alternatively and more efficiently, 'used space' can obviously be + * discovered in constant time simply by comparing the start and the end + * addresses of the semispace. However, per-object information can only be + * gathered by sweeping through the space and we do this here for tutorial + * purposes. + * + * @param event + * The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or + * AFTER_COLLECTION + */ + private void gcspyGatherData(int event) { + if(DEBUG) { + Log.writeln("SSGCspyCollector.gcspyGatherData, event=", event); + Log.writeln("SSGCspyCollector.gcspyGatherData, port=", GCspy.getGCspyPort()); + } + + // If port = 0 there can be no GCspy client connected + if (GCspy.getGCspyPort() == 0) + return; + + // If the server is connected to a client that is interested in this + // event, then we gather data. But first we start a timer to + // compensate for the time spent gathering data here. + if (GCspy.server.isConnected(event)) { + + if (DEBUG) { + if (SSGCspy.hi) + Log.write("\nCollector Examining Lowspace (event ", event); + else + Log.write("\nCollector Examining Highspace (event ", event); + Log.write(")"); + SSGCspy.reportSpaces(); Log.writeln(); + } + + if (event == SSGCspy.BEFORE_COLLECTION) { + if (DEBUG) debugSpaces(SSGCspy.fromSpace()); + + // Just send the old values again + if (DEBUG) { + Log.write("SSGCspyCollector.gcspyGatherData transmit driver, "); + Log.writeln(SSGCspy.fromSpace().getName()); + } + + fromSpaceDriver().transmit(event); + // Mutator.gcspyGatherData follows so leave safepoint to there. + } else if (event == SSGCspy.SEMISPACE_COPIED) { + if (DEBUG) debugSpaces(SSGCspy.toSpace()); + + // We need to reset, scan and send values for tospace + // We'll leave resetting fromspace to AFTER_COLLECTION + if (DEBUG) { + Log.write("SSGCspyCollector.gcspyGatherData reset, gather and transmit driver "); + Log.writeln(SSGCspy.toSpace().getName()); + } + + GCspy.server.startCompensationTimer(); + toSpaceDriver().resetData(); + ss.gcspyGatherData(toSpaceDriver(), SSGCspy.toSpace()); + GCspy.server.stopCompensationTimer(); + toSpaceDriver().transmit(event); + + // We'll leave the safepoint to RELEASE + } else if (event == SSGCspy.AFTER_COLLECTION) { + if (DEBUG) { + Log.write("SSGCspyCollector.gcspyGatherData transmit toSpaceDriver, "); + Log.writeln(SSGCspy.toSpace().getName()); + Log.write("SSGCspyCollector.gcspyGatherData reset fromSpaceDriver, "); + Log.writeln(SSGCspy.fromSpace().getName()); + } + + toSpaceDriver().transmit(event); + + // Here we reset fromspace data + fromSpaceDriver().resetData(); + Address start = SSGCspy.fromSpace().getStart(); + fromSpaceDriver().setRange(start, start); + fromSpaceDriver().transmit(event); + } + + } + // else Log.write("not transmitting..."); + } + + /** + * Print some debugging info + * @param scannedSpace + */ + private void debugSpaces(CopySpace scannedSpace) { + Log.write("SSGCspyCollector.gcspyGatherData: gather data for active semispace "); + Log.write(scannedSpace.getStart()); Log.write("-",ss.getCursor()); Log.flush(); + Log.write(". The space is: "); Log.writeln(ss.getSpace().getName()); + Log.write("scannedSpace is "); Log.writeln(scannedSpace.getName()); + Log.write("The range is "); Log.write(ss.getSpace().getStart()); + Log.write(" to "); Log.writeln(ss.getCursor()); + SSGCspy.reportSpaces(); + } + + /** + * Reset all root streams.

+ */ + void resetRootStreams() { + SSGCspy.ss0Driver.resetRootsStream(); + SSGCspy.ss1Driver.resetRootsStream(); + SSGCspy.immortalDriver.resetRootsStream(); + SSGCspy.losNurseryDriver.resetRootsStream(); + SSGCspy.losDriver.resetRootsStream(); + SSGCspy.plosNurseryDriver.resetRootsStream(); + SSGCspy.plosDriver.resetRootsStream(); + ss.getCursor(); + } + + /** + * Pass a root to all drivers.

+ * @param addr The Address of the object to be checked + */ + protected void checkAllDriversForRootAddress(Address addr) { + if(addr.isZero()) + return; + + SSGCspy.ss0Driver.handleRoot(addr); + SSGCspy.ss1Driver.handleRoot(addr); + SSGCspy.immortalDriver.handleRoot(addr); + SSGCspy.losNurseryDriver.handleRoot(addr); + SSGCspy.losDriver.handleRoot(addr); + SSGCspy.plosNurseryDriver.handleRoot(addr); + SSGCspy.plosDriver.handleRoot(addr); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an SSGCspy instance. */ + @Inline + private static SSGCspy global() { + return (SSGCspy) VM.activePlan.global(); + } + + /** @return the driver for toSpace */ + private LinearSpaceDriver toSpaceDriver() { + return SSGCspy.hi ? SSGCspy.ss1Driver : SSGCspy.ss0Driver; + } + + /** @return the driver for fromSpace */ + private LinearSpaceDriver fromSpaceDriver() { + return SSGCspy.hi ? SSGCspy.ss0Driver : SSGCspy.ss1Driver; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gcspy; + +import org.mmtk.plan.semispace.SSConstraints; +import org.vmmagic.pragma.*; + +/** + * Semi space GCspy constants. + */ + at Uninterruptible +public class SSGCspyConstraints extends SSConstraints { + @Override + public boolean needsLinearScan() { return true; } + @Override + public boolean withGCspy() { return true; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,348 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gcspy; + +import org.mmtk.plan.Phase; +import org.mmtk.plan.semispace.SSMutator; +import org.mmtk.policy.CopySpace; +import org.mmtk.policy.Space; +import org.mmtk.policy.ImmortalLocal; +import org.mmtk.utility.Log; +import org.mmtk.utility.alloc.BumpPointer; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.gcspy.GCspy; +import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior and state for the + * SSGCspy plan. + * + * See {@link SSGCspy} for an overview of the GC-spy mechanisms. + *

+ * + * @see SSMutator + * @see SSGCspy + * @see SSGCspyCollector + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + */ + at Uninterruptible public class SSGCspyMutator extends SSMutator { + + /***************************************************************************** + * Instance fields + */ + + private static final boolean DEBUG = false; + + private static final boolean LOS_TOSPACE = true; // gather from tospace + private static final boolean LOS_FROMSPACE = false; // gather from fromspace + + /** Per-mutator allocator into GCspy's space */ + private BumpPointer gcspy = new ImmortalLocal(SSGCspy.gcspySpace); + + + + /***************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Allocate space (for an object) + * + * @param bytes The size of the space to be allocated (in bytes) + * @param align The requested alignment. + * @param offset The alignment offset. + * @param allocator The allocator number to be used for this allocation + * @param site Allocation site + * @return The address of the first byte of the allocated region + */ + @Inline + public Address alloc(int bytes, int align, int offset, int allocator, int site) { + if (allocator == SSGCspy.ALLOC_GCSPY) + return gcspy.alloc(bytes, align, offset); + else + return super.alloc(bytes, align, offset, allocator, site); + } + + /** + * Perform post-allocation actions. For many allocators none are required. + * + * @param object The newly allocated object + * @param typeRef The type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public void postAlloc(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + if (allocator == SSGCspy.ALLOC_GCSPY) + SSGCspy.gcspySpace.initializeHeader(object); + else + super.postAlloc(object, typeRef, bytes, allocator); + } + + /** + * Return the allocator instance associated with a space + * space, for this plan instance. + * + * @param space The space for which the allocator instance is desired. + * @return The allocator instance associated with this plan instance + * which is allocating into space, or null + * if no appropriate allocator can be established. + */ + public Allocator getAllocatorFromSpace(Space space) { + if (space == SSGCspy.gcspySpace) return gcspy; + return super.getAllocatorFromSpace(space); + } + + /***************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * Before a collection, we need to discover + *

    + *
  • the tospace objects copied by the collector in the last GC cycle + *
  • the ojects allocated since by the mutator. + *
  • all immortal objects allocated by the mutator + *
  • all large objects allocated by the mutator + *
+ * After the semispace has been copied, we need to discover + *
    + *
  • the tospace objects copied by the collector + *
  • all immortal objects allocated by the mutator + *
  • all large objects allocated by the mutator + *
+ */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (DEBUG) { Log.write("--Phase Mutator."); Log.writeln(Phase.getName(phaseId)); } + + // TODO do we need to worry any longer about primary?? + if (phaseId == SSGCspy.PREPARE) { + //if (primary) + gcspyGatherData(SSGCspy.BEFORE_COLLECTION); + super.collectionPhase(phaseId, primary); + return; + } + + if (phaseId == SSGCspy.RELEASE) { + //if (primary) + gcspyGatherData(SSGCspy.SEMISPACE_COPIED); + super.collectionPhase(phaseId, primary); + //if (primary) + gcspyGatherData(SSGCspy.AFTER_COLLECTION); + return; + } + + super.collectionPhase(phaseId, primary); + } + + /** + * Gather data for GCspy for the semispaces, the immortal space and the large + * object space. + *

+ * This method sweeps the semispace under consideration to gather data. + * Alternatively and more efficiently, 'used space' can obviously be + * discovered in constant time simply by comparing the start and the end + * addresses of the semispace. However, per-object information can only be + * gathered by sweeping through the space and we do this here for tutorial + * purposes. + * + * @param event + * The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or + * AFTER_COLLECTION + */ + private void gcspyGatherData(int event) { + if(DEBUG) { + Log.writeln("SSGCspyMutator.gcspyGatherData, event=", event); + Log.writeln("SSGCspyMutator.gcspyGatherData, port=", GCspy.getGCspyPort()); + } + + // If port = 0 there can be no GCspy client connected + if (GCspy.getGCspyPort() == 0) + return; + + // If the server is connected to a client that is interested in this + // event, then we gather data. But first we start a timer to + // compensate for the time spent gathering data here. + if (GCspy.server.isConnected(event)) { + + if (DEBUG) { + if (SSGCspy.hi) + Log.write("\nMutator Examining Lowspace (event ", event); + else + Log.write("\nMutator Examining Highspace (event ", event); + Log.write(")"); + SSGCspy.reportSpaces(); Log.writeln(); + } + + if (event == SSGCspy.BEFORE_COLLECTION) { + // Before the flip + // Mutator has not rebound toSpace yet + GCspy.server.startCompensationTimer(); + + // -- Handle the semispaces + // Here I need to scan newly allocated objects + if (DEBUG) { + //debugSpaces(SSGCspy.fromSpace()); + debugSpaces(SSGCspy.toSpace()); + Log.write("SSGCspyMutator.gcspyGatherData reset, gather and transmit driver "); + //Log.writeln(SSGCspy.fromSpace().getName()); + Log.writeln(SSGCspy.toSpace().getName()); + } + //ss.gcspyGatherData(fromSpaceDriver(), SSGCspy.fromSpace()); + ss.gcspyGatherData(toSpaceDriver(), SSGCspy.toSpace()); + + // -- Handle the immortal space -- + gatherImmortal(event); + + // -- Handle the LOSes + + // reset, collect and scan los data for the nursery and tospace + SSGCspy.losNurseryDriver.resetData(); + los.gcspyGatherData(event, SSGCspy.losNurseryDriver); + SSGCspy.losDriver.resetData(); + los.gcspyGatherData(event, SSGCspy.losDriver, LOS_TOSPACE); + + // transmit the data + GCspy.server.stopCompensationTimer(); + //fromSpaceDriver().transmit(event); + toSpaceDriver().transmit(event); + SSGCspy.immortalDriver.transmit(event); + SSGCspy.losNurseryDriver.transmit(event); + SSGCspy.losDriver.transmit(event); + SSGCspy.plosNurseryDriver.transmit(event); + SSGCspy.plosDriver.transmit(event); + + // As this follows Collector.gcspyGatherData, I'll safepoint here + // This is a safepoint for the server, i.e. it is a point at which + // the server can pause. + GCspy.server.serverSafepoint(event); + } else if (event == SSGCspy.SEMISPACE_COPIED) { + // We have flipped + // toSpace still has not been rebound + + // -- Handle the semispaces + if (DEBUG) { + //debugSpaces(SSGCspy.toSpace()); + debugSpaces(SSGCspy.fromSpace()); + Log.writeln("SSGCspyMutator.gcspyGatherData: do nothing"); + } + + // -- Handle the immortal space -- + GCspy.server.startCompensationTimer(); + gatherImmortal(event); + + // reset, scan and send the los for the nursery and tospace + // and fromspace as well if full heap collection + SSGCspy.losNurseryDriver.resetData(); + los.gcspyGatherData(event, SSGCspy.losNurseryDriver); + SSGCspy.losDriver.resetData(); + los.gcspyGatherData(event, SSGCspy.losDriver, LOS_FROMSPACE); + los.gcspyGatherData(event, SSGCspy.losDriver, LOS_TOSPACE); + + // transmit + GCspy.server.stopCompensationTimer(); + SSGCspy.immortalDriver.transmit(event); + SSGCspy.losNurseryDriver.transmit(event); + SSGCspy.losDriver.transmit(event); + SSGCspy.plosNurseryDriver.transmit(event); + SSGCspy.plosDriver.transmit(event); + + // As this follows Collector.gcspyGatherData, I'll safepoint here + // This is a safepoint for the server, i.e. it is a point at which + // the server can pause. + GCspy.server.serverSafepoint(event); + } else if (event == SSGCspy.AFTER_COLLECTION) { + // We have flipped + // And toSpace has been rebound + + GCspy.server.startCompensationTimer(); + + // -- Handle the semispaces + if (DEBUG) debugSpaces(SSGCspy.toSpace()); + + // -- Handle the immortal space -- + gatherImmortal(event); + + // -- Handle the LOSes + + // reset, scan and send the los + SSGCspy.losNurseryDriver.resetData(); + SSGCspy.losDriver.resetData(); + // no need to scan empty nursery + los.gcspyGatherData(event, SSGCspy.losDriver, LOS_TOSPACE); + + //transmit + GCspy.server.stopCompensationTimer(); + SSGCspy.immortalDriver.transmit(event); + SSGCspy.losNurseryDriver.transmit(event); + SSGCspy.losDriver.transmit(event); + SSGCspy.plosNurseryDriver.transmit(event); + SSGCspy.plosDriver.transmit(event); + + // Reset fromspace + if (DEBUG) { + Log.write("SSGCspyMutator.gcspyGatherData: reset and zero range for driver "); + Log.write(SSGCspy.toSpace().getName()); + } + } + + } + // else Log.write("not transmitting..."); + } + + /** + * Gather data for the immortal space + * @param event + * The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or + * AFTER_COLLECTION + */ + private void gatherImmortal(int event) { + // We want to do this at every GCspy event + if (DEBUG) { + Log.write("SSGCspyMutator.gcspyGatherData: gather data for immortal space "); + Log.write(SSGCspy.immortalSpace.getStart()); Log.writeln("-",immortal.getCursor()); + } + SSGCspy.immortalDriver.resetData(); + immortal.gcspyGatherData(SSGCspy.immortalDriver); + if (DEBUG) Log.writeln("Finished immortal space."); + } + + /** + * Debugging info for the semispaces + * @param scannedSpace the space to output debug for. + */ + private void debugSpaces(CopySpace scannedSpace) { + Log.write("SSGCspyMutator.gcspyGatherData: gather data for active semispace "); + Log.write(scannedSpace.getStart()); Log.write("-",ss.getCursor()); Log.flush(); + Log.write(". The space is: "); Log.writeln(ss.getSpace().getName()); + Log.write("scannedSpace is "); Log.writeln(scannedSpace.getName()); + Log.write("The range is "); Log.write(ss.getSpace().getStart()); + Log.write(" to "); Log.writeln(ss.getCursor()); + SSGCspy.reportSpaces(); + } + + /** @return the driver for toSpace */ + private LinearSpaceDriver toSpaceDriver() { + return SSGCspy.hi ? SSGCspy.ss1Driver : SSGCspy.ss0Driver; + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,70 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gcspy; + +import org.mmtk.plan.Trace; +import org.mmtk.plan.semispace.SSTraceLocal; +import org.mmtk.policy.Space; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implments the core functionality for a transitive + * closure over the heap graph. + */ + at Uninterruptible +public final class SSGCspyTraceLocal extends SSTraceLocal { + /** + * Constructor + */ + public SSGCspyTraceLocal(Trace trace) { + super(trace); + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(SSGCspy.GCSPY, object)) + return SSGCspy.gcspySpace.traceObject(this, object); + return super.traceObject(object); + } + + /** + * Will this object move from this point on, during the current trace ? + * + * @param object The object to query. + * @return True if the object will not move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (Space.isInSpace(SSGCspy.GCSPY, object)) + return true; + return super.willNotMoveInCurrentCollection(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,208 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gctrace; + +import org.mmtk.plan.semispace.*; +import org.mmtk.policy.RawPageSpace; +import org.mmtk.utility.deque.SortTODSharedDeque; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.TraceGenerator; +import org.mmtk.utility.options.Options; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This plan has been modified slightly to perform the processing necessary + * for GC trace generation. To maximize performance, it attempts to remain + * as faithful as possible to semiSpace/Plan.java. + * + * The generated trace format is as follows: + * B 345678 12 + * (Object 345678 was created in the boot image with a size of 12 bytes) + * U 59843 234 47298 + * (Update object 59843 at the slot at offset 234 to refer to 47298) + * S 1233 12345 + * (Update static slot 1233 to refer to 12345) + * T 4567 78924 + * (The TIB of 4567 is set to refer to 78924) + * D 342789 + * (Object 342789 became unreachable) + * A 6860 24 346648 3 + * (Object 6860 was allocated, requiring 24 bytes, with fp 346648 on + * thread 3; this allocation has perfect knowledge) + * a 6884 24 346640 5 + * (Object 6864 was allocated, requiring 24 bytes, with fp 346640 on + * thread 5; this allocation DOES NOT have perfect knowledge) + * I 6860 24 346648 3 + * (Object 6860 was allocated into immortal space, requiring 24 bytes, + * with fp 346648 on thread 3; this allocation has perfect knowledge) + * i 6884 24 346640 5 + * (Object 6864 was allocated into immortal space, requiring 24 bytes, + * with fp 346640 on thread 5; this allocation DOES NOT have perfect + * knowledge) + * 48954->[345]LObject;:blah()V:23 Ljava/lang/Foo; + * (Citation for: a) where the was allocated, fp of 48954, + * at the method with ID 345 -- or void Object.blah() -- and bytecode + * with offset 23; b) the object allocated is of type java.lang.Foo) + * D 342789 361460 + * (Object 342789 became unreachable after 361460 was allocated) + * + * This class implements a simple semi-space collector. See the Jones + * & Lins GC book, section 2.2 for an overview of the basic + * algorithm. This implementation also includes a large object space + * (LOS), and an uncollected "immortal" space.

+ * + * All plans make a clear distinction between global and + * thread-local activities. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. Instances of Plan map 1:1 to "kernel + * threads" (aka CPUs). Thus instance + * methods allow fast, unsychronized access to Plan utilities such as + * allocation and collection. Each instance rests on static resources + * (such as memory and virtual memory resources) which are "global" + * and therefore "static" members of Plan. This mapping of threads to + * instances is crucial to understanding the correctness and + * performance proprties of this plan. + */ + at Uninterruptible public class GCTrace extends SS { + + /**************************************************************************** + * + * Class variables + */ + + /* Spaces */ + public static final RawPageSpace traceSpace = new RawPageSpace("trace", DEFAULT_POLL_FREQUENCY, VMRequest.create()); + public static final int TRACE = traceSpace.getDescriptor(); + + /* GC state */ + public static boolean lastGCWasTracing = false; // True when previous GC was for tracing + public static boolean traceInducedGC = false; // True if trace triggered GC + public static boolean deathScan = false; + public static boolean finalDead = false; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public GCTrace() { + SortTODSharedDeque workList = new SortTODSharedDeque("workList",traceSpace, 1); + SortTODSharedDeque traceBuf = new SortTODSharedDeque("traceBuf",traceSpace, 1); + workList.prepareNonBlocking(); + traceBuf.prepareNonBlocking(); + TraceGenerator.init(workList, traceBuf); + } + + /** + * The postBoot method is called by the runtime immediately after + * command-line arguments are available. + */ + @Interruptible + public void postBoot() { + Options.noFinalizer.setValue(true); + } + + /** + * The planExit method is called at RVM termination to allow the + * trace process to finish. + */ + @Interruptible + public final void notifyExit(int value) { + super.notifyExit(value); + finalDead = true; + traceInducedGC = false; + deathScan = true; + TraceGenerator.notifyExit(value); + } + + /** + * This method controls the triggering of a GC. It is called periodically + * during allocation. Returns true to trigger a collection. + * + * @param spaceFull Space request failed, must recover pages within 'space'. + * @return True if a collection is requested by the plan. + */ + public final boolean collectionRequired(boolean spaceFull) { + if (super.collectionRequired(spaceFull)) { + traceInducedGC = false; + return true; + } + return false; + } + + /**************************************************************************** + * + * Collection + */ + + public void collectionPhase(short phaseId) { + if (phaseId == PREPARE) { + lastGCWasTracing = traceInducedGC; + } + if (phaseId == RELEASE) { + if (traceInducedGC) { + /* Clean up following a trace-induced scan */ + deathScan = false; + } else { + /* Finish the collection by calculating the unreachable times */ + deathScan = true; + TraceGenerator.postCollection(); + deathScan = false; + /* Perform the semispace collections. */ + super.collectionPhase(phaseId); + } + } else if (!traceInducedGC || + (phaseId == INITIATE) || + (phaseId == PREPARE_STACKS) || + (phaseId == ROOTS) || + (phaseId == STACK_ROOTS) || + (phaseId == COMPLETE)) { + /* Performing normal GC; sponge off of parent's work. */ + super.collectionPhase(phaseId); + } + } + + + /**************************************************************************** + * + * Space management + */ + + /** + * @return Since trace induced collections are not called to free up memory, + * their failure to return memory isn't cause for concern. + */ + public boolean isLastGCFull() { + return !lastGCWasTracing; + } + + /** + * @return the active PlanLocal as a GCTraceLocal + */ + public static GCTraceCollector local() { + return ((GCTraceCollector) VM.activePlan.collector()); + } + + /** + * @return the active Plan as a GCTrace + */ + public static GCTrace global() { + return ((GCTrace) VM.activePlan.global()); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,108 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gctrace; + +import org.mmtk.plan.*; +import org.mmtk.plan.semispace.*; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + + +/** + * This class implements per-collector thread behavior and state for the + * GCTrace plan, which implements a GC tracing algorithm.

+ * + * Specifically, this class defines SS collection behavior + * (through inducedTrace and the collectionPhase + * method), and collection-time allocation (copying of objects).

+ * + * See {@link GCTrace} for an overview of the GC trace algorithm.

+ * + * @see SSCollector + * @see GCTrace + * @see GCTraceMutator + * @see org.mmtk.plan.StopTheWorldCollector + * @see org.mmtk.plan.CollectorContext + */ + at Uninterruptible public class GCTraceCollector extends SSCollector { + /**************************************************************************** + * Instance fields + */ + protected final GCTraceTraceLocal inducedTrace; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public GCTraceCollector() { + inducedTrace = new GCTraceTraceLocal(global().ssTrace); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + public void collectionPhase(short phaseId, boolean primary) { + if (phaseId == GCTrace.CLOSURE) { + inducedTrace.completeTrace(); + return; + } + + if (phaseId == GCTrace.RELEASE) { + inducedTrace.release(); + if (!GCTrace.traceInducedGC) { + super.collectionPhase(phaseId, primary); + } + return; + } + + /* fall through case */ + if (!GCTrace.traceInducedGC || + ((phaseId != StopTheWorld.SOFT_REFS) && + (phaseId != StopTheWorld.WEAK_REFS) && + (phaseId != StopTheWorld.PHANTOM_REFS) && + (phaseId != StopTheWorld.FINALIZABLE) && + (phaseId != SS.PREPARE))) { + // Delegate up. + super.collectionPhase(phaseId, primary); + } + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as a GCTrace instance. */ + @Inline + private static GCTrace global() { + return (GCTrace) VM.activePlan.global(); + } + + /** @return The current trace instance */ + public TraceLocal getCurrentTrace() { + return inducedTrace; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gctrace; + +import org.mmtk.plan.semispace.SSConstraints; + +import org.vmmagic.pragma.*; + +/** + * GCTrace constants. + */ + at Uninterruptible +public class GCTraceConstraints extends SSConstraints { + @Override + public boolean needsWriteBarrier() { return true; } + @Override + public boolean generateGCTrace() { return true; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,180 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gctrace; + +import org.mmtk.plan.semispace.SSMutator; +import org.mmtk.plan.*; +import org.mmtk.utility.TraceGenerator; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements per-mutator thread behavior and state for the + * GCTrace plan, which implements a GC tracing algorithm.

+ * + * Specifically, this class defines SS mutator-time allocation, write + * barriers, and per-mutator collection semantics.

+ * + * See {@link GCTrace} for an overview of the GC trace algorithm.

+ * + * @see SSMutator + * @see GCTrace + * @see GCTraceCollector + * @see org.mmtk.plan.StopTheWorldMutator + * @see org.mmtk.plan.MutatorContext + */ + at Uninterruptible public class GCTraceMutator extends SSMutator { + + /**************************************************************************** + * + * Mutator-time allocation + */ + + /** + * Perform post-allocation actions. For many allocators none are + * required. + * + * @param object The newly allocated object + * @param typeRef the type reference for the instance being created + * @param bytes The size of the space to be allocated (in bytes) + * @param allocator The allocator number to be used for this allocation + */ + @Inline + public final void postAlloc(ObjectReference object, ObjectReference typeRef, + int bytes, int allocator) { + /* Make the trace generator aware of the new object. */ + TraceGenerator.addTraceObject(object, allocator); + + super.postAlloc(object, typeRef, bytes, allocator); + + /* Now have the trace process aware of the new allocation. */ + GCTrace.traceInducedGC = TraceGenerator.MERLIN_ANALYSIS; + TraceGenerator.traceAlloc(allocator == GCTrace.ALLOC_IMMORTAL, object, typeRef, bytes); + GCTrace.traceInducedGC = false; + } + + + /**************************************************************************** + * + * Write barrier. + */ + + /** + * A new reference is about to be created. Take appropriate write + * barrier actions.

+ * + * In this case, we remember the address of the source of the + * pointer if the new reference points into the nursery from + * non-nursery space. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * being modified + * @param mode The mode of the store (eg putfield, putstatic etc) + */ + @Inline + public final void writeBarrier(ObjectReference src, Address slot, + ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + TraceGenerator.processPointerUpdate(mode == PUTFIELD_WRITE_BARRIER, + src, slot, tgt); + VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode); + } + + /** + * Attempt to atomically exchange the value in the given slot + * with the passed replacement value. If a new reference is + * created, we must then take appropriate write barrier actions.

+ * + * By default do nothing, override if appropriate. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param old The old reference to be swapped out + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The context in which the store occured + * @return True if the swap was successful. + */ + @Inline + public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot, + ObjectReference old, ObjectReference tgt, Word metaDataA, + Word metaDataB, int mode) { + boolean result = VM.barriers.tryCompareAndSwapWriteInBarrier(src, slot, old, tgt, metaDataA, metaDataB, mode); + if (result) { + TraceGenerator.processPointerUpdate(mode == PUTFIELD_WRITE_BARRIER, src, slot, tgt); + } + return result; + } + + /** + * A number of references are about to be copied from object + * src to object dst (as in an array + * copy). Thus, dst is the mutated object. Take + * appropriate write barrier actions.

+ * + * @param src The source of the values to be copied + * @param srcOffset The offset of the first source address, in + * bytes, relative to src (in principle, this could be + * negative). + * @param dst The mutated object, i.e. the destination of the copy. + * @param dstOffset The offset of the first destination address, in + * bytes relative to tgt (in principle, this could be + * negative). + * @param bytes The size of the region being copied, in bytes. + * @return True if the update was performed by the barrier, false if + * left to the caller (always false in this case). + */ + public boolean writeBarrier(ObjectReference src, Offset srcOffset, + ObjectReference dst, Offset dstOffset, int bytes) { + /* These names seem backwards, but are defined to be compatable with the + * previous writeBarrier method. */ + Address slot = dst.toAddress().plus(dstOffset); + Address tgtLoc = src.toAddress().plus(srcOffset); + for (int i = 0; i < bytes; i += BYTES_IN_ADDRESS) { + ObjectReference tgt = tgtLoc.loadObjectReference(); + TraceGenerator.processPointerUpdate(false, dst, slot, tgt); + slot = slot.plus(BYTES_IN_ADDRESS); + tgtLoc = tgtLoc.plus(BYTES_IN_ADDRESS); + } + return false; + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary perform any single-threaded local activities. + */ + public void collectionPhase(short phaseId, boolean primary) { + if (!GCTrace.traceInducedGC || + (phaseId != StopTheWorld.PREPARE) && + (phaseId != StopTheWorld.RELEASE)) { + // Delegate up. + super.collectionPhase(phaseId, primary); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,199 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.semispace.gctrace; + +import org.mmtk.plan.Trace; +import org.mmtk.plan.semispace.*; +import org.mmtk.policy.Space; +import org.mmtk.utility.TraceGenerator; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This plan has been modified slightly to perform the processing necessary + * for GC trace generation. To maximize performance, it attempts to remain + * as faithful as possible to semiSpace/Plan.java. + * + * The generated trace format is as follows: + * B 345678 12 + * (Object 345678 was created in the boot image with a size of 12 bytes) + * U 59843 234 47298 + * (Update object 59843 at the slot at offset 234 to refer to 47298) + * S 1233 12345 + * (Update static slot 1233 to refer to 12345) + * T 4567 78924 + * (The TIB of 4567 is set to refer to 78924) + * D 342789 + * (Object 342789 became unreachable) + * A 6860 24 346648 3 + * (Object 6860 was allocated, requiring 24 bytes, with fp 346648 on + * thread 3; this allocation has perfect knowledge) + * a 6884 24 346640 5 + * (Object 6864 was allocated, requiring 24 bytes, with fp 346640 on + * thread 5; this allocation DOES NOT have perfect knowledge) + * I 6860 24 346648 3 + * (Object 6860 was allocated into immortal space, requiring 24 bytes, + * with fp 346648 on thread 3; this allocation has perfect knowledge) + * i 6884 24 346640 5 + * (Object 6864 was allocated into immortal space, requiring 24 bytes, + * with fp 346640 on thread 5; this allocation DOES NOT have perfect + * knowledge) + * 48954->[345]LObject;:blah()V:23 Ljava/lang/Foo; + * (Citation for: a) where the was allocated, fp of 48954, + * at the method with ID 345 -- or void Object.blah() -- and bytecode + * with offset 23; b) the object allocated is of type java.lang.Foo) + * D 342789 361460 + * (Object 342789 became unreachable after 361460 was allocated) + * + * This class implements a simple semi-space collector. See the Jones + * & Lins GC book, section 2.2 for an overview of the basic + * algorithm. This implementation also includes a large object space + * (LOS), and an uncollected "immortal" space.

+ * + * All plans make a clear distinction between global and + * thread-local activities. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. Instances of Plan map 1:1 to "kernel + * threads" (aka CPUs). Thus instance + * methods allow fast, unsychronized access to Plan utilities such as + * allocation and collection. Each instance rests on static resources + * (such as memory and virtual memory resources) which are "global" + * and therefore "static" members of Plan. This mapping of threads to + * instances is crucial to understanding the correctness and + * performance proprties of this plan. + */ + at Uninterruptible +public final class GCTraceTraceLocal extends SSTraceLocal { + + /** + * Constructor + * + * @param trace The global trace to use. + */ + public GCTraceTraceLocal(Trace trace) { + super(trace, false); + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Trace a reference during GC. This involves determining which + * collection policy applies (such as those needed for trace generation) + * and taking the appropriate actions. + * + * @param object The object reference to be traced. In certain + * cases, this should NOT be an interior pointer. + * @return The possibly moved reference. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (GCTrace.traceInducedGC) { + /* We are performing a root scan following an allocation. */ + TraceGenerator.rootEnumerate(object); + return object; + } else if (GCTrace.deathScan) { + /* We are performing the last scan before program termination. */ + TraceGenerator.propagateDeathTime(object); + return object; + } else { + /* *gasp* We are actually performing garbage collection */ + return super.traceObject(object); + } + } + + /** + * Ensure that the referenced object will not move during a collection + * by 'precopying' it at the beginning. + * + * @param object The object to ensure will not move. + */ + @Inline + public ObjectReference precopyObject(ObjectReference object) { + if (object.isNull()) return object; + if (GCTrace.traceInducedGC) { + /* We are performing a root scan following an allocation. */ + TraceGenerator.rootEnumerate(object); + return object; + } else if (GCTrace.deathScan) { + /* We are performing the last scan before program termination. */ + TraceGenerator.propagateDeathTime(object); + return object; + } else { + return super.precopyObject(object); + } + } + + + /** + * If the referenced object has moved, return the new location. + * + * Some copying collectors will need to override this method. + * + * @param object The object which may have been forwarded. + * @return The new location of object. + */ + @Inline + public ObjectReference getForwardedReference(ObjectReference object) { + if (object.isNull()) return object; + if (SS.hi && Space.isInSpace(SS.SS0, object)) { + return SS.copySpace0.traceObject(this, object, GCTrace.ALLOC_SS); + } else if (!SS.hi && Space.isInSpace(SS.SS1, object)) { + return SS.copySpace1.traceObject(this, object, GCTrace.ALLOC_SS); + } + return object; + } + + /** + * Return true if obj is a live object. + * + * @param object The object in question + * @return True if obj is a live object. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + else if (GCTrace.traceInducedGC) return true; + else return super.isLive(object); + } + + /** + * Return true if obj is a reachable object. + * + * @param object The object in question + * @return True if obj is a reachable object; + * unreachable objects may still be live, however + */ + public boolean isReachable(ObjectReference object) { + if (GCTrace.finalDead) return false; + else if (object.isNull()) return false; + else { + Space space = Space.getSpaceForObject(object); + return space.isReachable(object); + } + } + + /** + * Is this object guaranteed not to move during the collection. + * + * @param object The object to check. + * @return True if the object is guaranteed not to move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (GCTrace.traceInducedGC) return true; + else return super.willNotMoveInCurrentCollection(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,237 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyimmix; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.immix.Immix; +import org.mmtk.utility.Log; +import org.mmtk.utility.deque.SharedDeque; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.statistics.BooleanCounter; +import org.mmtk.utility.statistics.Stats; +import org.mmtk.vm.Collection; + +import org.vmmagic.pragma.*; + +/** + * This class implements the global state of a simple sticky mark bits collector, + * based on an immix collector. The sticky mark bits algorithm is + * due to Demmers et al. (http://doi.acm.org/10.1145/96709.96735), and allows + * generational collection to be performed in a non-moving heap by overloading + * the role of mark bits to also indicate whether an object is new (nursery) or + * not. Thus nursery objects are identified by a bit in their header, not by + * where they lie within the address space. While Demmers et al. did their work + * in a conservative collector, here we have an exact collector, so we can use + * a regular write barrier, and don't need to use page protection etc. + * + * See the PLDI'08 paper by Blackburn and McKinley for a description + * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586 + * + * All plans make a clear distinction between global and + * thread-local activities, and divides global and local state + * into separate class hierarchies. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. There is a single instance of Plan (or the + * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel + * threads" (aka CPUs or in Jikes RVM, Processors). Thus instance + * methods of PlanLocal allow fast, unsychronized access to functions such as + * allocation and collection. + * + * The global instance defines and manages static resources + * (such as memory and virtual memory resources). This mapping of threads to + * instances is crucial to understanding the correctness and + * performance properties of MMTk plans. + */ + at Uninterruptible +public class StickyImmix extends Immix { + + /**************************************************************************** + * Constants + */ + /** If true, then new PLOS objects are collected at each nursery GC */ + static final boolean NURSERY_COLLECT_PLOS = true; + /** If true then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */ + static final boolean MAJOR_GC_ONLY = false; + /** estimated collection yield */ + protected static final float SURVIVAL_ESTIMATE = (float) 0.8; + + public static int SCAN_NURSERY = 2; + + /**************************************************************************** + * Class variables + */ + private static int lastCommittedImmixPages = 0; + + /* statistics */ + public static BooleanCounter fullHeap = new BooleanCounter("majorGC", true, true); + + /**************************************************************************** + * Instance variables + */ + /* Remset pool */ + public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1); + + /** + * Constructor. + * + */ + public StickyImmix() { + collectWholeHeap = nextGCWholeHeap = false; + } + + /***************************************************************************** + * + * Collection + */ + + /** + * A user-triggered GC has been initiated. + */ + public void userTriggeredGC() { + nextGCWholeHeap |= Options.fullHeapSystemGC.getValue(); + } + + /** + * Force the next collection to be full heap. + */ + @Override + public void forceFullHeapCollection() { + nextGCWholeHeap = true; + } + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase to execute. + */ + @Inline + @Override + public final void collectionPhase(short phaseId) { + + if (phaseId == SET_COLLECTION_KIND) { + collectWholeHeap = requiresFullHeapCollection(); + if (Stats.gatheringStats() && collectWholeHeap) fullHeap.set(); + super.collectionPhase(phaseId); + return; + } + + if (!collectWholeHeap && phaseId == PREPARE) { + immixTrace.prepare(); + immixSpace.prepare(false); + return; + } + + if (phaseId == RELEASE) { + if (collectWholeHeap) { + super.collectionPhase(RELEASE); + } else { + immixTrace.release(); + lastGCWasDefrag = immixSpace.release(false); + } + modPool.reset(); + lastCommittedImmixPages = immixSpace.committedPages(); + nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery()); + return; + } + + super.collectionPhase(phaseId); + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * This method controls the triggering of a GC. It is called periodically + * during allocation. Returns true to trigger a collection. + * + * @param spaceFull Space request failed, must recover pages within 'space'. + * @return True if a collection is requested by the plan. + */ + public final boolean collectionRequired(boolean spaceFull) { + boolean nurseryFull = immixSpace.getPagesAllocated() > Options.nurserySize.getMaxNursery(); + return super.collectionRequired(spaceFull) || nurseryFull; + } + + /** + * Determine whether this GC should be a full heap collection. + * + * @return True if this GC should be a full heap collection. + */ + protected boolean requiresFullHeapCollection() { + if (collectionTrigger == Collection.EXTERNAL_GC_TRIGGER && Options.fullHeapSystemGC.getValue()) { + return true; + } + if (nextGCWholeHeap || collectionAttempt > 1) { + // Forces full heap collection + return true; + } + if (loSpace.allocationFailed()) { + // We need space from the nursery + return true; + } + + // Estimate the yield from small nursery pages + int smallNurseryPages = immixSpace.committedPages() - lastCommittedImmixPages; + int smallNurseryYield = (int)(smallNurseryPages * SURVIVAL_ESTIMATE); + + if (smallNurseryYield < getPagesRequired()) { + // Our total yield is insufficient. + return true; + } + + if (immixSpace.allocationFailed()) { + if (smallNurseryYield < immixSpace.requiredPages()) { + // We have run out of VM pages in the nursery + return true; + } + } + + return false; + } + + /** + * Print pre-collection statistics. In this class we prefix the output + * indicating whether the collection was full heap or not. + */ + @Override + public void printPreStats() { + if ((Options.verbose.getValue() >= 1) && (collectWholeHeap)) + Log.write("[Full heap]"); + super.printPreStats(); + } + + /** + * @return Is current GC only collecting objects allocated since last GC. + */ + public final boolean isCurrentGCNursery() { + return !collectWholeHeap; + } + + /** + * @return Is last GC a full collection? + */ + public final boolean isLastGCFull() { + return collectWholeHeap; + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyImmixNurseryTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,127 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyimmix; + +import org.mmtk.plan.*; +import org.mmtk.plan.immix.Immix; +import org.mmtk.plan.immix.ImmixCollector; +import org.mmtk.plan.immix.ImmixDefragTraceLocal; +import org.mmtk.plan.immix.ImmixTraceLocal; +import org.mmtk.policy.immix.CollectorLocal; +import org.mmtk.utility.alloc.ImmixAllocator; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements per-collector thread behavior + * and state for the StickMS plan, which implements a generational + * sticky mark bits immix collector.

+ * + * Specifically, this class defines StickyMS collection behavior + * (through trace and the collectionPhase + * method).

+ * + * @see StickyImmix for an overview of the algorithm.

+ * @see StickyImmixMutator + * @see StopTheWorldCollector + * @see CollectorContext + * @see Phase + */ + at Uninterruptible +public class StickyImmixCollector extends ImmixCollector { + + /**************************************************************************** + * Instance fields + */ + private StickyImmixNurseryTraceLocal nurseryTrace; + private final ImmixAllocator nurseryCopy; + + /**************************************************************************** + * Initialization + */ + + /** + * Constructor + */ + public StickyImmixCollector() { + ObjectReferenceDeque modBuffer = new ObjectReferenceDeque("mod buffer", global().modPool); + fastTrace = new ImmixTraceLocal(global().immixTrace, modBuffer); + defragTrace = new ImmixDefragTraceLocal(global().immixTrace, modBuffer); + nurseryTrace = new StickyImmixNurseryTraceLocal(global().immixTrace, modBuffer); + immix = new CollectorLocal(StickyImmix.immixSpace); + nurseryCopy = new ImmixAllocator(Immix.immixSpace, true, true); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + boolean collectWholeHeap = global().collectWholeHeap; + + if (phaseId == StickyImmix.PREPARE) { + global().modPool.prepareNonBlocking(); /* always do this */ + } + + if (!collectWholeHeap) { + if (phaseId == StickyImmix.PREPARE) { + currentTrace = (TraceLocal) nurseryTrace; + immix.prepare(false); + nurseryTrace.prepare(); + nurseryCopy.reset(); + copy.reset(); + return; + } + + if (phaseId == StickyImmix.ROOTS) { + VM.scanning.computeStaticRoots(currentTrace); + VM.scanning.computeGlobalRoots(currentTrace); + return; + } + + if (phaseId == StickyImmix.CLOSURE) { + nurseryTrace.completeTrace(); + return; + } + + if (phaseId == StickyImmix.RELEASE) { + nurseryTrace.release(); + immix.release(false); + global().modPool.reset(); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an StickyImmix instance. */ + private static StickyImmix global() { + return (StickyImmix) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,55 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyimmix; + +import static org.mmtk.policy.immix.ImmixConstants.MAX_IMMIX_OBJECT_BYTES; + +import org.mmtk.plan.immix.ImmixConstraints; + +import org.mmtk.policy.MarkSweepSpace; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Word; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class StickyImmixConstraints extends ImmixConstraints { + /** @return The number of specialized scans. We need nursery & full heap. */ + @Override + public int numSpecializedScans() { return 3; } + + /** @return True if this plan requires a write barrier */ + @Override + public boolean needsWriteBarrier() { return true; } + + /** @return True if this Plan requires a header bit for object logging */ + @Override + public boolean needsLogBitInHeader() { return true; } + + /** @return A bit which represents that a header is unlogged */ + @Override + public Word unloggedBit() {return MarkSweepSpace.UNLOGGED_BIT; } + + /** @return Size (in bytes) beyond which new regular objects must be allocated to the LOS */ + @Override + public int maxNonLOSDefaultAllocBytes() { return MAX_IMMIX_OBJECT_BYTES; } + + /** @return Size (in bytes) beyond which copied objects must be copied to the LOS */ + @Override + public int maxNonLOSCopyBytes() { return MAX_IMMIX_OBJECT_BYTES; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,201 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyimmix; + +import org.mmtk.plan.*; +import org.mmtk.plan.immix.ImmixMutator; + +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior + * and state for the StickyImmix plan, which implements a + * generational mark-sweep collector.

+ * + * Specifically, this class defines MS mutator-time allocation + * and per-mutator thread collection semantics (flushing and restoring + * per-mutator allocator state).

+ * * + * @see StickyImmix + * @see StickyImmixCollector + * @see MutatorContext + * @see Phase + */ + at Uninterruptible +public class StickyImmixMutator extends ImmixMutator { + + /**************************************************************************** + * Instance fields + */ + + private ObjectReferenceDeque modBuffer; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public StickyImmixMutator() { + super(); + modBuffer = new ObjectReferenceDeque("mod buf", global().modPool); + } + + /**************************************************************************** + * + * Barriers + */ + + /** + * A new reference is about to be created. Take appropriate write + * barrier actions.

+ * + * In this case, we remember the address of the source of the + * pointer if the new reference points into the nursery from + * non-nursery space. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The mode of the store (eg putfield, putstatic etc) + */ + @Inline + public final void writeBarrier(ObjectReference src, Address slot, + ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) { + if (Plan.logRequired(src)) + logSource(src); + VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode); + } + + /** + * A number of references are about to be copied from object + * src to object dst (as in an array + * copy). Thus, dst is the mutated object. Take + * appropriate write barrier actions.

+ * + * In this case, we remember the mutated source address range and + * will scan that address range at GC time. + * + * @param src The source of the values to copied + * @param srcOffset The offset of the first source address, in + * bytes, relative to src (in principle, this could be + * negative). + * @param dst The mutated object, i.e. the destination of the copy. + * @param dstOffset The offset of the first destination address, in + * bytes relative to tgt (in principle, this could be + * negative). + * @param bytes The size of the region being copied, in bytes. + * @return True if the update was performed by the barrier, false if + * left to the caller (always false in this case). + */ + @Inline + public final boolean writeBarrier(ObjectReference src, Offset srcOffset, + ObjectReference dst, Offset dstOffset, int bytes) { + if (Plan.logRequired(src)) + logSource(src); + return false; + } + + /** + * Add an object to the modified objects buffer and mark the + * object has having been logged. Since duplicate entries do + * not raise any correctness issues, we do not worry + * about synchronization and allow threads to race to log the + * object, potentially including it twice (unlike reference + * counting where duplicates would lead to incorrect reference + * counts). + * + * @param src The object to be logged + */ + private void logSource(ObjectReference src) { + Plan.markAsLogged(src); + modBuffer.push(src); + } + + /** + * Flush per-mutator remembered sets into the global remset pool. + */ + public final void flushRememberedSets() { + modBuffer.flushLocal(); + assertRemsetFlushed(); + } + + /** + * Assert that the remsets have been flushed. This is critical to + * correctness. We need to maintain the invariant that remset entries + * do not accrue during GC. If the host JVM generates barrier entires + * it is its own responsibility to ensure that they are flushed before + * returning to MMTk. + */ + public final void assertRemsetFlushed() { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(modBuffer.isFlushed()); + } + } + + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == StickyImmix.PREPARE) { + flushRememberedSets(); + } + if (phaseId == StickyImmix.RELEASE) { + assertRemsetFlushed(); + } + + if (!global().collectWholeHeap) { + if (phaseId == StickyImmix.PREPARE) { + immix.prepare(); + return; + } + + if (phaseId == StickyImmix.RELEASE) { + immix.release(); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an MSGen instance. */ + @Inline + private static StickyImmix global() { + return (StickyImmix) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,143 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyimmix; + +import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME; +import static org.mmtk.policy.immix.ImmixConstants.TMP_PREFER_COPY_ON_NURSERY_GC; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local functionality for a transitive + * closure over a sticky-immix space. + */ + at Uninterruptible +public final class StickyImmixNurseryTraceLocal extends TraceLocal { + + /**************************************************************************** + * + * Instance fields. + */ + private final ObjectReferenceDeque modBuffer; + + /** + * Constructor + */ + public StickyImmixNurseryTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) { + super(StickyImmix.SCAN_NURSERY, trace); + this.modBuffer = modBuffer; + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(StickyImmix.IMMIX, object)) + return TMP_PREFER_COPY_ON_NURSERY_GC ? StickyImmix.immixSpace.copyNurseryIsLive(object) : StickyImmix.immixSpace.fastIsLive(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(super.isLive(object)); + return true; + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * msSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(StickyImmix.IMMIX, object)) + return StickyImmix.immixSpace.nurseryTraceObject(this, object, StickyImmix.ALLOC_DEFAULT); + else + return object; + } + + /** + * Return true if this object is guaranteed not to move during this + * collection (i.e. this object is definitely not an unforwarded + * object). + * + * @param object + * @return True if this object is guaranteed not to move during this + * collection. + */ + @Override + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + if (Space.isInSpace(StickyImmix.IMMIX, object)) { + if (!TMP_PREFER_COPY_ON_NURSERY_GC) + return true; + else + return StickyImmix.immixSpace.willNotMoveThisNurseryGC(object); + } + return super.willNotMoveInCurrentCollection(object); + } + + /** + * Collectors that move objects must override this method. + * It performs the deferred scanning of objects which are forwarded + * during bootstrap of each copying collection. Because of the + * complexities of the collection bootstrap (such objects are + * generally themselves gc-critical), the forwarding and scanning of + * the objects must be dislocated. It is an error for a non-moving + * collector to call this method. + * + * @param object The forwarded object to be scanned + */ + @Inline + @Override + protected void scanObject(ObjectReference object) { + super.scanObject(object); + if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(StickyImmix.IMMIX, object)) + StickyImmix.immixSpace.markLines(object); + } + + /** + * Process any remembered set entries. This means enumerating the + * mod buffer and for each entry, marking the object as unlogged + * and enqueing it for scanning. + */ + protected void processRememberedSets() { + logMessage(2, "processing modBuffer"); + while (!modBuffer.isEmpty()) { + ObjectReference src = modBuffer.pop(); + Plan.markAsUnlogged(src); + processNode(src); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,206 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyms; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.plan.marksweep.MS; +import org.mmtk.policy.Space; +import org.mmtk.utility.Log; +import org.mmtk.utility.deque.SharedDeque; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.sanitychecker.SanityChecker; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements the global state of a simple sticky mark bits collector, + * based a simple on mark-sweep collector. The sticky mark bits algorithm is + * due to Demmers et al. (http://doi.acm.org/10.1145/96709.96735), and allows + * generational collection to be performed in a non-moving heap by overloading + * the role of mark bits to also indicate whether an object is new (nursery) or + * not. Thus nursery objects are identified by a bit in their header, not by + * where they lie within the address space. While Demmers et al. did their work + * in a conservative collector, here we have an exact collector, so we can use + * a regular write barrier, and don't need to use page protection etc. + * + * All plans make a clear distinction between global and + * thread-local activities, and divides global and local state + * into separate class hierarchies. Global activities must be + * synchronized, whereas no synchronization is required for + * thread-local activities. There is a single instance of Plan (or the + * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel + * threads" (aka CPUs or in Jikes RVM, Processors). Thus instance + * methods of PlanLocal allow fast, unsychronized access to functions such as + * allocation and collection. + * + * The global instance defines and manages static resources + * (such as memory and virtual memory resources). This mapping of threads to + * instances is crucial to understanding the correctness and + * performance properties of MMTk plans. + */ + at Uninterruptible +public class StickyMS extends MS { + + /**************************************************************************** + * Constants + */ + /** If true, then new PLOS objects are collected at each nursery GC */ + static final boolean NURSERY_COLLECT_PLOS = true; + /** If true then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */ + static final boolean MAJOR_GC_ONLY = false; + + /**************************************************************************** + * Class variables + */ + + public static int SCAN_NURSERY = 1; + + /**************************************************************************** + * Instance variables + */ + /* status fields */ + /** will the next collection collect the whole heap? */ + public boolean nextGCWholeHeap = false; + /** will this collection collect the whole heap */ + public boolean collectWholeHeap = nextGCWholeHeap; + + /* Remset pool */ + public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1); + + /**************************************************************************** + * Static initialization + */ + { + msSpace.isAgeSegregatedSpace(); /* this space is to be collected generationally */ + } + + /***************************************************************************** + * + * Collection + */ + + /** + * A user-triggered GC has been initiated. + */ + public void userTriggeredGC() { + nextGCWholeHeap |= Options.fullHeapSystemGC.getValue(); + } + + /** + * Force the next collection to be full heap. + */ + @Override + public void forceFullHeapCollection() { + nextGCWholeHeap = true; + } + + /** + * Perform a (global) collection phase. + * + * @param phaseId Collection phase to execute. + */ + @Inline + @Override + public final void collectionPhase(short phaseId) { + + if (phaseId == INITIATE) { + collectWholeHeap = MAJOR_GC_ONLY || emergencyCollection || nextGCWholeHeap; + nextGCWholeHeap = false; + super.collectionPhase(phaseId); + return; + } + + if (!collectWholeHeap) { + if (phaseId == PREPARE) { + msTrace.prepare(); + msSpace.prepare(false); + return; + } + + if (phaseId == RELEASE) { + msTrace.release(); + msSpace.release(); + modPool.reset(); + nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery()); + return; + } + } + + super.collectionPhase(phaseId); + } + + /***************************************************************************** + * + * Accounting + */ + + /** + * Print pre-collection statistics. In this class we prefix the output + * indicating whether the collection was full heap or not. + */ + @Override + public void printPreStats() { + if ((Options.verbose.getValue() >= 1) && (collectWholeHeap)) + Log.write("[Full heap]"); + super.printPreStats(); + } + + /** + * @return Is current GC only collecting objects allocated since last GC. + */ + public final boolean isCurrentGCNursery() { + return !collectWholeHeap; + } + + /** + * @return Is last GC a full collection? + */ + public final boolean isLastGCFull() { + return collectWholeHeap; + } + + /** + * Return the expected reference count. For non-reference counting + * collectors this becomes a true/false relationship. + * @param object The object to check. + * @param sanityRootRC The number of root references to the object. + * + * @return The expected (root excluded) reference count. + */ + public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { + Space space = Space.getSpaceForObject(object); + + // Immortal spaces + if (space == StickyMS.immortalSpace || space == StickyMS.vmSpace) { + return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD; + } + + // Mature space (nursery collection) + if (VM.activePlan.global().isCurrentGCNursery() && space != StickyMS.msSpace) { + return SanityChecker.UNSURE; + } + + return super.sanityExpectedRC(object, sanityRootRC); + } + + /** + * Register specialized methods. + */ + @Interruptible + protected void registerSpecializedMethods() { + TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyMSNurseryTraceLocal.class); + super.registerSpecializedMethods(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,116 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyms; + +import org.mmtk.plan.*; +import org.mmtk.plan.marksweep.MSCollector; +import org.mmtk.plan.marksweep.MSTraceLocal; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements per-collector thread behavior + * and state for the StickMS plan, which implements a generational + * sticky mark bits mark-sweep collector.

+ * + * Specifically, this class defines StickyMS collection behavior + * (through trace and the collectionPhase + * method).

+ * + * @see StickyMS for an overview of the algorithm.

+ * @see StickyMSMutator + * @see StopTheWorldCollector + * @see CollectorContext + * @see Phase + */ + at Uninterruptible +public class StickyMSCollector extends MSCollector { + + /**************************************************************************** + * Instance fields + */ + private StickyMSNurseryTraceLocal nurseryTrace; + + /**************************************************************************** + * Initialization + */ + + /** + * Constructor + */ + public StickyMSCollector() { + ObjectReferenceDeque modBuffer = new ObjectReferenceDeque("mod buffer", global().modPool); + fullTrace = new MSTraceLocal(global().msTrace, modBuffer); + nurseryTrace = new StickyMSNurseryTraceLocal(global().msTrace, modBuffer); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-collector collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + boolean collectWholeHeap = global().collectWholeHeap; + + if (phaseId == StickyMS.PREPARE) { + currentTrace = collectWholeHeap ? (TraceLocal) fullTrace : (TraceLocal) nurseryTrace; + global().modPool.prepareNonBlocking(); /* always do this */ + } + + if (!collectWholeHeap) { + if (phaseId == StickyMS.PREPARE) { + nurseryTrace.prepare(); + return; + } + + if (phaseId == StickyMS.ROOTS) { + VM.scanning.computeStaticRoots(currentTrace); + VM.scanning.computeGlobalRoots(currentTrace); + return; + } + + if (phaseId == StickyMS.CLOSURE) { + nurseryTrace.completeTrace(); + return; + } + + if (phaseId == StickyMS.RELEASE) { + nurseryTrace.release(); + global().modPool.reset(); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an MS instance. */ + @Inline + private static StickyMS global() { + return (StickyMS) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,48 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyms; + +import org.mmtk.plan.marksweep.MSConstraints; + +import org.mmtk.policy.MarkSweepSpace; +import org.mmtk.policy.SegregatedFreeListSpace; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Word; + +/** + * This class and its subclasses communicate to the host VM/Runtime + * any features of the selected plan that it needs to know. This is + * separate from the main Plan/PlanLocal class in order to bypass any + * issues with ordering of static initialization. + */ + at Uninterruptible +public class StickyMSConstraints extends MSConstraints { + /** @return The number of specialized scans. We need nursery & full heap. */ + @Override + public int numSpecializedScans() { return 2; } + + /** @return True if this plan requires a write barrier */ + @Override + public boolean needsWriteBarrier() { return true; } + + /** @return True if this Plan requires a header bit for object logging */ + @Override + public boolean needsLogBitInHeader() { return true; } + + /** @return A bit which represents that a header is unlogged */ + @Override + public Word unloggedBit() {return MarkSweepSpace.UNLOGGED_BIT; } + @Override + public int maxNonLOSDefaultAllocBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,213 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyms; + +import org.mmtk.plan.*; +import org.mmtk.plan.marksweep.MSMutator; +import org.mmtk.policy.MarkSweepLocal; + +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements per-mutator thread behavior + * and state for the StickyMS plan, which implements a + * generational mark-sweep collector.

+ * + * Specifically, this class defines MS mutator-time allocation + * and per-mutator thread collection semantics (flushing and restoring + * per-mutator allocator state).

+ * * + * @see StickyMS + * @see StickyMSCollector + * @see MutatorContext + * @see Phase + */ + at Uninterruptible +public class StickyMSMutator extends MSMutator { + + /**************************************************************************** + * Instance fields + */ + + private ObjectReferenceDeque modBuffer; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public StickyMSMutator() { + ms = new MarkSweepLocal(StickyMS.msSpace); + modBuffer = new ObjectReferenceDeque("mod buf", global().modPool); + } + + /**************************************************************************** + * + * Barriers + */ + + /** + * A new reference is about to be created. Take appropriate write + * barrier actions.

+ * + * In this case, we remember the address of the source of the + * pointer if the new reference points into the nursery from + * non-nursery space. + * + * @param src The object into which the new reference will be stored + * @param slot The address into which the new reference will be + * stored. + * @param tgt The target of the new reference + * @param metaDataA A value that assists the host VM in creating a store + * @param metaDataB A value that assists the host VM in creating a store + * @param mode The mode of the store (eg putfield, putstatic etc) + */ + @Inline + public final void writeBarrier(ObjectReference src, Address slot, + ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) { + if (Plan.logRequired(src)) + logSource(src); + VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode); + } + + /** + * A number of references are about to be copied from object + * src to object dst (as in an array + * copy). Thus, dst is the mutated object. Take + * appropriate write barrier actions.

+ * + * In this case, we remember the mutated source address range and + * will scan that address range at GC time. + * + * @param src The source of the values to copied + * @param srcOffset The offset of the first source address, in + * bytes, relative to src (in principle, this could be + * negative). + * @param dst The mutated object, i.e. the destination of the copy. + * @param dstOffset The offset of the first destination address, in + * bytes relative to tgt (in principle, this could be + * negative). + * @param bytes The size of the region being copied, in bytes. + * @return True if the update was performed by the barrier, false if + * left to the caller (always false in this case). + */ + @Inline + public final boolean writeBarrier(ObjectReference src, Offset srcOffset, + ObjectReference dst, Offset dstOffset, int bytes) { + if (Plan.logRequired(src)) + logSource(src); + return false; + } + + /** + * Add an object to the modified objects buffer and mark the + * object has having been logged. Since duplicate entries do + * not raise any correctness issues, we do not worry + * about synchronization and allow threads to race to log the + * object, potentially including it twice (unlike reference + * counting where duplicates would lead to incorrect reference + * counts). + * + * @param src The object to be logged + */ + private void logSource(ObjectReference src) { + Plan.markAsLogged(src); + modBuffer.push(src); + } + + /** + * Flush per-mutator remembered sets into the global remset pool. + */ + public final void flushRememberedSets() { + modBuffer.flushLocal(); + assertRemsetFlushed(); + } + + /** + * Assert that the remsets have been flushed. This is critical to + * correctness. We need to maintain the invariant that remset entries + * do not accrue during GC. If the host JVM generates barrier entires + * it is its own responsibility to ensure that they are flushed before + * returning to MMTk. + */ + public final void assertRemsetFlushed() { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(modBuffer.isFlushed()); + } + } + + + /**************************************************************************** + * + * Collection + */ + + /** + * Perform a per-mutator collection phase. + * + * @param phaseId The collection phase to perform + * @param primary Perform any single-threaded activities using this thread. + */ + @Inline + public final void collectionPhase(short phaseId, boolean primary) { + if (phaseId == StickyMS.PREPARE) { + flushRememberedSets(); + } + if (phaseId == StickyMS.RELEASE) { + assertRemsetFlushed(); + } + + if (!global().collectWholeHeap) { + if (phaseId == StickyMS.PREPARE) { + ms.prepare(); + return; + } + + if (phaseId == StickyMS.RELEASE) { + ms.release(); + return; + } + } + + super.collectionPhase(phaseId, primary); + } + + + /** + * Flush mutator context, in response to a requestMutatorFlush. + * Also called by the default implementation of deinitMutator. + */ + @Override + public void flush() { + super.flush(); + ms.flush(); + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** @return The active global plan as an MSGen instance. */ + @Inline + private static StickyMS global() { + return (StickyMS) VM.activePlan.global(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,101 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.plan.stickyms; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.ObjectReferenceDeque; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the thread-local functionality for a transitive + * closure over a mark-sweep space. + */ + at Uninterruptible +public final class StickyMSNurseryTraceLocal extends TraceLocal { + + /**************************************************************************** + * + * Instance fields. + */ + private final ObjectReferenceDeque modBuffer; + + /** + * Constructor + */ + public StickyMSNurseryTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) { + super(StickyMS.SCAN_NURSERY, trace); + this.modBuffer = modBuffer; + } + + /**************************************************************************** + * + * Externally visible Object processing and tracing + */ + + /** + * Is the specified object live? + * + * @param object The object. + * @return True if the object is live. + */ + public boolean isLive(ObjectReference object) { + if (object.isNull()) return false; + if (Space.isInSpace(StickyMS.MARK_SWEEP, object)) + return StickyMS.msSpace.isLive(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(super.isLive(object)); + return true; + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * 1. Ensure the traced object is not collected. + * 2. If this is the first visit to the object enqueue it to be scanned. + * 3. Return the forwarded reference to the object. + * + * In this instance, we refer objects in the mark-sweep space to the + * msSpace for tracing, and defer to the superclass for all others. + * + * @param object The object to be traced. + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object) { + if (object.isNull()) return object; + if (Space.isInSpace(StickyMS.MARK_SWEEP, object)) + return StickyMS.msSpace.traceObject(this, object); + else + return object; + } + + /** + * Process any remembered set entries. This means enumerating the + * mod buffer and for each entry, marking the object as unlogged + * and enqueing it for scanning. + */ + protected void processRememberedSets() { + logMessage(2, "processing modBuffer"); + while (!modBuffer.isEmpty()) { + ObjectReference src = modBuffer.pop(); + Plan.markAsUnlogged(src); + processNode(src); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,126 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.utility.heap.FreeListPageResource; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.Constants; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one treadmill *space*. + * + * Each of the instance methods of this class may be called by any + * thread (i.e. synchronization must be explicit in any instance or + * class method). + * + * This stands in contrast to TreadmillLocal, which is instantiated + * and called on a per-thread basis, where each instance of + * TreadmillLocal corresponds to one thread operating over one space. + */ + at Uninterruptible +public abstract class BaseLargeObjectSpace extends Space implements Constants { + + /**************************************************************************** + * + * Class variables + */ + protected static final Word PAGE_MASK = Word.fromIntSignExtend(~(BYTES_IN_PAGE - 1)); + + /**************************************************************************** + * + * Initialization + */ + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public BaseLargeObjectSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, false, false, vmRequest); + if (vmRequest.isDiscontiguous()) { + pr = new FreeListPageResource(pageBudget, this, 0); + } else { + pr = new FreeListPageResource(pageBudget, this, start, extent); + } + } + + /** + * Calculate the header size required for the large object. + * + * Must be multiple of MIN_ALIGNMENT. + */ + public final int getHeaderSize() { + return superPageHeaderSize() + cellHeaderSize(); + } + + /**************************************************************************** + * + * Freeing + */ + + /** + * Free a cell. If the cell is large (own superpage) then release + * the superpage, if not add to the super page's free list and if + * all cells on the superpage are free, then release the + * superpage. + * + * @param cell The address of the first byte of the cell to be freed + */ + @Inline + public final void free(Address cell) { + release(getSuperPage(cell)); + } + + /**************************************************************************** + * + * Superpages + */ + + protected abstract int superPageHeaderSize(); + protected abstract int cellHeaderSize(); + + /** + * Return the superpage for a given cell. If the cell is a small + * cell then this is found by masking the cell address to find the + * containing page. Otherwise the first word of the cell contains + * the address of the page. + * + * @param cell The address of the first word of the cell (exclusive + * of any sub-class specific metadata). + * @return The address of the first word of the superpage containing + * cell. + */ + @Inline + public static Address getSuperPage(Address cell) { + return cell.toWord().and(PAGE_MASK).toAddress(); + } + + /** + * Return the size of the super page + * + * @param first the Address of the first word in the superpage + * @return the size in bytes + */ + public Extent getSize(Address first) { + return ((FreeListPageResource) pr).getSize(first); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,44 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.utility.alloc.BumpPointer; + +import org.vmmagic.pragma.*; + +/** + * This class implements unsynchronized (local) elements of a + * copying collector. Allocation is via the bump pointer + * (@see BumpPointer). + * + * @see BumpPointer + * @see CopySpace + */ + at Uninterruptible public final class CopyLocal extends BumpPointer { + + /** + * Constructor + * + * @param space The space to bump point into. + */ + public CopyLocal(CopySpace space) { + super(space, true); + } + + /** + * Constructor + */ + public CopyLocal() { + super(null, true); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,407 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.*; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements tracing functionality for a simple copying + * space. Since no state needs to be held globally or locally, all + * methods are static. + */ + at Uninterruptible public final class CopySpace extends Space + implements Constants { + + /**************************************************************************** + * + * Class variables + */ + public static final int LOCAL_GC_BITS_REQUIRED = 2; + public static final int GLOBAL_GC_BITS_REQUIRED = 0; + public static final int GC_HEADER_WORDS_REQUIRED = 0; + + private static final int META_DATA_PAGES_PER_REGION = CARD_META_PAGES_PER_REGION; + + /* + * The forwarding process uses three states to deal with a GC race: + * 1. !GC_FORWARDED: Unforwarded + * 2. GC_BEING_FORWARDED: Being forwarded (forwarding is underway) + * 3. GC_FORWARDED: Forwarded + */ + /** If this bit is set, then forwarding of this object has commenced */ + private static final Word GC_FORWARDED = Word.one().lsh(1); // ...10 + /** If this bit is set, then forwarding of this object is incomplete */ + private static final Word GC_BEING_FORWARDED = Word.one().lsh(2).minus(Word.one()); // ...11 + /** This mask is used to reveal which state this object is in with respect to forwarding */ + private static final Word GC_FORWARDING_MASK = GC_FORWARDED.or(GC_BEING_FORWARDED); + + /** A single bit is used to indicate a mark when tracing (but not copying) the space */ + private static final Word GC_MARK_BIT_MASK = Word.one(); + + /**************************************************************************** + * + * Instance variables + */ + private boolean fromSpace = true; + + public boolean isFromSpace() { + return fromSpace; + } + + /**************************************************************************** + * + * Initialization + */ + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param fromSpace The does this instance start life as from-space + * (or to-space)? + * @param vmRequest An object describing the virtual memory requested. + */ + public CopySpace(String name, int pageBudget, boolean fromSpace, VMRequest vmRequest) { + super(name, true, false, vmRequest); + this.fromSpace = fromSpace; + if (vmRequest.isDiscontiguous()) { + pr = new MonotonePageResource(pageBudget, this, META_DATA_PAGES_PER_REGION); + } else { + pr = new MonotonePageResource(pageBudget, this, start, extent, META_DATA_PAGES_PER_REGION); + } + } + + /**************************************************************************** + * + * Prepare and release + */ + + /** + * Prepare this space instance for a collection. Set the + * "fromSpace" field according to whether this space is the + * source or target of the collection. + * + * @param fromSpace Set the fromSpace field to this value + */ + public void prepare(boolean fromSpace) { this.fromSpace = fromSpace; } + + /** + * Release this copy space after a collection. This means releasing + * all pages associated with this (now empty) space. + */ + public void release() { + ((MonotonePageResource) pr).reset(); + lastDiscontiguousRegion = Address.zero(); + fromSpace = false; + } + + /** + * Release an allocated page or pages. In this case we do nothing + * because we only release pages enmasse. + * + * @param start The address of the start of the page or pages + */ + @Inline + public void release(Address start) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(false); // this policy only releases pages enmasse + } + + /**************************************************************************** + * + * Tracing and forwarding + */ + + /** + * Trace an object under a copying collection policy. + * + * We use a tri-state algorithm to deal with races to forward + * the object. The tracer must wait if the object is concurrently + * being forwarded by another thread. + * + * If the object is already forwarded, the copy is returned. + * Otherwise, the object is forwarded and the copy is returned. + * + * @param trace The trace being conducted. + * @param object The object to be forwarded. + * @return The forwarded object. + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + VM.assertions.fail("CopySpace.traceLocal called without allocator"); + return ObjectReference.nullReference(); + } + + /** + * Trace an object under a copying collection policy. + * + * We use a tri-state algorithm to deal with races to forward + * the object. The tracer must wait if the object is concurrently + * being forwarded by another thread. + * + * If the object is already forwarded, the copy is returned. + * Otherwise, the object is forwarded and the copy is returned. + * + * @param trace The trace being conducted. + * @param object The object to be forwarded. + * @param allocator The allocator to use when copying. + * @return The forwarded object. + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object, int allocator) { + /* If the object in question is already in to-space, then do nothing */ + if (!fromSpace) return object; + + /* Try to forward the object */ + Word forwardingPtr = attemptToForward(object); + + if (stateIsForwardedOrBeingForwarded(forwardingPtr)) { + /* Somebody else got to it first. */ + + /* We must wait (spin) if the object is not yet fully forwarded */ + while (stateIsBeingForwarded(forwardingPtr)) + forwardingPtr = getForwardingWord(object); + + /* Now extract the object reference from the forwarding word and return it */ + return forwardingPtr.and(GC_FORWARDING_MASK.not()).toAddress().toObjectReference(); + } else { + /* We are the designated copier, so forward it and enqueue it */ + ObjectReference newObject = VM.objectModel.copy(object, allocator); + setForwardingPointer(object, newObject); + trace.processNode(newObject); // Scan it later + + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.write("C["); Log.write(object); Log.write("/"); + Log.write(getName()); Log.write("] -> "); + Log.write(newObject); Log.write("/"); + Log.write(Space.getSpaceForObject(newObject).getName()); + Log.writeln("]"); + } + return newObject; + } + } + + /** + * Return true if this object is live in this GC + * + * @param object The object in question + * @return True if this object is live in this GC (has it been forwarded?) + */ + public boolean isLive(ObjectReference object) { + return isForwarded(object); + } + + /** + * Has the object in this space been reached during the current collection. + * This is used for GC Tracing. + * + * @param object The object reference. + * @return True if the object is reachable. + */ + public boolean isReachable(ObjectReference object) { + return !fromSpace || isForwarded(object); + } + + /**************************************************************************** + * + * Non-copying tracing (just mark, don't forward) + */ + + /** + * Mark an object as having been traversed, *WITHOUT* forwarding the object. + * This is only used when + * + * @param object The object to be marked + * @param markState The sense of the mark bit (flips from 0 to 1) + */ + @Inline + public static void markObject(TraceLocal trace, ObjectReference object, + Word markState) { + if (testAndMark(object, markState)) + trace.processNode(object); + } + + /**************************************************************************** + * + * Header manipulation + */ + + /** + * Perform any required post-allocation initialization + * + * Nothing to be done in this case + * + * @param object the object ref to the storage to be initialized + */ + @Inline + public void postAlloc(ObjectReference object) {} + + /** + * Clear the GC portion of the header for an object. + * + * @param object the object ref to the storage to be initialized + */ + @Inline + public static void clearGCBits(ObjectReference object) { + Word header = VM.objectModel.readAvailableBitsWord(object); + VM.objectModel.writeAvailableBitsWord(object, header.and(GC_FORWARDING_MASK.not())); + } + + /** + * Has an object been forwarded? + * + * @param object The object to be checked + * @return True if the object has been forwarded + */ + @Inline + public static boolean isForwarded(ObjectReference object) { + return stateIsForwarded(getForwardingWord(object)); + } + + /** + * Has an object been forwarded or being forwarded? + * + * @param object The object to be checked + * @return True if the object has been forwarded or is being forwarded + */ + @Inline + public static boolean isForwardedOrBeingForwarded(ObjectReference object) { + return stateIsForwardedOrBeingForwarded(getForwardingWord(object)); + } + + /** + * Non-atomic read of forwarding pointer word + * + * @param object The object whose forwarding word is to be read + * @return The forwarding word stored in object's + * header. + */ + @Inline + private static Word getForwardingWord(ObjectReference object) { + return VM.objectModel.readAvailableBitsWord(object); + } + + /** + * Non-atomic read of forwarding pointer + * + * @param object The object whose forwarding pointer is to be read + * @return The forwarding pointer stored in object's + * header. + */ + @Inline + public static ObjectReference getForwardingPointer(ObjectReference object) { + return getForwardingWord(object).and(GC_FORWARDING_MASK.not()).toAddress().toObjectReference(); + } + + /** + * Used to mark boot image objects during a parallel scan of objects + * during GC Returns true if marking was done. + * + * @param object The object to be marked + * @param value The value to store in the mark bit + */ + @Inline + private static boolean testAndMark(ObjectReference object, Word value) { + Word oldValue; + do { + oldValue = VM.objectModel.prepareAvailableBits(object); + Word markBit = oldValue.and(GC_MARK_BIT_MASK); + if (markBit.EQ(value)) return false; + } while (!VM.objectModel.attemptAvailableBits(object, oldValue, + oldValue.xor(GC_MARK_BIT_MASK))); + return true; + } + + /** + * Either return the forwarding pointer if the object is already + * forwarded (or being forwarded) or write the bit pattern that + * indicates that the object is being forwarded + * + * @param object The object to be forwarded + * @return The forwarding pointer for the object if it has already + * been forwarded. + */ + @Inline + private static Word attemptToForward(ObjectReference object) { + Word oldValue; + do { + oldValue = VM.objectModel.prepareAvailableBits(object); + if (oldValue.and(GC_FORWARDING_MASK).EQ(GC_FORWARDED)) return oldValue; + } while (!VM.objectModel.attemptAvailableBits(object, oldValue, + oldValue.or(GC_BEING_FORWARDED))); + return oldValue; + } + + /** + * Is the state of the forwarding word being forwarded? + * + * @param fword A forwarding word. + * @return True if the forwarding word's state is being forwarded. + */ + @Inline + private static boolean stateIsBeingForwarded(Word fword) { + return fword.and(GC_FORWARDING_MASK).EQ(GC_BEING_FORWARDED); + } + + /** + * Is the state of the forwarding word forwarded? + * + * @param fword A forwarding word. + * @return True if the forwarding word's state is forwarded. + */ + @Inline + private static boolean stateIsForwarded(Word fword) { + return fword.and(GC_FORWARDING_MASK).EQ(GC_FORWARDED); + } + + /** + * Is the state of the forwarding word forwarded or being forwarded? + * + * @param fword A forwarding word. + * @return True if the forwarding word's state is forwarded or being + * forwarded. + */ + @Inline + public static boolean stateIsForwardedOrBeingForwarded(Word fword) { + return !(fword.and(GC_FORWARDED).isZero()); + } + + /** + * Non-atomic write of forwarding pointer word (assumption, thread + * doing the set has done attempt to forward and owns the right to + * copy the object) + * + * @param object The object whose forwarding pointer is to be set + * @param ptr The forwarding pointer to be stored in the object's + * forwarding word + */ + @Inline + private static void setForwardingPointer(ObjectReference object, + ObjectReference ptr) { + VM.objectModel.writeAvailableBitsWord(object, ptr.toAddress().toWord().or(GC_FORWARDED)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,77 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.utility.alloc.SegregatedFreeListLocal; +import org.mmtk.utility.Constants; + +import org.vmmagic.pragma.*; + +/** + * This class implements unsynchronized (local) elements of an + * explicity managed collector. Allocation is via the segregated free list + * (@see org.mmtk.utility.alloc.SegregatedFreeList).

+ * + * @see org.mmtk.utility.alloc.SegregatedFreeList + * @see ExplicitFreeListSpace + */ + at Uninterruptible +public final class ExplicitFreeListLocal extends SegregatedFreeListLocal implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + /**************************************************************************** + * + * Instance variables + */ + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param space The rc space to which this allocator + * instances is bound. + */ + public ExplicitFreeListLocal(ExplicitFreeListSpace space) { + super(space); + } + + /**************************************************************************** + * + * Allocation + */ + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare for a collection. If paranoid, perform a sanity check. + */ + public void prepare() { + flush(); + } + + /** + * Finish up after a collection. + */ + public void release() {} +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,175 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.*; +import org.mmtk.utility.Constants; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one *space*. + * Each of the instance methods of this class may be called by any + * thread (i.e. synchronization must be explicit in any instance or + * class method). This contrasts with the MarkSweepLocal, where + * instances correspond to *plan* instances and therefore to kernel + * threads. Thus unlike this class, synchronization is not necessary + * in the instance methods of MarkSweepLocal. + */ + at Uninterruptible +public final class ExplicitFreeListSpace extends SegregatedFreeListSpace implements Constants { + + /**************************************************************************** + * + * Class variables + */ + public static final int LOCAL_GC_BITS_REQUIRED = 0; + public static final int GLOBAL_GC_BITS_REQUIRED = 0; + public static final int GC_HEADER_WORDS_REQUIRED = 0; + + /**************************************************************************** + * + * Initialization + */ + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public ExplicitFreeListSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, pageBudget, 0, vmRequest); + } + + /** + * Should SegregatedFreeListSpace manage a side bitmap to keep track of live objects? + */ + @Inline + protected boolean maintainSideBitmap() { + return true; + } + + /** + * Do we need to preserve free lists as we move blocks around. + */ + @Inline + protected boolean preserveFreeList() { + return false; + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare the next block in the free block list for use by the free + * list allocator. In the case of lazy sweeping this involves + * sweeping the available cells. The sweeping operation must + * ensure that cells are pre-zeroed, as this method must return + * pre-zeroed cells. + * + * @param block The block to be prepared for use + * @param sizeClass The size class of the block + * @return The address of the first pre-zeroed cell in the free list + * for this block, or zero if there are no available cells. + */ + protected Address advanceToBlock(Address block, int sizeClass) { + return makeFreeList(block, sizeClass); + } + + /** + * Notify that a new block has been installed. This is to ensure that + * appropriate collection state can be initialized for the block + * + * @param block The new block + * @param sizeClass The block's sizeclass. + */ + protected void notifyNewBlock(Address block, int sizeClass) { + clearLiveBits(block, sizeClass); + } + + /** + * Free an object. + * + * @param object The object to be freed. + */ + @Inline + public void free(ObjectReference object) { + clearLiveBit(object); + } + + /** + * Prepare for a new collection increment. + */ + public void prepare() { + flushAvailableBlocks(); + } + + /** + * A new collection increment has completed. + */ + public void release() { + sweepConsumedBlocks(true); + } + + /** + * Release an allocated page or pages + * + * @param start The address of the start of the page or pages + */ + @Inline + public void release(Address start) { + ((FreeListPageResource) pr).releasePages(start); + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Trace a reference to an object under a mark sweep collection + * policy. If the object header is not already marked, mark the + * object in either the bitmap or by moving it off the treadmill, + * and enqueue the object for subsequent processing. The object is + * marked as (an atomic) side-effect of checking whether already + * marked. + * + * @param object The object to be traced. + * @return The object (there is no object forwarding in this + * collector, so we always return the same object: this could be a + * void method but for compliance to a more general interface). + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + return object; + } + + /** + * + * @param object The object in question + * @return True if this object is known to be live (i.e. it is marked) + */ + @Inline + public boolean isLive(ObjectReference object) { + return liveBitSet(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,193 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.FreeListPageResource; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.DoublyLinkedList; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one explicitly managed + * large object space. + */ + at Uninterruptible +public final class ExplicitLargeObjectSpace extends BaseLargeObjectSpace { + + /**************************************************************************** + * + * Instance variables + */ + private final DoublyLinkedList cells; + + /**************************************************************************** + * + * Initialization + */ + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public ExplicitLargeObjectSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, pageBudget, vmRequest); + cells = new DoublyLinkedList(LOG_BYTES_IN_PAGE, true); + } + + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare for a new collection increment. + */ + public void prepare() { + } + + /** + * A new collection increment has completed. + */ + public void release() { + } + + /** + * Release a group of pages that were allocated together. + * + * @param first The first page in the group of pages that were + * allocated together. + */ + @Inline + public void release(Address first) { + ((FreeListPageResource) pr).releasePages(first); + } + + /** + * Perform any required initialization of the GC portion of the header. + * + * @param object the object ref to the storage to be initialized + * @param alloc is this initialization occuring due to (initial) allocation + * (true) or due to copying (false)? + */ + @Inline + public void initializeHeader(ObjectReference object, boolean alloc) { + Address cell = VM.objectModel.objectStartRef(object); + cells.add(DoublyLinkedList.midPayloadToNode(cell)); + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Trace a reference to an object under a mark sweep collection + * policy. If the object header is not already marked, mark the + * object in either the bitmap or by moving it off the treadmill, + * and enqueue the object for subsequent processing. The object is + * marked as (an atomic) side-effect of checking whether already + * marked. + * + * @param trace The trace being conducted. + * @param object The object to be traced. + * @return The object (there is no object forwarding in this + * collector, so we always return the same object: this could be a + * void method but for compliance to a more general interface). + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + return object; + } + + /** + * @param object The object in question + * @return True if this object is known to be live (i.e. it is marked) + */ + @Inline + public boolean isLive(ObjectReference object) { + return true; + } + + /** + * Return the size of the per-superpage header required by this + * system. In this case it is just the underlying superpage header + * size. + * + * @return The size of the per-superpage header required by this + * system. + */ + @Inline + protected int superPageHeaderSize() { + return DoublyLinkedList.headerSize(); + } + + /** + * Return the size of the per-cell header for cells of a given class + * size. + * + * @return The size of the per-cell header for cells of a given class + * size. + */ + @Inline + protected int cellHeaderSize() { return 0; } + + /** + * Sweep through all the objects in this space. + * + * @param sweeper The sweeper callback to use. + */ + @Inline + public void sweep(Sweeper sweeper) { + Address cell = cells.getHead(); + while (!cell.isZero()) { + Address next = cells.getNext(cell); + ObjectReference obj = VM.objectModel.getObjectFromStartAddress(cell.plus(DoublyLinkedList.headerSize())); + if (sweeper.sweepLargeObject(obj)) { + free(obj); + } + cell = next; + } + } + + /** + * Free an object + * + * @param object The object to be freed. + */ + @Inline + public void free(ObjectReference object) { + Address cell = getSuperPage(VM.objectModel.refToAddress(object)); + cells.remove(cell); + release(cell); + } + + /** + * A callback used to perform sweeping of the large object space. + */ + @Uninterruptible + public abstract static class Sweeper { + public abstract boolean sweepLargeObject(ObjectReference object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,37 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.utility.alloc.BumpPointer; + +import org.vmmagic.pragma.*; + +/** + * This class implements unsynchronized (local) elements of an + * immortal space. Allocation is via the bump pointer + * (@see BumpPointer). + * + * @see BumpPointer + * @see ImmortalSpace + */ + at Uninterruptible public final class ImmortalLocal extends BumpPointer { + + /** + * Constructor + * + * @param space The space to bump point into. + */ + public ImmortalLocal(ImmortalSpace space) { + super(space, true); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,171 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.MonotonePageResource; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements tracing for a simple immortal collection + * policy. Under this policy all that is required is for the + * "collector" to propogate marks in a liveness trace. It does not + * actually collect. This class does not hold any state, all methods + * are static. + */ + at Uninterruptible public final class ImmortalSpace extends Space + implements Constants { + + /**************************************************************************** + * + * Class variables + */ + static final Word GC_MARK_BIT_MASK = Word.one(); + private static final int META_DATA_PAGES_PER_REGION = CARD_META_PAGES_PER_REGION; + + /**************************************************************************** + * + * Instance variables + */ + private Word markState = Word.zero(); // when GC off, the initialization value + + /**************************************************************************** + * + * Initialization + */ + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public ImmortalSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, false, true, vmRequest); + if (vmRequest.isDiscontiguous()) { + pr = new MonotonePageResource(pageBudget, this, META_DATA_PAGES_PER_REGION); + } else { + pr = new MonotonePageResource(pageBudget, this, start, extent, META_DATA_PAGES_PER_REGION); + } + } + + /** @return the current mark state */ + @Inline + public Word getMarkState() { return markState; } + + /**************************************************************************** + * + * Object header manipulations + */ + + /** + * Initialize the object header post-allocation. We need to set the mark state + * correctly and set the logged bit if necessary. + * + * @param object The newly allocated object instance whose header we are initializing + */ + public void initializeHeader(ObjectReference object) { + Word oldValue = VM.objectModel.readAvailableBitsWord(object); + Word newValue = oldValue.and(GC_MARK_BIT_MASK.not()).or(markState); + if (Plan.NEEDS_LOG_BIT_IN_HEADER) newValue = newValue.or(Plan.UNLOGGED_BIT); + VM.objectModel.writeAvailableBitsWord(object, newValue); + } + + /** + * Used to mark boot image objects during a parallel scan of objects during GC + * Returns true if marking was done. + */ + @Inline + private static boolean testAndMark(ObjectReference object, Word value) { + Word oldValue; + do { + oldValue = VM.objectModel.prepareAvailableBits(object); + Word markBit = oldValue.and(GC_MARK_BIT_MASK); + if (markBit.EQ(value)) return false; + } while (!VM.objectModel.attemptAvailableBits(object, oldValue, + oldValue.xor(GC_MARK_BIT_MASK))); + return true; + } + + /** + * Trace a reference to an object under an immortal collection + * policy. If the object is not already marked, enqueue the object + * for subsequent processing. The object is marked as (an atomic) + * side-effect of checking whether already marked. + * + * @param trace The trace being conducted. + * @param object The object to be traced. + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + if (testAndMark(object, markState)) + trace.processNode(object); + return object; + } + + /** + * Prepare for a new collection increment. For the immortal + * collector we must flip the state of the mark bit between + * collections. + */ + public void prepare() { + markState = GC_MARK_BIT_MASK.minus(markState); + } + + public void release() {} + + /** + * Release an allocated page or pages. In this case we do nothing + * because we only release pages enmasse. + * + * @param start The address of the start of the page or pages + */ + @Inline + public void release(Address start) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(false); // this policy only releases pages enmasse + } + + @Inline + public boolean isLive(ObjectReference object) { + return true; + } + + /** + * Returns if the object in question is currently thought to be reachable. + * This is done by comparing the mark bit to the current mark state. For the + * immortal collector reachable and live are different, making this method + * necessary. + * + * @param object The address of an object in immortal space to test + * @return True if ref may be a reachable object (e.g., having + * the current mark state). While all immortal objects are live, + * some may be unreachable. + */ + public boolean isReachable(ObjectReference object) { + if (Plan.SCAN_BOOT_IMAGE && this == Plan.vmSpace) + return true; // ignore boot image "reachabilty" if we're not tracing it + else + return (VM.objectModel.readAvailableBitsWord(object).and(GC_MARK_BIT_MASK).EQ(markState)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,110 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.utility.alloc.LargeObjectAllocator; +import org.mmtk.utility.gcspy.drivers.TreadmillDriver; +import org.mmtk.utility.Constants; + +import org.vmmagic.pragma.*; + +/** + * Each instance of this class is intended to provide fast, + * unsynchronized access to a treadmill. Therefore instances must not + * be shared across truely concurrent threads (CPUs). Rather, one or + * more instances of this class should be bound to each CPU. The + * shared VMResource used by each instance is the point of global + * synchronization, and synchronization only occurs at the granularity + * of aquiring (and releasing) chunks of memory from the VMResource. + * + * If there are C CPUs and T TreadmillSpaces, there must be C X T + * instances of this class, one for each CPU, TreadmillSpace pair. + */ + at Uninterruptible +public final class LargeObjectLocal extends LargeObjectAllocator implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + /**************************************************************************** + * + * Instance variables + */ + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param space The treadmill space to which this thread instance is + * bound. + */ + public LargeObjectLocal(BaseLargeObjectSpace space) { + super(space); + } + + /**************************************************************************** + * + * Allocation + */ + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare for a collection. Clear the treadmill to-space head and + * prepare the collector. If paranoid, perform a sanity check. + */ + public void prepare(boolean fullHeap) { + } + + /** + * Finish up after a collection. + */ + public void release(boolean fullHeap) { + } + + /**************************************************************************** + * + * Miscellaneous size-related methods + */ + + /** + * Gather data for GCSpy from the nursery + * @param event the gc event + * @param losDriver the GCSpy space driver + */ + public void gcspyGatherData(int event, TreadmillDriver losDriver) { + // TODO: assumes single threaded + // TODO: assumes non-explit LOS + ((LargeObjectSpace)space).getTreadmill().gcspyGatherData(event, losDriver); + } + + /** + * Gather data for GCSpy for an older space + * @param event the gc event + * @param losDriver the GCSpy space driver + * @param tospace gather from tospace? + */ + public void gcspyGatherData(int event, TreadmillDriver losDriver, boolean tospace) { + // TODO: assumes single threaded + ((LargeObjectSpace)space).getTreadmill().gcspyGatherData(event, losDriver, tospace); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,284 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.FreeListPageResource; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.Treadmill; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one explicitly managed + * large object space. + */ + at Uninterruptible +public final class LargeObjectSpace extends BaseLargeObjectSpace { + + /**************************************************************************** + * + * Class variables + */ + public static final int LOCAL_GC_BITS_REQUIRED = 2; + public static final int GLOBAL_GC_BITS_REQUIRED = 0; + private static final Word MARK_BIT = Word.one(); // ...01 + private static final Word NURSERY_BIT = Word.fromIntZeroExtend(2); // ...10 + private static final Word LOS_BIT_MASK = Word.fromIntZeroExtend(3); // ...11 + + /**************************************************************************** + * + * Instance variables + */ + private Word markState; + private boolean inNurseryGC; + private final Treadmill treadmill; + + /**************************************************************************** + * + * Initialization + */ + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public LargeObjectSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, pageBudget, vmRequest); + treadmill = new Treadmill(LOG_BYTES_IN_PAGE, true); + markState = Word.zero(); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare for a new collection increment. For the mark-sweep + * collector we must flip the state of the mark bit between + * collections. + */ + public void prepare(boolean fullHeap) { + if (fullHeap) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(treadmill.fromSpaceEmpty()); + } + markState = MARK_BIT.minus(markState); + } + treadmill.flip(fullHeap); + inNurseryGC = !fullHeap; + } + + /** + * A new collection increment has completed. For the mark-sweep + * collector this means we can perform the sweep phase. + */ + public void release(boolean fullHeap) { + // sweep the large objects + sweepLargePages(true); // sweep the nursery + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(treadmill.nurseryEmpty()); + if (fullHeap) sweepLargePages(false); // sweep the mature space + } + + /** + * Sweep through the large pages, releasing all superpages on the + * "from space" treadmill. + */ + private void sweepLargePages(boolean sweepNursery) { + while (true) { + Address cell = sweepNursery ? treadmill.popNursery() : treadmill.pop(); + if (cell.isZero()) break; + release(getSuperPage(cell)); + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(sweepNursery ? treadmill.nurseryEmpty() : treadmill.fromSpaceEmpty()); + } + + /** + * Release a group of pages that were allocated together. + * + * @param first The first page in the group of pages that were + * allocated together. + */ + @Inline + public void release(Address first) { + ((FreeListPageResource) pr).releasePages(first); + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Trace a reference to an object under a mark sweep collection + * policy. If the object header is not already marked, mark the + * object in either the bitmap or by moving it off the treadmill, + * and enqueue the object for subsequent processing. The object is + * marked as (an atomic) side-effect of checking whether already + * marked. + * + * @param trace The trace being conducted. + * @param object The object to be traced. + * @return The object (there is no object forwarding in this + * collector, so we always return the same object: this could be a + * void method but for compliance to a more general interface). + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + boolean nurseryObject = isInNursery(object); + if (!inNurseryGC || nurseryObject) { + if (testAndMark(object, markState)) { + internalMarkObject(object, nurseryObject); + trace.processNode(object); + } + } + return object; + } + + /** + * @param object The object in question + * @return True if this object is known to be live (i.e. it is marked) + */ + @Inline + public boolean isLive(ObjectReference object) { + return testMarkBit(object, markState); + } + + /** + * An object has been marked (identifiged as live). Large objects + * are added to the to-space treadmill, while all other objects will + * have a mark bit set in the superpage header. + * + * @param object The object which has been marked. + */ + @Inline + private void internalMarkObject(ObjectReference object, boolean nurseryObject) { + + Address cell = VM.objectModel.objectStartRef(object); + Address node = Treadmill.midPayloadToNode(cell); + treadmill.copy(node, nurseryObject); + } + + /**************************************************************************** + * + * Header manipulation + */ + + /** + * Perform any required initialization of the GC portion of the header. + * + * @param object the object ref to the storage to be initialized + * @param alloc is this initialization occuring due to (initial) allocation + * (true) or due to copying (false)? + */ + @Inline + public void initializeHeader(ObjectReference object, boolean alloc) { + Word oldValue = VM.objectModel.readAvailableBitsWord(object); + Word newValue = oldValue.and(LOS_BIT_MASK.not()).or(markState); + if (alloc) newValue = newValue.or(NURSERY_BIT); + if (Plan.NEEDS_LOG_BIT_IN_HEADER) newValue = newValue.or(Plan.UNLOGGED_BIT); + VM.objectModel.writeAvailableBitsWord(object, newValue); + Address cell = VM.objectModel.objectStartRef(object); + treadmill.addToTreadmill(Treadmill.midPayloadToNode(cell), alloc); + } + + /** + * Atomically attempt to set the mark bit of an object. Return true + * if successful, false if the mark bit was already set. + * + * @param object The object whose mark bit is to be written + * @param value The value to which the mark bit will be set + */ + @Inline + private boolean testAndMark(ObjectReference object, Word value) { + Word oldValue, markBit; + do { + oldValue = VM.objectModel.prepareAvailableBits(object); + markBit = oldValue.and(inNurseryGC ? LOS_BIT_MASK : MARK_BIT); + if (markBit.EQ(value)) return false; + } while (!VM.objectModel.attemptAvailableBits(object, oldValue, + oldValue.and(LOS_BIT_MASK.not()).or(value))); + return true; + } + + /** + * Return true if the mark bit for an object has the given value. + * + * @param object The object whose mark bit is to be tested + * @param value The value against which the mark bit will be tested + * @return True if the mark bit for the object has the given value. + */ + @Inline + private boolean testMarkBit(ObjectReference object, Word value) { + return VM.objectModel.readAvailableBitsWord(object).and(MARK_BIT).EQ(value); + } + + /** + * Return true if the object is in the logical nursery + * + * @param object The object whose status is to be tested + * @return True if the object is in the logical nursery + */ + @Inline + private boolean isInNursery(ObjectReference object) { + return VM.objectModel.readAvailableBitsWord(object).and(NURSERY_BIT).EQ(NURSERY_BIT); + } + + /** + * Return the size of the per-superpage header required by this + * system. In this case it is just the underlying superpage header + * size. + * + * @return The size of the per-superpage header required by this + * system. + */ + @Inline + protected int superPageHeaderSize() { + return Treadmill.headerSize(); + } + + /** + * Return the size of the per-cell header for cells of a given class + * size. + * + * @return The size of the per-cell header for cells of a given class + * size. + */ + @Inline + protected int cellHeaderSize() { + return 0; + } + + /** + * This is the treadmill used by the large object space. + * + * Note that it depends on the specific local in use whether this + * is being used. + * + * @return The treadmill associated with this large object space. + */ + public Treadmill getTreadmill() { + return this.treadmill; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,210 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.markcompact.MC; +import org.mmtk.utility.Conversions; +import org.mmtk.utility.alloc.Allocator; +import org.mmtk.utility.alloc.BumpPointer; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Extent; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class implements unsynchronized (local) elements of a + * sliding mark-compact collector. Allocation is via the bump pointer + * (@see BumpPointer). + * + * @see BumpPointer + * @see MarkCompactSpace + */ + at Uninterruptible public final class MarkCompactLocal extends BumpPointer { + + /** + * Constructor + * + * @param space The space to bump point into. + */ + public MarkCompactLocal(MarkCompactSpace space) { + super(space, true); + } + + /** + * Perform the compacting phase of the collection. + */ + public void compact() { + /* Has this allocator ever allocated anything? */ + if (initialRegion.isZero()) return; + + /* Loop through active regions or until the last region */ + Address start = initialRegion; + Address allocStart = initialRegion; + Address allocEnd = initialRegion.plus(REGION_LIMIT_OFFSET).loadAddress(); + Address allocCursor = allocStart.plus(DATA_START_OFFSET); + + /* Keep track of which regions are being used */ + int oldPages = 0; + int newPages = Conversions.bytesToPages(allocEnd.diff(allocStart).plus(BYTES_IN_ADDRESS)); + + while (!start.isZero()) { + /* Get the end of this region */ + Address end = start.plus(REGION_LIMIT_OFFSET).loadAddress(); + Address dataEnd = start.plus(DATA_END_OFFSET).loadAddress(); + Address nextRegion = start.plus(NEXT_REGION_OFFSET).loadAddress(); + oldPages += Conversions.bytesToPages(end.diff(start).plus(BYTES_IN_ADDRESS)); + + /* dataEnd = zero represents the current region. */ + Address currentLimit = (dataEnd.isZero() ? cursor : dataEnd); + ObjectReference current = + VM.objectModel.getObjectFromStartAddress(start.plus(DATA_START_OFFSET)); + + while (VM.objectModel.refToAddress(current).LT(currentLimit) && !current.isNull()) { + ObjectReference next = VM.objectModel.getNextObject(current); + + ObjectReference copyTo = MarkCompactSpace.getForwardingPointer(current); + + if (!copyTo.isNull() && Space.isInSpace(MC.MARK_COMPACT, copyTo)) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!MarkCompactSpace.isMarked(current)); + // To be copied. + if (copyTo.toAddress().GT(allocEnd) || copyTo.toAddress().LT(allocStart)) { + // changed regions. + + VM.memory.zero(allocCursor, allocEnd.diff(allocCursor).toWord().toExtent().plus(BYTES_IN_ADDRESS)); + + allocStart.store(allocCursor, DATA_END_OFFSET); + allocStart = allocStart.plus(NEXT_REGION_OFFSET).loadAddress(); + allocEnd = allocStart.plus(REGION_LIMIT_OFFSET).loadAddress(); + allocCursor = allocStart.plus(DATA_START_OFFSET); + + newPages += Conversions.bytesToPages(allocEnd.diff(allocStart).plus(BYTES_IN_ADDRESS)); + + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(allocCursor.LT(allocEnd) && allocCursor.GE(allocStart)); + } + } + allocCursor = VM.objectModel.copyTo(current, copyTo, allocCursor); + MarkCompactSpace.setForwardingPointer(copyTo, ObjectReference.nullReference()); + } + current = next; + } + if (dataEnd.isZero()) { + break; + } + start = nextRegion; + } + Extent zeroBytes = allocEnd.diff(allocCursor).toWord().toExtent().plus(BYTES_IN_ADDRESS); + VM.memory.zero(allocCursor, zeroBytes); + + allocStart.store(Address.zero(), DATA_END_OFFSET); + region = allocStart; + cursor = allocCursor; + updateLimit(allocEnd, region, 0); + if (oldPages > newPages) { + ((MarkCompactSpace) space).unusePages((oldPages - newPages)); + } + + // Zero during GC to help debugging. + allocStart = allocStart.loadAddress(NEXT_REGION_OFFSET); + while (!allocStart.isZero()) { + allocStart.store(Address.zero(), DATA_END_OFFSET); + if (VM.VERIFY_ASSERTIONS) { + Address low = allocStart.plus(DATA_START_OFFSET); + Extent size = allocStart.loadAddress(REGION_LIMIT_OFFSET).diff(allocStart).toWord().toExtent().minus(2 * BYTES_IN_ADDRESS); + VM.memory.zero(low, size); + } + allocStart = allocStart.loadAddress(NEXT_REGION_OFFSET); + } + } + + /** + * Perform a linear scan through the objects allocated by this bump pointer, + * calculating where each live object will be post collection. + */ + public void calculateForwardingPointers() { + /* Has this allocator ever allocated anything? */ + if (initialRegion.isZero()) return; + + /* Loop through active regions or until the last region */ + Address start = initialRegion; + Address allocStart = initialRegion; + Address allocDataEnd = initialRegion.plus(DATA_END_OFFSET).loadAddress(); + Address allocLimit = (allocDataEnd.isZero() ? cursor : allocDataEnd); + Address allocCursor = start.plus(DATA_START_OFFSET); + + while (!start.isZero()) { + /* Get the end of this region */ + Address dataEnd = start.plus(DATA_END_OFFSET).loadAddress(); + + /* dataEnd = zero represents the current region. */ + Address currentLimit = (dataEnd.isZero() ? cursor : dataEnd); + ObjectReference current = + VM.objectModel.getObjectFromStartAddress(start.plus(DATA_START_OFFSET)); + + while (VM.objectModel.refToAddress(current).LT(currentLimit) && !current.isNull()) { + ObjectReference next = VM.objectModel.getNextObject(current); + + if (MarkCompactSpace.toBeCompacted(current)) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(MarkCompactSpace.getForwardingPointer(current).isNull()); + + // Fake - allocate it. + int size = VM.objectModel.getSizeWhenCopied(current); + int align = VM.objectModel.getAlignWhenCopied(current); + int offset = VM.objectModel.getAlignOffsetWhenCopied(current); + allocCursor = Allocator.alignAllocationNoFill(allocCursor, align, offset); + + boolean sameRegion = allocStart.EQ(start); + + if (!sameRegion && allocCursor.plus(size).GT(allocLimit)) { + allocStart = allocStart.plus(NEXT_REGION_OFFSET).loadAddress(); + allocDataEnd = allocStart.plus(DATA_END_OFFSET).loadAddress(); + allocLimit = (allocDataEnd.isZero() ? cursor : allocDataEnd); + allocCursor = Allocator.alignAllocationNoFill(allocStart.plus(DATA_START_OFFSET), align, offset); + } + + ObjectReference target = VM.objectModel.getReferenceWhenCopiedTo(current, allocCursor); + if (sameRegion && target.toAddress().GE(current.toAddress())) { + MarkCompactSpace.setForwardingPointer(current, current); + allocCursor = VM.objectModel.getObjectEndAddress(current); + } else { + MarkCompactSpace.setForwardingPointer(current, target); + allocCursor = allocCursor.plus(size); + } + } + current = next; + } + if (dataEnd.isZero()) { + break; + } + start = start.plus(NEXT_REGION_OFFSET).loadAddress(); // Move on to next + } + } + + /** + * Some pages are about to be re-used to satisfy a slow path request. + * @param pages The number of pages. + */ + protected void reusePages(int pages) { + ((MarkCompactSpace)space).reusePages(pages); + } + + /** + * Maximum size of a single region. Important for children that implement + * load balancing or increments based on region size. + * @return the maximum region size + */ + protected Extent maximumRegionSize() { return Extent.fromIntZeroExtend(4 << LOG_BLOCK_SIZE) ; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,335 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.*; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements functionality for a simple sliding mark-compact + * space. + */ + at Uninterruptible public final class MarkCompactSpace extends Space + implements Constants { + + /**************************************************************************** + * + * Class variables + */ + public static final int LOCAL_GC_BITS_REQUIRED = 1; + public static final int GLOBAL_GC_BITS_REQUIRED = 0; + public static final int GC_HEADER_WORDS_REQUIRED = 1; + + private static final Word GC_MARK_BIT_MASK = Word.one(); + private static final Offset FORWARDING_POINTER_OFFSET = VM.objectModel.GC_HEADER_OFFSET(); + + /**************************************************************************** + * + * Instance variables + */ + + /**************************************************************************** + * + * Initialization + */ + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public MarkCompactSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, true, false, vmRequest); + if (vmRequest.isDiscontiguous()) { + pr = new MonotonePageResource(pageBudget, this, 0); + } else { + pr = new MonotonePageResource(pageBudget, this, start, extent, 0); + } + } + + /** + * Prepare for a collection + */ + public void prepare() { + // nothing to do + } + + /** + * Release after a collection + */ + public void release() { + // nothing to do + } + + + /** + * Notify that several pages are no longer in use. + * + * @param pages The number of pages + */ + public void unusePages(int pages) { + ((MonotonePageResource) pr).unusePages(pages); + } + + /** + * Notify that several pages are no longer in use. + * + * @param pages The number of pages + */ + public void reusePages(int pages) { + ((MonotonePageResource) pr).reusePages(pages); + } + + /** + * Release an allocated page or pages. In this case we do nothing + * because we only release pages enmasse. + * + * @param start The address of the start of the page or pages + */ + @Inline + public void release(Address start) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(false); // this policy only releases pages enmasse + } + + /** + * Trace an object under a copying collection policy. + * If the object is already copied, the copy is returned. + * Otherwise, a copy is created and returned. + * In either case, the object will be marked on return. + * + * @param trace The trace being conducted. + * @param object The object to be forwarded. + * @return The forwarded object. + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(false); + return null; + } + + /** + * Trace an object under a copying collection policy. + * If the object is already copied, the copy is returned. + * Otherwise, a copy is created and returned. + * In either case, the object will be marked on return. + * + * @param trace The trace being conducted. + * @param object The object to be forwarded. + * @return The forwarded object. + */ + @Inline + public ObjectReference traceMarkObject(TraceLocal trace, ObjectReference object) { + if (testAndMark(object)) { + trace.processNode(object); + } else if (!getForwardingPointer(object).isNull()) { + return getForwardingPointer(object); + } + return object; + } + + /** + * Trace an object under a copying collection policy. + * If the object is already copied, the copy is returned. + * Otherwise, a copy is created and returned. + * In either case, the object will be marked on return. + * + * @param trace The trace being conducted. + * @param object The object to be forwarded. + * @return The forwarded object. + */ + @Inline + public ObjectReference traceForwardObject(TraceLocal trace, ObjectReference object) { + if (testAndClearMark(object)) { + trace.processNode(object); + } + ObjectReference newObject = getForwardingPointer(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!newObject.isNull()); + return getForwardingPointer(object); + } + + /** + * Is this object live? + * + * @param object The object + * @return True if the object is live + */ + public boolean isLive(ObjectReference object) { + return isMarked(object); + } + + /** + * Has the object in this space been reached during the current collection. + * This is used for GC Tracing. + * + * @param object The object reference. + * @return True if the object is reachable. + */ + public boolean isReachable(ObjectReference object) { + return isMarked(object); + } + + + /**************************************************************************** + * + * Header manipulation + */ + + /** + * Perform any required post-allocation initialization + * + * Nothing to be done in this case + * + * @param object the object ref to the storage to be initialized + */ + @Inline + public void postAlloc(ObjectReference object) { + } + + /** + * Non-atomic read of forwarding pointer + * + * @param object The object whose forwarding pointer is to be read + * @return The forwarding pointer stored in object's + * header. + */ + @Inline + public static ObjectReference getForwardingPointer(ObjectReference object) { + return object.toAddress().loadObjectReference(FORWARDING_POINTER_OFFSET); + } + + /** + * Initialise the header of the object. + * + * @param object The object to initialise + */ + @Inline + public void initializeHeader(ObjectReference object) { + // nothing to do + } + + /** + * Used to mark boot image objects during a parallel scan of objects + * during GC Returns true if marking was done. + * + * @param object The object to be marked + */ + @Inline + public static boolean testAndMark(ObjectReference object) { + Word oldValue; + do { + oldValue = VM.objectModel.prepareAvailableBits(object); + Word markBit = oldValue.and(GC_MARK_BIT_MASK); + if (!markBit.isZero()) return false; + } while (!VM.objectModel.attemptAvailableBits(object, oldValue, + oldValue.or(GC_MARK_BIT_MASK))); + return true; + } + + /** + * Used to mark boot image objects during a parallel scan of objects + * during GC Returns true if marking was done. + * + * @param object The object to be marked + */ + @Inline + public static boolean isMarked(ObjectReference object) { + Word oldValue = VM.objectModel.readAvailableBitsWord(object); + Word markBit = oldValue.and(GC_MARK_BIT_MASK); + return (!markBit.isZero()); + } + + /** + * Used to mark boot image objects during a parallel scan of objects + * during GC Returns true if marking was done. + * + * @param object The object to be marked + */ + @Inline + private static boolean testAndClearMark(ObjectReference object) { + Word oldValue; + do { + oldValue = VM.objectModel.prepareAvailableBits(object); + Word markBit = oldValue.and(GC_MARK_BIT_MASK); + if (markBit.isZero()) return false; + } while (!VM.objectModel.attemptAvailableBits(object, oldValue, + oldValue.and(GC_MARK_BIT_MASK.not()))); + return true; + } + + + /** + * Used to mark boot image objects during a parallel scan of objects + * during GC Returns true if marking was done. + * + * @param object The object to be marked + */ + @Inline + public static boolean toBeCompacted(ObjectReference object) { + Word oldValue = VM.objectModel.readAvailableBitsWord(object); + Word markBit = oldValue.and(GC_MARK_BIT_MASK); + return !markBit.isZero() && getForwardingPointer(object).isNull(); + } + + /** + * Used to mark boot image objects during a parallel scan of objects + * during GC Returns true if marking was done. + * + * @param object The object to be marked + */ + @Inline + public static void clearMark(ObjectReference object) { + Word oldValue = VM.objectModel.readAvailableBitsWord(object); + VM.objectModel.writeAvailableBitsWord(object, oldValue.and(GC_MARK_BIT_MASK.not())); + } + + /** + * Non-atomic write of forwarding pointer word (assumption, thread + * doing the set has done attempt to forward and owns the right to + * copy the object) + * + * @param object The object whose forwarding pointer is to be set + * @param ptr The forwarding pointer to be stored in the object's + * forwarding word + */ + @Inline + public static void setForwardingPointer(ObjectReference object, + ObjectReference ptr) { + object.toAddress().store(ptr.toAddress(), FORWARDING_POINTER_OFFSET); + } + + /** + * Non-atomic clear of forwarding pointer word (assumption, thread + * doing the set has done attempt to forward and owns the right to + * copy the object) + * + * @param object The object whose forwarding pointer is to be set + */ + @Inline + public static void clearForwardingPointer(ObjectReference object) { + object.toAddress().store(Address.zero(), FORWARDING_POINTER_OFFSET); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,76 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.utility.alloc.SegregatedFreeListLocal; +import org.mmtk.utility.Constants; + +import org.vmmagic.pragma.*; + +/** + * This class implements unsynchronized (local) elements of a + * mark-sweep collector. Allocation is via the segregated free list + * (@see SegregatedFreeList). Marking is done using both a bit in + * each header's object word, and a mark bitmap. Sweeping is + * performed lazily.

+ * + * A free list block is a contiguous region of memory containing cells + * of a single size class, and is a construct of the + * SegregatedFreeList. This class extends the block to include a mark + * bitmap. During the mark phase, if an object is encountered with + * the mark bit in its header unset, it is set and the mark bit in the + * block header corresponding to that object is set. The rationale + * behind this approach is that testing (and setting) the mark bit in + * the object header is cheap, while using a bitmap makes sweeping + * more efficient. This approach maximizes the speed of the common + * case when marking, while also allowing for fast sweeping, with + * minimal space overhead (2 bits per object). + * + * @see org.mmtk.utility.alloc.SegregatedFreeList + * @see MarkSweepSpace + */ + at Uninterruptible +public final class MarkSweepLocal extends SegregatedFreeListLocal implements Constants { + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param space The mark-sweep space to which this allocator + * instances is bound. + */ + public MarkSweepLocal(MarkSweepSpace space) { + super(space); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare for a collection. If paranoid, perform a sanity check. + */ + public void prepare() { + flush(); + } + + /** + * Finish up after a collection. + */ + public void release() {} +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,428 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.*; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.options.MarkSweepMarkBits; +import org.mmtk.utility.options.EagerCompleteSweep; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one mark-sweep *space*. + * Each of the instance methods of this class may be called by any + * thread (i.e. synchronization must be explicit in any instance or + * class method). This contrasts with the MarkSweepLocal, where + * instances correspond to *plan* instances and therefore to kernel + * threads. Thus unlike this class, synchronization is not necessary + * in the instance methods of MarkSweepLocal. + */ + at Uninterruptible +public final class MarkSweepSpace extends SegregatedFreeListSpace implements Constants { + + /**************************************************************************** + * + * Class variables + */ + /** + * Select between using mark bits in a side bitmap, or mark bits + * in the headers of object (or other sub-class scheme), and a single + * mark bit per block. + */ + public static final boolean HEADER_MARK_BITS = VM.config.HEADER_MARK_BITS; + /** highest bit bits we may use */ + private static final int MAX_BITS = 4; + + /* mark bits */ + private static final int COUNT_BASE = 0; + public static final int DEFAULT_MARKCOUNT_BITS = 2; + public static final int MAX_MARKCOUNT_BITS = Plan.NEEDS_LOG_BIT_IN_HEADER ? MAX_BITS - 1 : MAX_BITS; + public static final Word UNLOGGED_BIT = Word.one().lsh(MAX_BITS - 1).lsh(COUNT_BASE); + private static final Word MARK_COUNT_INCREMENT = Word.one().lsh(COUNT_BASE); + private static final Word MARK_COUNT_MASK = Word.one().lsh(MAX_MARKCOUNT_BITS).minus(Word.one()).lsh(COUNT_BASE); + private static final Word MARK_BITS_MASK = Word.one().lsh(MAX_BITS).minus(Word.one()); + + private static final boolean EAGER_MARK_CLEAR = Plan.NEEDS_LOG_BIT_IN_HEADER; + + /* header requirements */ + public static final int LOCAL_GC_BITS_REQUIRED = MAX_BITS; + public static final int GLOBAL_GC_BITS_REQUIRED = 0; + public static final int GC_HEADER_WORDS_REQUIRED = 0; + + + /**************************************************************************** + * + * Instance variables + */ + private Word markState = Word.one(); + private Word allocState = Word.zero(); + private boolean inMSCollection; + private static final boolean usingStickyMarkBits = VM.activePlan.constraints().needsLogBitInHeader(); /* are sticky mark bits in use? */ + private boolean isAgeSegregated = false; /* is this space a nursery space? */ + + /**************************************************************************** + * + * Initialization + */ + + static { + Options.markSweepMarkBits = new MarkSweepMarkBits(); + Options.eagerCompleteSweep = new EagerCompleteSweep(); + } + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public MarkSweepSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, pageBudget, 0, vmRequest); + if (usingStickyMarkBits) allocState = allocState.or(UNLOGGED_BIT); + } + + /** + * This instance will be age-segregated using the sticky mark bits + * algorithm. Perform appropriate initialization + */ + public void isAgeSegregatedSpace() { + /* we must be using sticky mark bits */ + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(usingStickyMarkBits); + allocState = allocState.and(UNLOGGED_BIT.not()); /* clear the unlogged bit for nursery allocs */ + isAgeSegregated = true; + } + + /** + * Should SegregatedFreeListSpace manage a side bitmap to keep track of live objects? + */ + @Inline + protected boolean maintainSideBitmap() { + return !HEADER_MARK_BITS; + } + + /** + * Do we need to preserve free lists as we move blocks around. + */ + @Inline + protected boolean preserveFreeList() { + return !LAZY_SWEEP; + } + + /**************************************************************************** + * + * Allocation + */ + + /** + * Prepare the next block in the free block list for use by the free + * list allocator. In the case of lazy sweeping this involves + * sweeping the available cells. The sweeping operation must + * ensure that cells are pre-zeroed, as this method must return + * pre-zeroed cells. + * + * @param block The block to be prepared for use + * @param sizeClass The size class of the block + * @return The address of the first pre-zeroed cell in the free list + * for this block, or zero if there are no available cells. + */ + protected Address advanceToBlock(Address block, int sizeClass) { + if (HEADER_MARK_BITS) { + if (inMSCollection) markBlock(block); + } + + if (LAZY_SWEEP) { + return makeFreeList(block, sizeClass); + } else { + return getFreeList(block); + } + } + + /** + * Notify that a new block has been installed. This is to ensure that + * appropriate collection state can be initialized for the block + * + * @param block The new block + * @param sizeClass The block's sizeclass. + */ + protected void notifyNewBlock(Address block, int sizeClass) { + if (HEADER_MARK_BITS) { + if (inMSCollection) markBlock(block); + } + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare for a new collection increment. For the mark-sweep + * collector we must flip the state of the mark bit between + * collections. + * + * @param gcWholeMS True if we are going to collect the whole marksweep space + */ + public void prepare(boolean gcWholeMS) { + if (HEADER_MARK_BITS && Options.eagerCompleteSweep.getValue()) { + consumeBlocks(); + } else { + flushAvailableBlocks(); + } + if (HEADER_MARK_BITS) { + if (gcWholeMS) { + allocState = markState; + if (usingStickyMarkBits && !isAgeSegregated) /* if true, we allocate as "mature", not nursery */ + allocState = allocState.or(UNLOGGED_BIT); + markState = deltaMarkState(true); + if (EAGER_MARK_CLEAR) + clearAllBlockMarks(); + } + } else { + zeroLiveBits(start, ((FreeListPageResource) pr).getHighWater()); + } + inMSCollection = true; + } + + /** + * A new collection increment has completed. For the mark-sweep + * collector this means we can perform the sweep phase. + */ + public void release() { + sweepConsumedBlocks(!EAGER_MARK_CLEAR); + inMSCollection = false; + } + + /** + * Release an allocated page or pages + * + * @param start The address of the start of the page or pages + */ + @Inline + public void release(Address start) { + ((FreeListPageResource) pr).releasePages(start); + } + + /** + * Should the sweep reclaim the cell containing this object. Is this object + * live. This is only used when maintainSideBitmap is false. + * + * @param object The object to query + * @return True if the cell should be reclaimed + */ + @Inline + protected boolean isCellLive(ObjectReference object) { + if (!HEADER_MARK_BITS) { + return super.isCellLive(object); + } + return testMarkState(object, markState); + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Trace a reference to an object under a mark sweep collection + * policy. If the object header is not already marked, mark the + * object in either the bitmap or by moving it off the treadmill, + * and enqueue the object for subsequent processing. The object is + * marked as (an atomic) side-effect of checking whether already + * marked. + * + * @param object The object to be traced. + * @return The object (there is no object forwarding in this + * collector, so we always return the same object: this could be a + * void method but for compliance to a more general interface). + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + if (HEADER_MARK_BITS) { + Word markValue = Plan.NEEDS_LOG_BIT_IN_HEADER ? markState.or(Plan.UNLOGGED_BIT) : markState; + if (testAndMark(object, markValue)) { + markBlock(object); + trace.processNode(object); + } + } else { + if (testAndSetLiveBit(object)) { + trace.processNode(object); + } + } + return object; + } + + /** + * + * @param object The object in question + * @return True if this object is known to be live (i.e. it is marked) + */ + @Inline + public boolean isLive(ObjectReference object) { + if (HEADER_MARK_BITS) { + return testMarkState(object, markState); + } else { + return liveBitSet(object); + } + } + + /** + * Get the current mark state + * + * @return The current mark state. + */ + @Inline + public Word getMarkState() { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(markState.and(MARK_COUNT_MASK.not()).isZero()); + return markState; + } + + /** + * Get the previous mark state. + * + * @return The previous mark state. + */ + @Inline + public Word getPreviousMarkState() { + return deltaMarkState(false); + } + + /** + * Return the mark state incremented or decremented by one. + * + * @param increment If true, then return the incremented value else return the decremented value + * @return the mark state incremented or decremented by one. + */ + private Word deltaMarkState(boolean increment) { + Word mask = Word.fromIntZeroExtend((1 << Options.markSweepMarkBits.getValue()) - 1).lsh(COUNT_BASE); + Word rtn = increment ? markState.plus(MARK_COUNT_INCREMENT) : markState.minus(MARK_COUNT_INCREMENT); + rtn = rtn.and(mask); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(markState.and(MARK_COUNT_MASK.not()).isZero()); + return rtn; + } + + /**************************************************************************** + * + * Header manipulation + */ + + /** + * Perform any required post allocation initialization + * + * @param object the object ref to the storage to be initialized + */ + @Inline + public void postAlloc(ObjectReference object) { + initializeHeader(object, true); + } + + /** + * Perform any required post copy (i.e. in-GC allocation) initialization. + * This is relevant (for example) when MS is used as the mature space in + * a copying GC. + * + * @param object the object ref to the storage to be initialized + * @param majorGC Is this copy happening during a major gc? + */ + @Inline + public void postCopy(ObjectReference object, boolean majorGC) { + initializeHeader(object, false); + if (!HEADER_MARK_BITS) { + testAndSetLiveBit(object); + } + } + + /** + * Perform any required initialization of the GC portion of the header. + * + * @param object the object ref to the storage to be initialized + * @param alloc is this initialization occuring due to (initial) allocation + * (true) or due to copying (false)? + */ + @Inline + public void initializeHeader(ObjectReference object, boolean alloc) { + if (HEADER_MARK_BITS) { + if (alloc) { + writeAllocState(object); + } else { + writeMarkState(object); + } + } + } + + /** + * Atomically attempt to set the mark bit of an object. Return true + * if successful, false if the mark bit was already set. + * + * @param object The object whose mark bit is to be written + * @param value The value to which the mark bits will be set + */ + @Inline + private static boolean testAndMark(ObjectReference object, Word value) { + int oldValue, markBits; + oldValue = VM.objectModel.readAvailableByte(object); + markBits = oldValue & MARK_BITS_MASK.toInt(); + if (markBits == value.toInt()) return false; + VM.objectModel.writeAvailableByte(object, (byte)(oldValue & ~MARK_BITS_MASK.toInt() | value.toInt())); + return true; + } + + /** + * Return true if the mark count for an object has the given value. + * + * @param object The object whose mark bit is to be tested + * @param value The value against which the mark bit will be tested + * @return True if the mark bit for the object has the given value. + */ + @Inline + public static boolean testMarkState(ObjectReference object, Word value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(MARK_COUNT_MASK.not()).isZero()); + return VM.objectModel.readAvailableBitsWord(object).and(MARK_COUNT_MASK).EQ(value); + } + + /** + * Write the allocState into the mark state fields of an object non-atomically. + * This is appropriate for allocation time initialization. + * + * @param object The object whose mark state is to be written + */ + @Inline + private void writeAllocState(ObjectReference object) { + Word oldValue = VM.objectModel.readAvailableBitsWord(object); + Word newValue = oldValue.and(MARK_BITS_MASK.not()).or(allocState); + VM.objectModel.writeAvailableBitsWord(object, newValue); + } + + /** + * Write the markState into the mark state fields of an object non-atomically. + * This is appropriate for collection time initialization. + * + * @param object The object whose mark state is to be written + */ + @Inline + private void writeMarkState(ObjectReference object) { + Word oldValue = VM.objectModel.readAvailableBitsWord(object); + Word newValue = oldValue.and(MARK_BITS_MASK.not()).or(markState); + VM.objectModel.writeAvailableBitsWord(object, newValue); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,85 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.FreeListPageResource; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one raw page space. + * + * This class provides access to raw memory for managing internal meta + * data. + */ + at Uninterruptible public final class RawPageSpace extends Space + implements Constants { + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume + * before consulting the plan + * @param vmRequest An object describing the virtual memory requested. + */ + public RawPageSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, false, false, vmRequest); + if (vmRequest.isDiscontiguous()) { + pr = new FreeListPageResource(pageBudget, this, 0); + } else { + pr = new FreeListPageResource(pageBudget, this, start, extent); + } + } + + public void prepare() { } + public void release() { } + + /** + * Release a group of pages that were allocated together. + * + * @param first The first page in the group of pages that were + * allocated together. + */ + @Inline + public void release(Address first) { + ((FreeListPageResource) pr).releasePages(first); + } + + /** + * Trace an object. + * + * This makes no sense for a raw page space and should never be + * called. + * + * @param object The object to be traced. + * @return zero: calling this is an error. + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + return ObjectReference.nullReference(); + } + + public boolean isLive(ObjectReference object) { + return true; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,992 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.utility.alloc.BlockAllocator; +import org.mmtk.utility.alloc.EmbeddedMetaData; +import org.mmtk.utility.heap.FreeListPageResource; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Conversions; +import org.mmtk.utility.Memory; + +import org.mmtk.vm.Lock; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one mark-sweep *space*. + * Each of the instance methods of this class may be called by any + * thread (i.e. synchronization must be explicit in any instance or + * class method). This contrasts with the MarkSweepLocal, where + * instances correspond to *plan* instances and therefore to kernel + * threads. Thus unlike this class, synchronization is not necessary + * in the instance methods of MarkSweepLocal. + */ + at Uninterruptible +public abstract class SegregatedFreeListSpace extends Space implements Constants { + + /**************************************************************************** + * + * Class variables + */ + protected static final boolean LAZY_SWEEP = true; + private static final boolean COMPACT_SIZE_CLASSES = false; + protected static final int MIN_CELLS = 6; + protected static final int MAX_CELLS = 99; // (1<<(INUSE_BITS-1))-1; + protected static final int MAX_CELL_SIZE = 8<<10; + public static final int MAX_FREELIST_OBJECT_BYTES = MAX_CELL_SIZE; + + // live bits etc + private static final int OBJECT_LIVE_SHIFT = LOG_MIN_ALIGNMENT; // 4 byte resolution + private static final int LOG_BIT_COVERAGE = OBJECT_LIVE_SHIFT; + private static final int LOG_LIVE_COVERAGE = LOG_BIT_COVERAGE + LOG_BITS_IN_BYTE; + private static final int LIVE_BYTES_PER_REGION = 1 << (EmbeddedMetaData.LOG_BYTES_IN_REGION - LOG_LIVE_COVERAGE); + private static final Word WORD_SHIFT_MASK = Word.one().lsh(LOG_BITS_IN_WORD).minus(Extent.one()); + private static final int LOG_LIVE_WORD_STRIDE = LOG_LIVE_COVERAGE + LOG_BYTES_IN_WORD; + private static final Extent LIVE_WORD_STRIDE = Extent.fromIntSignExtend(1< + * + * This is guaranteed to return pre-zeroed cells + * + * @param sizeClass The size class to be expanded + * @param freeList The free list to populate. + * @return The block that was just allocated. + */ + @Inline + private Address expandSizeClass(int sizeClass, AddressArray freeList) { + Address block = BlockAllocator.alloc(this, blockSizeClass[sizeClass]); + + if (block.isZero()) { + return Address.zero(); + } + + BlockAllocator.setNext(block, Address.zero()); + BlockAllocator.setAllClientSizeClass(block, blockSizeClass[sizeClass], (byte) sizeClass); + + notifyNewBlock(block, sizeClass); + + int cellExtent = cellSize[sizeClass]; + int blockSize = BlockAllocator.blockSize(blockSizeClass[sizeClass]); + int useableBlockSize = blockSize - blockHeaderSize[sizeClass]; + Address firstCell = block.plus(blockHeaderSize[sizeClass]); + Address sentinel = block.plus(blockSize); + + /* pre-zero the block */ + VM.memory.zero(firstCell, Extent.fromIntZeroExtend(useableBlockSize)); + + /* construct the free list */ + Address nextCell; + Address cell = firstCell; + while ((nextCell = cell.plus(cellExtent)).LT(sentinel)) { + cell.store(nextCell); + cell = nextCell; + } + + /* Populate the free list */ + freeList.set(sizeClass, firstCell); + return block; + } + + /**************************************************************************** + * + * Block management + */ + + /** + * Initialize the size class data structures. + */ + private void initSizeClasses() { + for (int sc = 0; sc < sizeClassCount(); sc++) { + cellSize[sc] = getBaseCellSize(sc); + for (byte blk = 0; blk < BlockAllocator.BLOCK_SIZE_CLASSES; blk++) { + int usableBytes = BlockAllocator.blockSize(blk); + int cells = usableBytes / cellSize[sc]; + blockSizeClass[sc] = blk; + /* cells must start at multiple of MIN_ALIGNMENT because + cellSize is also supposed to be multiple, this should do + the trick: */ + blockHeaderSize[sc] = BlockAllocator.blockSize(blk) - cells * cellSize[sc]; + if (((usableBytes < BYTES_IN_PAGE) && (cells*2 > MAX_CELLS)) || + ((usableBytes > (BYTES_IN_PAGE>>1)) && (cells > MIN_CELLS))) + break; + } + } + } + + /** + * Get the size class for a given number of bytes. + * + * We use size classes based on a worst case internal fragmentation + * loss target of 1/8. In fact, across sizes from 8 bytes to 512 + * the average worst case loss is 13.3%, giving an expected loss + * (assuming uniform distribution) of about 7%. We avoid using the + * Lea class sizes because they were so numerous and therefore + * liable to lead to excessive inter-class-size fragmentation.

+ * + * This method may segregate arrays and scalars (currently it does + * not).

+ * + * This method should be more intelligent and take alignment requests + * into consideration. The issue with this is that the block header + * which can be varied by subclasses can change the alignment of the + * cells.

+ * + * @param bytes The number of bytes required to accommodate the object + * to be allocated. + * @return The size class capable of accommodating the allocation request. + */ + @Inline + public final int getSizeClass(int bytes) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((bytes > 0) && (bytes <= MAX_CELL_SIZE)); + + int sz1 = bytes - 1; + + if (BYTES_IN_ADDRESS == 4) { // 32-bit + if (COMPACT_SIZE_CLASSES) + return ( + (sz1 <= 31) ? (sz1 >> 2) : // 4 bytes apart + (sz1 <= 63) ? 4 + (sz1 >> 3) : // 8 bytes apart + (sz1 <= 95) ? 8 + (sz1 >> 4) : // 16 bytes apart + (sz1 <= 223) ? 14 + (sz1 >> 6) : // 64 bytes apart + (sz1 <= 734) ? 17 + (sz1 >> 8) : // 256 bytes apart + 20 + (sz1 >> 10)); // 1024 bytes apart + else + return ( + (sz1 <= 63) ? (sz1 >> 2) : // 4 bytes apart + (sz1 <= 127) ? 12 + (sz1 >> 4) : // 16 bytes apart + (sz1 <= 255) ? 16 + (sz1 >> 5) : // 32 bytes apart + (sz1 <= 511) ? 20 + (sz1 >> 6) : // 64 bytes apart + (sz1 <= 2047) ? 26 + (sz1 >> 8) : // 256 bytes apart + 32 + (sz1 >> 10)); // 1024 bytes apart + } else { // 64-bit + if (COMPACT_SIZE_CLASSES) + return ( + (sz1 <= 95) ? (sz1 >> 3) : // 8 bytes apart + (sz1 <= 127) ? 6 + (sz1 >> 4) : // 16 bytes apart + (sz1 <= 191) ? 10 + (sz1 >> 5) : // 32 bytes apart + (sz1 <= 383) ? 13 + (sz1 >> 6) : // 64 bytes apart + (sz1 <= 511) ? 16 + (sz1 >> 7) : // 128 bytes apart + (sz1 <= 1023) ? 19 + (sz1 >> 9) : // 512 bytes apart + 20 + (sz1 >> 10)); // 1024 bytes apart + else + return ( + (sz1 <= 111) ? (sz1 >> 3) : // 8 bytes apart + (sz1 <= 223) ? 7 + (sz1 >> 4) : // 16 bytes apart + (sz1 <= 319) ? 14 + (sz1 >> 5) : // 32 bytes apart + (sz1 <= 575) ? 19 + (sz1 >> 6) : // 64 bytes apart + (sz1 <= 2047) ? 26 + (sz1 >> 8) : // 256 bytes apart + 32 + (sz1 >> 10)); // 1024 bytes apart + } + } + + /** + * Return the size of a basic cell (i.e. not including any cell + * header) for a given size class. + * + * @param sc The size class in question + * @return The size of a basic cell (i.e. not including any cell + * header). + */ + @Inline + public final int getBaseCellSize(int sc) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((sc >= 0) && (sc < sizeClassCount())); + + if (BYTES_IN_ADDRESS == 4) { // 32-bit + if (COMPACT_SIZE_CLASSES) + return ((sc < 8) ? (sc + 1) << 2: + (sc < 12) ? (sc - 3) << 3: + (sc < 16) ? (sc - 7) << 4: + (sc < 18) ? (sc - 13) << 6: + (sc < 21) ? (sc - 16) << 8: + (sc - 19) << 10); + else + return ((sc < 16) ? (sc + 1) << 2: + (sc < 20) ? (sc - 11) << 4: + (sc < 24) ? (sc - 15) << 5: + (sc < 28) ? (sc - 19) << 6: + (sc < 34) ? (sc - 25) << 8: + (sc - 31) << 10); + } else { // 64-bit + if (COMPACT_SIZE_CLASSES) + return ((sc < 12) ? (sc + 1) << 3: + (sc < 14) ? (sc - 5) << 4: + (sc < 16) ? (sc - 9) << 5: + (sc < 19) ? (sc - 12) << 6: + (sc < 20) ? (sc - 15) << 7: + (sc < 21) ? (sc - 18) << 9: + (sc - 19) << 10); + else + return ((sc < 14) ? (sc + 1) << 3: + (sc < 21) ? (sc - 6) << 4: + (sc < 24) ? (sc - 13) << 5: + (sc < 28) ? (sc - 18) << 6: + (sc < 34) ? (sc - 25) << 8: + (sc - 31) << 10); + } + } + + /** + * The number of distinct size classes. + */ + @Inline + public static int sizeClassCount() { + return (COMPACT_SIZE_CLASSES) ? 28 : 40; + } + + /**************************************************************************** + * + * Preserving (saving & restoring) free lists + */ + + /** + * Prepare a block for allocation, returning a free list into the block. + * + * @param block The new block + * @param sizeClass The block's sizeclass. + */ + protected abstract Address advanceToBlock(Address block, int sizeClass); + + /** + * Notify that a new block has been installed. + * + * @param block The new block + * @param sizeClass The block's sizeclass. + */ + protected void notifyNewBlock(Address block, int sizeClass) {} + + /** + * Should the sweep reclaim the cell containing this object. Is this object + * live. This is only used when maintainSideBitmap is false. + * + * @param object The object to query + * @return True if the cell should be reclaimed + */ + protected boolean reclaimCellForObject(ObjectReference object) { + VM.assertions.fail("Must implement reclaimCellForObject if not maintaining side bitmap"); + return false; + } + + /**************************************************************************** + * + * Metadata manipulation + */ + + /** + * In the case where free lists associated with each block are + * preserved, get the free list for a given block. + * + * @param block The block whose free list is to be found + * @return The free list for this block + */ + @Inline + protected final Address getFreeList(Address block) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(preserveFreeList()); + return BlockAllocator.getFreeListMeta(block); + } + + /** + * In the case where free lists associated with each block are + * preserved, set the free list for a given block. + * + * @param block The block whose free list is to be found + * @param cell The head of the free list (i.e. the first cell in the + * free list). + */ + @Inline + protected final void setFreeList(Address block, Address cell) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(preserveFreeList()); + BlockAllocator.setFreeListMeta(block, cell); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Clear all block marks for this space. This method is important when + * it is desirable to do partial collections, which man mean that block + * marks need to be explicitly cleared when necessary. + */ + protected final void clearAllBlockMarks() { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!maintainSideBitmap()); + for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) { + Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass])); + /* Flushed blocks */ + Address block = flushedBlockHead.get(sizeClass); + while (!block.isZero()) { + Address next = BlockAllocator.getNext(block); + clearBlockMark(block, blockSize); + block = next; + } + /* Available blocks */ + block = consumedBlockHead.get(sizeClass); + while (!block.isZero()) { + Address next = BlockAllocator.getNext(block); + clearBlockMark(block, blockSize); + block = next; + } + } + } + + /** + * Sweep all blocks for free objects. + * + * @param clearMarks should we clear block mark bits as we process. + */ + protected final void sweepConsumedBlocks(boolean clearMarks) { + for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) { + Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass])); + Address availableHead = Address.zero(); + /* Flushed blocks */ + Address block = flushedBlockHead.get(sizeClass); + flushedBlockHead.set(sizeClass, Address.zero()); + while (!block.isZero()) { + Address next = BlockAllocator.getNext(block); + availableHead = sweepBlock(block, sizeClass, blockSize, availableHead, clearMarks); + block = next; + } + /* Consumed blocks */ + block = consumedBlockHead.get(sizeClass); + consumedBlockHead.set(sizeClass, Address.zero()); + while (!block.isZero()) { + Address next = BlockAllocator.getNext(block); + availableHead = sweepBlock(block, sizeClass, blockSize, availableHead, clearMarks); + block = next; + } + /* Make blocks available */ + availableBlockHead.set(sizeClass, availableHead); + } + } + + /** + * Sweep a block, freeing it and adding to the list given by availableHead + * if it contains no free objects. + * + * @param clearMarks should we clear block mark bits as we process. + */ + protected final Address sweepBlock(Address block, int sizeClass, Extent blockSize, Address availableHead, boolean clearMarks) { + boolean liveBlock = containsLiveCell(block, blockSize, clearMarks); + if (!liveBlock) { + BlockAllocator.setNext(block, Address.zero()); + BlockAllocator.free(this, block); + } else { + BlockAllocator.setNext(block, availableHead); + availableHead = block; + if (!LAZY_SWEEP) { + setFreeList(block, makeFreeList(block, sizeClass)); + } + } + return availableHead; + } + + /** + * Eagerly consume all remaining blocks. + */ + protected final void consumeBlocks() { + for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) { + while (!getAllocationBlock(sizeClass, null).isZero()); + } + } + + /** + * Flush all the allocation blocks to the consumed list. + */ + protected final void flushAvailableBlocks() { + for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) { + flushedBlockHead.set(sizeClass, availableBlockHead.get(sizeClass)); + availableBlockHead.set(sizeClass, Address.zero()); + } + } + + /** + * Does this block contain any live cells. + * + * @param block The block + * @param blockSize The size of the block + * @param clearMarks should we clear block mark bits as we process. + * @return True if any cells in the block are live + */ + @Inline + protected boolean containsLiveCell(Address block, Extent blockSize, boolean clearMarks) { + if (maintainSideBitmap()) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(alignToLiveStride(block).EQ(block)); + Address cursor = getLiveWordAddress(block); + Address sentinel = getLiveWordAddress(block.plus(blockSize.minus(1))); + while (cursor.LE(sentinel)) { + Word live = cursor.loadWord(); + if (!live.isZero()) { + return true; + } + cursor = cursor.plus(BYTES_IN_WORD); + } + return false; + } else { + boolean live = false; + Address cursor = block; + while(cursor.LT(block.plus(blockSize))) { + live |= BlockAllocator.checkBlockMeta(cursor); + if (clearMarks) + BlockAllocator.clearBlockMeta(cursor); + cursor = cursor.plus(1 << BlockAllocator.LOG_MIN_BLOCK); + } + return live; + } + } + + + /** + * Clear block marks for a block + * + * @param block The block + * @param blockSize The size of the block + */ + @Inline + protected void clearBlockMark(Address block, Extent blockSize) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!maintainSideBitmap()); + Address cursor = block; + while(cursor.LT(block.plus(blockSize))) { + BlockAllocator.clearBlockMeta(cursor); + cursor = cursor.plus(1 << BlockAllocator.LOG_MIN_BLOCK); + } + } + + /** + * In the cell containing this object live? + * + * @param object The object + * @return True if the cell is live + */ + @Inline + protected boolean isCellLive(ObjectReference object) { + /* Must override if not using the side bitmap */ + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(maintainSideBitmap()); + return liveBitSet(object); + } + + /** + * Use the live bits for a block to infer free cells and thus + * construct a free list for the block. + * + * @param block The block to be processed + * @param sizeClass The size class for the block + * @return The head of the new free list + */ + @Inline + protected final Address makeFreeList(Address block, int sizeClass) { + Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass])); + Address cursor = block.plus(blockHeaderSize[sizeClass]); + Address lastFree = Address.zero(); + Address firstFree = Address.zero(); + Address end = block.plus(blockSize); + Extent cellExtent = Extent.fromIntSignExtend(cellSize[sizeClass]); + while (cursor.LT(end)) { + ObjectReference current = VM.objectModel.getObjectFromStartAddress(cursor); + boolean free = true; + if (!current.isNull()) { + free = !isCellLive(current); + } + if (free) { + if (firstFree.isZero()) { + firstFree = cursor; + } else { + lastFree.store(cursor); + } + Memory.zeroSmall(cursor, cellExtent); + lastFree = cursor; + } + cursor = cursor.plus(cellExtent); + } + return firstFree; + } + + /** + * Sweep all blocks for free objects. + */ + public void sweepCells(Sweeper sweeper) { + for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) { + Address availableHead = Address.zero(); + /* Flushed blocks */ + Address block = flushedBlockHead.get(sizeClass); + flushedBlockHead.set(sizeClass, Address.zero()); + while (!block.isZero()) { + Address next = BlockAllocator.getNext(block); + availableHead = sweepCells(sweeper, block, sizeClass, availableHead); + block = next; + } + /* Consumed blocks */ + block = consumedBlockHead.get(sizeClass); + consumedBlockHead.set(sizeClass, Address.zero()); + while (!block.isZero()) { + Address next = BlockAllocator.getNext(block); + availableHead = sweepCells(sweeper, block, sizeClass, availableHead); + block = next; + } + /* Make blocks available */ + availableBlockHead.set(sizeClass, availableHead); + } + } + + /** + * Sweep a block, freeing it and adding to the list given by availableHead + * if it contains no free objects. + */ + private Address sweepCells(Sweeper sweeper, Address block, int sizeClass, Address availableHead) { + boolean liveBlock = sweepCells(sweeper, block, sizeClass); + if (!liveBlock) { + BlockAllocator.setNext(block, Address.zero()); + BlockAllocator.free(this, block); + } else { + BlockAllocator.setNext(block, availableHead); + availableHead = block; + } + return availableHead; + } + + /** + * Sweep a block, freeing it and making it available if any live cells were found. + * if it contains no free objects. + * + * This is designed to be called in parallel by multiple collector threads. + */ + public void parallelSweepCells(Sweeper sweeper) { + for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) { + Address block; + while(!(block = getSweepBlock(sizeClass)).isZero()) { + boolean liveBlock = sweepCells(sweeper, block, sizeClass); + if (!liveBlock) { + BlockAllocator.setNext(block, Address.zero()); + BlockAllocator.free(this, block); + } else { + lock.acquire(); + BlockAllocator.setNext(block, availableBlockHead.get(sizeClass)); + availableBlockHead.set(sizeClass, block); + lock.release(); + } + } + } + } + + /** + * Get a block for a parallel sweep. + * + * @param sizeClass The size class of the block to sweep. + * @return The block or zero if no blocks remain to be swept. + */ + private Address getSweepBlock(int sizeClass) { + lock.acquire(); + Address block; + + /* Flushed blocks */ + block = flushedBlockHead.get(sizeClass); + if (!block.isZero()) { + flushedBlockHead.set(sizeClass, BlockAllocator.getNext(block)); + lock.release(); + BlockAllocator.setNext(block, Address.zero()); + return block; + } + + /* Consumed blocks */ + block = consumedBlockHead.get(sizeClass); + if (!block.isZero()) { + flushedBlockHead.set(sizeClass, BlockAllocator.getNext(block)); + lock.release(); + BlockAllocator.setNext(block, Address.zero()); + return block; + } + + /* All swept! */ + lock.release(); + return Address.zero(); + } + + /** + * Does this block contain any live cells? + */ + @Inline + public boolean sweepCells(Sweeper sweeper, Address block, int sizeClass) { + Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass])); + Address cursor = block.plus(blockHeaderSize[sizeClass]); + Address end = block.plus(blockSize); + Extent cellExtent = Extent.fromIntSignExtend(cellSize[sizeClass]); + boolean containsLive = false; + while (cursor.LT(end)) { + ObjectReference current = VM.objectModel.getObjectFromStartAddress(cursor); + boolean free = true; + if (!current.isNull()) { + free = !liveBitSet(current); + if (!free) { + free = sweeper.sweepCell(current); + if (free) unsyncClearLiveBit(current); + } + } + if (!free) { + containsLive = true; + } + cursor = cursor.plus(cellExtent); + } + return containsLive; + } + + /** + * A callback used to perform sweeping of a free list space. + */ + @Uninterruptible + public abstract static class Sweeper { + public abstract boolean sweepCell(ObjectReference object); + } + + /**************************************************************************** + * + * Live bit manipulation + */ + + /** + * Atomically set the live bit for a given object + * + * @param object The object whose live bit is to be set. + * @return True if the bit was changed to true. + */ + @Inline + public static boolean testAndSetLiveBit(ObjectReference object) { + return updateLiveBit(VM.objectModel.objectStartRef(object), true, true); + } + + /** + * Set the live bit for the block containing the given object + * + * @param object The object whose blocks liveness is to be set. + */ + @Inline + protected static void markBlock(ObjectReference object) { + BlockAllocator.markBlockMeta(object); + } + + /** + * Set the live bit for the given block. + * + * @param block The block whose liveness is to be set. + */ + @Inline + protected static void markBlock(Address block) { + BlockAllocator.markBlockMeta(block); + } + + /** + * Set the live bit for a given object, without using + * synchronization primitives---must only be used when contention + * for live bit is strictly not possible + * + * @param object The object whose live bit is to be set. + */ + @Inline + public static boolean unsyncSetLiveBit(ObjectReference object) { + return updateLiveBit(VM.objectModel.refToAddress(object), true, false); + } + + /** + * Set the live bit for a given address + * + * @param address The address whose live bit is to be set. + * @param set True if the bit is to be set, as opposed to cleared + * @param atomic True if we want to perform this operation atomically + */ + @Inline + private static boolean updateLiveBit(Address address, boolean set, boolean atomic) { + Word oldValue, newValue; + Address liveWord = getLiveWordAddress(address); + Word mask = getMask(address, true); + if (atomic) { + do { + oldValue = liveWord.prepareWord(); + newValue = (set) ? oldValue.or(mask) : oldValue.and(mask.not()); + } while (!liveWord.attempt(oldValue, newValue)); + } else { + oldValue = liveWord.loadWord(); + liveWord.store(set ? oldValue.or(mask) : oldValue.and(mask.not())); + } + return oldValue.and(mask).NE(mask); + } + + /** + * Test the live bit for a given object + * + * @param object The object whose live bit is to be set. + */ + @Inline + protected static boolean liveBitSet(ObjectReference object) { + return liveBitSet(VM.objectModel.refToAddress(object)); + } + + /** + * Set the live bit for a given address + * + * @param address The address whose live bit is to be set. + * @return true if this operation changed the state of the live bit. + */ + @Inline + protected static boolean liveBitSet(Address address) { + Address liveWord = getLiveWordAddress(address); + Word mask = getMask(address, true); + Word value = liveWord.loadWord(); + return value.and(mask).EQ(mask); + } + + /** + * Clear the live bit for a given object + * + * @param object The object whose live bit is to be cleared. + */ + @Inline + protected static void clearLiveBit(ObjectReference object) { + clearLiveBit(VM.objectModel.refToAddress(object)); + } + + /** + * Clear the live bit for a given address + * + * @param address The address whose live bit is to be cleared. + */ + @Inline + protected static void clearLiveBit(Address address) { + updateLiveBit(address, false, true); + } + + /** + * Clear the live bit for a given object + * + * @param object The object whose live bit is to be cleared. + */ + @Inline + protected static void unsyncClearLiveBit(ObjectReference object) { + unsyncClearLiveBit(VM.objectModel.refToAddress(object)); + } + + /** + * Clear the live bit for a given address + * + * @param address The address whose live bit is to be cleared. + */ + @Inline + protected static void unsyncClearLiveBit(Address address) { + updateLiveBit(address, false, false); + } + + /** + * Clear all live bits for a block + */ + protected void clearLiveBits(Address block, int sizeClass) { + int blockSize = BlockAllocator.blockSize(blockSizeClass[sizeClass]); + Address cursor = getLiveWordAddress(block); + Address sentinel = getLiveWordAddress(block.plus(blockSize - 1)); + while (cursor.LE(sentinel)) { + cursor.store(Word.zero()); + cursor = cursor.plus(BYTES_IN_WORD); + } + } + + /** + * Clear all live bits + */ + protected static void zeroLiveBits(Address start, Address end) { + Extent bytes = Extent.fromIntSignExtend(EmbeddedMetaData.BYTES_IN_REGION>>LOG_LIVE_COVERAGE); + while (start.LT(end)) { + Address metadata = EmbeddedMetaData.getMetaDataBase(start).plus(META_DATA_OFFSET); + VM.memory.zero(metadata, bytes); + start = start.plus(EmbeddedMetaData.BYTES_IN_REGION); + } + } + + /** + * Align an address so that it corresponds to a live word boundary. + * In other words, if the live bit for the given address is not the + * zeroth bit of a live word, round the address down such that it + * does. + * + * @param address The address to be aligned to a live word + * @return The given address, aligned down so that it corresponds to + * an address on a live word boundary. + */ + private static Address alignToLiveStride(Address address) { + return address.toWord().and(LIVE_WORD_STRIDE_MASK).toAddress(); + } + + /** + * Given an address, produce a bit mask for the live table + * + * @param address The address whose live bit mask is to be established + * @param set True if we want the mask for setting the bit, + * false if we want the mask for clearing the bit. + * @return The appropriate bit mask for object for the live table for. + */ + @Inline + private static Word getMask(Address address, boolean set) { + int shift = address.toWord().rshl(OBJECT_LIVE_SHIFT).and(WORD_SHIFT_MASK).toInt(); + Word rtn = Word.one().lsh(shift); + return (set) ? rtn : rtn.not(); + } + + /** + * Given an address, return the address of the live word for + * that address. + * + * @param address The address whose live word address is to be returned + * @return The address of the live word for this object + */ + @Inline + private static Address getLiveWordAddress(Address address) { + Address rtn = EmbeddedMetaData.getMetaDataBase(address); + return rtn.plus(META_DATA_OFFSET).plus(EmbeddedMetaData.getMetaDataOffset(address, LOG_LIVE_COVERAGE, LOG_BYTES_IN_WORD)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,704 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.heap.Map; +import org.mmtk.utility.heap.Mmapper; +import org.mmtk.utility.heap.PageResource; +import org.mmtk.utility.heap.SpaceDescriptor; +import org.mmtk.utility.heap.VMRequest; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.Log; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class defines and manages spaces. Each policy is an instance + * of a space. A space is a region of virtual memory (contiguous or + * discontigous) which is subject to the same memory management + * regime. Multiple spaces (instances of this class or its + * descendants) may have the same policy (eg there could be numerous + * instances of CopySpace, each with different roles). Spaces are + * defined in terms of a unique region of virtual memory, so no two + * space instances ever share any virtual memory.

+ * + * In addition to tracking virtual memory use and the mapping to + * policy, spaces also manage memory consumption (used virtual + * memory).

+ * + */ + at Uninterruptible +public abstract class Space implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + private static boolean DEBUG = false; + + // the following is somewhat arbitrary for the 64 bit system at this stage + public static final int LOG_ADDRESS_SPACE = (BYTES_IN_ADDRESS == 4) ? 32 : 40; + public static final int LOG_BYTES_IN_CHUNK = 22; + public static final int BYTES_IN_CHUNK = 1 << LOG_BYTES_IN_CHUNK; + public static final int PAGES_IN_CHUNK = 1 << (LOG_BYTES_IN_CHUNK - LOG_BYTES_IN_PAGE); + private static final int LOG_MAX_CHUNKS = LOG_ADDRESS_SPACE - LOG_BYTES_IN_CHUNK; + public static final int MAX_CHUNKS = 1 << LOG_MAX_CHUNKS; + public static final int MAX_SPACES = 20; // quite arbitrary + + public static final Address HEAP_START = chunkAlign(VM.HEAP_START, true); + public static final Address AVAILABLE_START = chunkAlign(VM.AVAILABLE_START, false); + public static final Address AVAILABLE_END = chunkAlign(VM.AVAILABLE_END, true); + public static final Extent AVAILABLE_BYTES = AVAILABLE_END.toWord().minus(AVAILABLE_START.toWord()).toExtent(); + public static final int AVAILABLE_PAGES = AVAILABLE_BYTES.toWord().rshl(LOG_BYTES_IN_PAGE).toInt(); + public static final Address HEAP_END = chunkAlign(VM.HEAP_END, false); + + private static final boolean FORCE_SLOW_MAP_LOOKUP = false; + + private static final int PAGES = 0; + private static final int MB = 1; + private static final int PAGES_MB = 2; + private static final int MB_PAGES = 3; + + private static int spaceCount = 0; + private static Space[] spaces = new Space[MAX_SPACES]; + private static Address heapCursor = HEAP_START; + private static Address heapLimit = HEAP_END; + + /**************************************************************************** + * + * Instance variables + */ + private final String name; + private final int nameLength; + protected final int descriptor; + private final int index; + private final VMRequest vmRequest; + + protected final boolean immortal; + protected final boolean movable; + protected final boolean contiguous; + + protected PageResource pr; + protected final Address start; + protected final Extent extent; + protected Address lastDiscontiguousRegion; + + private boolean allocationFailed; + + /**************************************************************************** + * + * Initialization + */ + + { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(PAGES_IN_CHUNK > 1); + } + + /** + * This is the base constructor for all spaces.

+ * + * @param name The name of this space (used when printing error messages etc) + * @param movable Are objects in this space movable? + * @param immortal Are objects in this space immortal (uncollected)? + * @param vmRequest An object describing the virtual memory requested. + */ + protected Space(String name, boolean movable, boolean immortal, VMRequest vmRequest) { + this.name = name; + this.nameLength = name.length(); // necessary to avoid calling length() in uninterruptible code + this.movable = movable; + this.immortal = immortal; + this.vmRequest = vmRequest; + this.index = spaceCount++; + spaces[index] = this; + + if (vmRequest.type == VMRequest.REQUEST_DISCONTIGUOUS) { + this.contiguous = false; + this.descriptor = SpaceDescriptor.createDescriptor(); + this.start = Address.zero(); + this.extent = Extent.zero(); + this.lastDiscontiguousRegion = Address.zero(); + VM.memory.setHeapRange(index, HEAP_START, HEAP_END); // this should really be refined! Once we have a code space, we can be a lot more specific about what is a valid code heap area + return; + } + + Address start; + Extent extent; + + if (vmRequest.type == VMRequest.REQUEST_FRACTION) { + extent = getFracAvailable(vmRequest.frac); + } else { + extent = vmRequest.extent; + } + + if (extent.NE(chunkAlign(extent, false))) { + VM.assertions.fail(name + " requested non-aligned extent: " + extent.toLong() + " bytes"); + } + + if (vmRequest.type == VMRequest.REQUEST_FIXED) { + start = vmRequest.start; + if (start.NE(chunkAlign(start, false))) { + VM.assertions.fail(name + " starting on non-aligned boundary: " + start.toLong() + " bytes"); + } + } else if (vmRequest.top) { + heapLimit = heapLimit.minus(extent); + start = heapLimit; + } else { + start = heapCursor; + heapCursor = heapCursor.plus(extent); + } + + if (heapCursor.GT(heapLimit)) { + Log.write("Out of virtual address space allocating \""); + Log.write(name); Log.write("\" at "); + Log.write(heapCursor.minus(extent)); Log.write(" ("); + Log.write(heapCursor); Log.write(" > "); + Log.write(heapLimit); Log.writeln(")"); + VM.assertions.fail("exiting"); + } + + this.contiguous = true; + this.start = start; + this.extent = extent; + this.descriptor = SpaceDescriptor.createDescriptor(start, start.plus(extent)); + + VM.memory.setHeapRange(index, start, start.plus(extent)); + Map.insert(start, extent, descriptor, this); + + if (DEBUG) { + Log.write(name); Log.write(" "); + Log.write(start); Log.write(" "); + Log.write(start.plus(extent)); Log.write(" "); + Log.writeln(extent.toWord()); + } + } + + /**************************************************************************** + * + * Accessor methods + */ + + /** Start of discontig getter @return The start of the discontiguous space */ + public static Address getDiscontigStart() { return heapCursor; } + + /** End of discontig getter @return The end of the discontiguous space */ + public static Address getDiscontigEnd() { return heapLimit.minus(1); } + + /** Name getter @return The name of this space */ + public final String getName() { return name; } + + /** Start getter @return The start address of this space */ + public final Address getStart() { return start; } + + /** Extent getter @return The size (extent) of this space */ + public final Extent getExtent() { return extent; } + + /** Descriptor method @return The integer descriptor for this space */ + public final int getDescriptor() { return descriptor; } + + /** Index getter @return The index (ordinal number) of this space */ + public final int getIndex() { return index; } + + /** Immortal getter @return True if this space is never collected */ + public final boolean isImmortal() { return immortal; } + + /** Movable getter @return True if objects in this space may move */ + public final boolean isMovable() { return movable; } + + /** Allocationfailed getter @return true if an allocation has failed since GC */ + public final boolean allocationFailed() { return allocationFailed; } + + /** Clear Allocationfailed flag */ + public final void clearAllocationFailed() { allocationFailed = false; } + + /** ReservedPages getter @return The number of reserved pages */ + public final int reservedPages() { return pr.reservedPages(); } + + /** CommittedPages getter @return The number of committed pages */ + public final int committedPages() { return pr.committedPages(); } + + /** RequiredPages getter @return The number of required pages */ + public final int requiredPages() { return pr.requiredPages(); } + + /** AvailablePages getter @return The number of pages available for allocation */ + public final int availablePhysicalPages() { return pr.getAvailablePhysicalPages(); } + + /** Cumulative committed pages getter @return Cumulative committed pages. */ + public static long cumulativeCommittedPages() { + return PageResource.cumulativeCommittedPages(); + } + + /**************************************************************************** + * + * Object and address tests / accessors + */ + + /** + * Return true if the given object is in an immortal (uncollected) space. + * + * @param object The object in question + * @return True if the given object is in an immortal (uncollected) space. + */ + public static boolean isImmortal(ObjectReference object) { + Space space = getSpaceForObject(object); + if (space == null) + return true; + else + return space.isImmortal(); + } + + /** + * Return true if the given object is in space that moves objects. + * + * @param object The object in question + * @return True if the given object is in space that moves objects. + */ + @Inline + public static boolean isMovable(ObjectReference object) { + Space space = getSpaceForObject(object); + if (space == null) + return true; + else + return space.isMovable(); + } + + /** + * Return true if the given object is in a space managed by MMTk. + * + * @param object The object in question + * @return True if the given object is in a space managed by MMTk. + */ + @Inline + public static boolean isMappedObject(ObjectReference object) { + return !object.isNull() && (getSpaceForObject(object) != null) && Mmapper.objectIsMapped(object); + } + + /** + * Return true if the given address is in a space managed by MMTk. + * + * @param address The address in question + * @return True if the given address is in a space managed by MMTk. + */ + @Inline + public static boolean isMappedAddress(Address address) { + return Map.getSpaceForAddress(address) != null && Mmapper.addressIsMapped(address); + } + + /** + * Return true if the given object is the space associated with the + * given descriptor. + * + * @param descriptor The descriptor for a space + * @param object The object in question + * @return True if the given object is in the space associated with + * the descriptor. + */ + @Inline + public static boolean isInSpace(int descriptor, ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull()); + return isInSpace(descriptor, VM.objectModel.refToAddress(object)); + } + + /** + * Return true if the given address is the space associated with the + * given descriptor. + * + * @param descriptor The descriptor for a space + * @param address The address in question. + * @return True if the given address is in the space associated with + * the descriptor. + */ + @Inline + public static boolean isInSpace(int descriptor, Address address) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!address.isZero()); + if (FORCE_SLOW_MAP_LOOKUP || !SpaceDescriptor.isContiguous(descriptor)) { + return Map.getDescriptorForAddress(address) == descriptor; + } else { + Address start = SpaceDescriptor.getStart(descriptor); + if (!VM.VERIFY_ASSERTIONS && + SpaceDescriptor.isContiguousHi(descriptor)) + return address.GE(start); + else { + Extent size = Word.fromIntSignExtend(SpaceDescriptor.getChunks(descriptor)).lsh(LOG_BYTES_IN_CHUNK).toExtent(); + Address end = start.plus(size); + return address.GE(start) && address.LT(end); + } + } + } + + /** + * Return the space for a given object + * + * @param object The object in question + * @return The space containing the object + */ + @Inline + public static Space getSpaceForObject(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull()); + return Map.getSpaceForAddress(VM.objectModel.refToAddress(object)); + } + + /**************************************************************************** + * + * Page management + */ + + /** + * Acquire a number of pages from the page resource, returning + * either the address of the first page, or zero on failure.

+ * + * This may trigger a GC if necessary.

+ * + * First the page budget is checked to see whether polling the GC is + * necessary. If so, the GC is polled. If a GC is required then the + * request fails and zero is returned.

+ * + * If the check of the page budget does not lead to GC being + * triggered, then a request is made for specific pages in virtual + * memory. If the page manager cannot satisify this request, then + * the request fails, a GC is forced, and zero is returned. + * Otherwise the address of the first page is returned.

+ * + * @param pages The number of pages requested + * @return The start of the first page if successful, zero on + * failure. + */ + public final Address acquire(int pages) { + boolean allowPoll = !Plan.gcInProgress() && Plan.isInitialized() && !VM.collection.isEmergencyAllocation(); + + /* First check page budget and poll if necessary */ + if (!pr.reservePages(pages)) { + /* Need to poll, either fixing budget or requiring GC */ + if (allowPoll && VM.activePlan.global().poll(false, this)) { + pr.clearRequest(pages); + return Address.zero(); // GC required, return failure + } + } + + /* Page budget is ok, try to acquire virtual memory */ + Address rtn = pr.getNewPages(pages); + if (rtn.isZero()) { + /* Failed, so force a GC */ + if (VM.collection.isEmergencyAllocation()) { + pr.clearRequest(pages); + VM.assertions.fail("Failed emergency allocation"); + } + if (!allowPoll) VM.assertions.fail("Physical allocation failed during special (collection/emergency) allocation!"); + allocationFailed = true; + VM.collection.reportPhysicalAllocationFailed(); + VM.activePlan.global().poll(true, this); + pr.clearRequest(pages); + return Address.zero(); + } + + if (allowPoll) VM.collection.reportAllocationSuccess(); + return rtn; + } + + /** + * Extend the virtual memory associated with a particular discontiguous + * space. This simply involves requesting a suitable number of chunks + * from the pool of chunks available to discontiguous spaces. + * + * @param chunks The number of chunks by which the space needs to be extended + * @return The address of the new discontiguous space. + */ + public Address growDiscontiguousSpace(int chunks) { + this.lastDiscontiguousRegion = Map.allocateContiguousChunks(descriptor, this, chunks, lastDiscontiguousRegion); + return lastDiscontiguousRegion; + } + + /** + * Return the number of chunks required to satisfy a request for a certain number of pages + * + * @param pages The number of pages desired + * @return The number of chunks needed to satisfy the request + */ + public static int requiredChunks(int pages) { + Extent extent = chunkAlign(Extent.fromIntZeroExtend(pages<"); + Log.write(space.start.plus(space.extent.minus(1))); + if (space.vmRequest.type == VMRequest.REQUEST_EXTENT) { + Log.write(" E "); Log.write(space.vmRequest.extent); + } else if (space.vmRequest.type == VMRequest.REQUEST_FRACTION) { + Log.write(" F "); Log.write(space.vmRequest.frac); + } + Log.writeln(); + } else { + Log.write("D ["); + for(Address a = space.lastDiscontiguousRegion; !a.isZero(); a = Map.getNextContiguousRegion(a)) { + Log.write(a); Log.write("->"); + Log.write(a.plus(Map.getContiguousRegionSize(a).minus(1))); + if (Map.getNextContiguousRegion(a) != Address.zero()) + Log.write(", "); + } + Log.writeln("]"); + } + } + Log.write(" AVAILABLE_END "); Log.writeln(AVAILABLE_END); + Log.write(" HEAP_END "); Log.writeln(HEAP_END); + } + + /** + * Interface to use to implement the Visitor Pattern for Spaces. + */ + public static interface SpaceVisitor { + void visit(Space s); + } + + /** + * Implement the Visitor Pattern for Spaces. + * @param v The visitor to perform on each Space instance + */ + @Interruptible + public static void visitSpaces(SpaceVisitor v) { + for (int i = 0; i < spaceCount; i++) { + v.visit(spaces[i]); + } + } + + + /** + * Ensure that all MMTk spaces (all spaces aside from the VM space) + * are mapped. Demand zero map all of them if they are not already + * mapped. + */ + @Interruptible + public static void eagerlyMmapMMTkSpaces() { + for (int i = 0; i < spaceCount; i++) { + Space space = spaces[i]; + if (space != VM.memory.getVMSpace()) { + if (Options.verbose.getValue() > 2) { + Log.write("Mapping "); + Log.write(space.name); + Log.write(" "); + Log.write(space.start); + Log.write("->"); + Log.writeln(space.start.plus(space.extent.minus(1))); + } + Mmapper.ensureMapped(space.start, space.extent.toInt()>>LOG_BYTES_IN_PAGE); + } + } + } + + /** + * Print out the memory used by all spaces in either megabytes or + * pages. + * + * @param mode An enumeration type that specifies the format for the + * prining (PAGES, MB, PAGES_MB, or MB_PAGES). + */ + private static void printUsage(int mode) { + Log.write("used = "); + printPages(getPagesReserved(), mode); + boolean first = true; + for (int i = 0; i < spaceCount; i++) { + Space space = spaces[i]; + Log.write(first ? " = " : " + "); + first = false; + Log.write(space.name); Log.write(" "); + printPages(space.reservedPages(), mode); + } + Log.writeln(); + } + + /** + * Print out the number of pages and or megabytes, depending on the mode. + * + * @param pages The number of pages + * @param mode An enumeration type that specifies the format for the + * prining (PAGES, MB, PAGES_MB, or MB_PAGES). + */ + private static void printPages(int pages, int mode) { + double mb = (double) (pages << LOG_BYTES_IN_PAGE) / (double) (1 << 20); + switch (mode) { + case PAGES: Log.write(pages); Log.write(" pgs"); break; + case MB: Log.write(mb); Log.write(" Mb"); break; + case PAGES_MB: Log.write(pages); Log.write(" pgs ("); Log.write(mb); Log.write(" Mb)"); break; + case MB_PAGES: Log.write(mb); Log.write(" Mb ("); Log.write(pages); Log.write(" pgs)"); break; + default: VM.assertions.fail("writePages passed illegal printing mode"); + } + } + + /**************************************************************************** + * + * Miscellaneous + */ + + /** + * Trace an object as part of a collection and return the object, + * which may have been forwarded (if a copying collector). + * + * @param trace The trace being conducted. + * @param object The object to trace + * @return The object, forwarded, if appropriate + */ + public abstract ObjectReference traceObject(TransitiveClosure trace, ObjectReference object); + + + /** + * Has the object in this space been reached during the current collection. + * This is used for GC Tracing. + * + * @param object The object reference. + * @return True if the object is reachable. + */ + public boolean isReachable(ObjectReference object) { + return isLive(object); + } + + + /** + * Is the object in this space alive? + * + * @param object The object reference. + * @return True if the object is live. + */ + public abstract boolean isLive(ObjectReference object); + + /** + * Align an address to a space chunk + * + * @param addr The address to be aligned + * @param down If true the address will be rounded down, otherwise + * it will rounded up. + */ + public static Address chunkAlign(Address addr, boolean down) { + if (!down) addr = addr.plus(BYTES_IN_CHUNK - 1); + return addr.toWord().rshl(LOG_BYTES_IN_CHUNK).lsh(LOG_BYTES_IN_CHUNK).toAddress(); + } + + /** + * Align an extent to a space chunk + * + * @param bytes The extent to be aligned + * @param down If true the address will be rounded down, otherwise + * it will rounded up. + */ + public static Extent chunkAlign(Extent bytes, boolean down) { + if (!down) bytes = bytes.plus(BYTES_IN_CHUNK - 1); + return bytes.toWord().rshl(LOG_BYTES_IN_CHUNK).lsh(LOG_BYTES_IN_CHUNK).toExtent(); + } + + /** + * Convert a fraction into a number of bytes according to the + * fraction of available bytes. + * + * @param frac The fraction of avialable virtual memory desired + * @return The corresponding number of bytes, chunk-aligned. + */ + private static Extent getFracAvailable(float frac) { + long bytes = (long) (frac * AVAILABLE_BYTES.toLong()); + Word mb = Word.fromIntSignExtend((int) (bytes >> LOG_BYTES_IN_MBYTE)); + Extent rtn = mb.lsh(LOG_BYTES_IN_MBYTE).toExtent(); + return chunkAlign(rtn, false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,203 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy.immix; + +import static org.mmtk.policy.immix.ImmixConstants.*; + +import org.mmtk.utility.Constants; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Extent; +import org.vmmagic.unboxed.Offset; + +/** + * This class defines operations over block-granularity meta-data + * + */ + at Uninterruptible +public class Block implements Constants { + + static Address align(final Address ptr) { + return ptr.toWord().and(BLOCK_MASK.not()).toAddress(); + } + + public static boolean isAligned(final Address address) { + return address.EQ(align(address)); + } + + private static int getChunkIndex(final Address block) { + return block.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_BLOCK).toInt(); + } + + /*************************************************************************** + * Block marking + */ + public static boolean isUnused(final Address address) { + return getBlockMarkState(address) == UNALLOCATED_BLOCK_STATE; + } + + static boolean isUnusedState(Address cursor) { + return cursor.loadShort() == UNALLOCATED_BLOCK_STATE; + } + + static short getMarkState(Address cursor) { + return cursor.loadShort(); + } + + static void setState(Address cursor, short value) { + cursor.store(value); + } + + public static short getBlockMarkState(Address address) { + return getBlockMarkStateAddress(address).loadShort(); + } + + static void setBlockAsInUse(Address address) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isUnused(address)); + setBlockState(address, UNMARKED_BLOCK_STATE); + } + + public static void setBlockAsReused(Address address) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!isUnused(address)); + setBlockState(address, REUSED_BLOCK_STATE); + } + + static void setBlockAsUnallocated(Address address) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!isUnused(address)); + getBlockMarkStateAddress(address).store(UNALLOCATED_BLOCK_STATE); + } + + private static void setBlockState(Address address, short value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value != UNALLOCATED_BLOCK_STATE); + getBlockMarkStateAddress(address).store(value); + } + + static Address getBlockMarkStateAddress(Address address) { + Address chunk = Chunk.align(address); + int index = getChunkIndex(address); + Address rtn = chunk.plus(Chunk.BLOCK_STATE_TABLE_OFFSET).plus(index<= conservativeSpillCount); + markHistogram[conservativeSpillCount] += markCount; + + markCount = (short) (markCount + conservativeSpillCount); + + return markCount; + } + + /**************************************************************************** + * Block defrag state + */ + public static boolean isDefragSource(Address address) { + return getDefragStateAddress(address).loadShort() == BLOCK_IS_DEFRAG_SOURCE; + } + + static void clearConservativeSpillCount(Address address) { + getDefragStateAddress(address).store((short) 0); + } + + static short getConservativeSpillCount(Address address) { + return getDefragStateAddress(address).loadShort(); + } + + static Address getDefragStateAddress(Address address) { + Address chunk = Chunk.align(address); + int index = getChunkIndex(address); + Address rtn = chunk.plus(Chunk.BLOCK_DEFRAG_STATE_TABLE_OFFSET).plus(index<= threshold) defragState = BLOCK_IS_DEFRAG_SOURCE; + defragStateBase.store(defragState, csOffset); + } + + private static final short UNALLOCATED_BLOCK_STATE = 0; + private static final short UNMARKED_BLOCK_STATE = (short) (MAX_BLOCK_MARK_STATE + 1); + private static final short REUSED_BLOCK_STATE = (short) (MAX_BLOCK_MARK_STATE + 2); + + private static final short BLOCK_IS_NOT_DEFRAG_SOURCE = 0; + private static final short BLOCK_IS_DEFRAG_SOURCE = 1; + + /* block states */ + static final int LOG_BYTES_IN_BLOCK_STATE_ENTRY = LOG_BYTES_IN_SHORT; // use a short for now + static final int BYTES_IN_BLOCK_STATE_ENTRY = 1< 0 && marked <= LINES_IN_BLOCK); + Block.setState(cursor, marked); + if (defragSource) Defrag.defragBytesNotFreed.inc(BYTES_IN_BLOCK); + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isUnused(block) || (Block.getBlockMarkState(block) == marked && marked > 0 && marked <= MAX_BLOCK_MARK_STATE)); + cursor = cursor.plus(Block.BYTES_IN_BLOCK_STATE_ENTRY); + } + } + + static void clearMetaData(Address chunk) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(isAligned(chunk)); + VM.assertions._assert(Conversions.isPageAligned(chunk)); + VM.assertions._assert(Conversions.isPageAligned(ROUNDED_METADATA_BYTES_PER_CHUNK)); + } + Mmapper.ensureMapped(chunk, ROUNDED_METADATA_PAGES_PER_CHUNK); + VM.memory.zero(chunk, Extent.fromIntZeroExtend(ROUNDED_METADATA_BYTES_PER_CHUNK)); + if (VM.VERIFY_ASSERTIONS) checkMetaDataCleared(chunk, chunk); + } + + private static void checkMetaDataCleared(Address chunk, Address value) { + VM.assertions._assert(isAligned(chunk)); + Address block = Chunk.getHighWater(chunk); + if (value.EQ(chunk)) { + VM.assertions._assert(block.isZero()); + block = chunk.plus(Chunk.ROUNDED_METADATA_BYTES_PER_CHUNK); + } else { + block = block.plus(BYTES_IN_BLOCK); // start at first block after highwater + VM.assertions._assert(Block.align(block).EQ(block)); + } + while (block.LT(chunk.plus(BYTES_IN_CHUNK))) { + VM.assertions._assert(Chunk.align(block).EQ(chunk)); + VM.assertions._assert(Block.isUnused(block)); + block = block.plus(BYTES_IN_BLOCK); + } + } + + static void updateHighWater(Address value) { + Address chunk = align(value); + if (getHighWater(chunk).LT(value)) { + setHighWater(chunk, value); + } + } + + private static void setHighWater(Address chunk, Address value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk)); + chunk.plus(HIGHWATER_OFFSET).store(value); + } + + public static Address getHighWater(Address chunk) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk)); + return chunk.plus(HIGHWATER_OFFSET).loadAddress(); + } + + static void setMap(Address chunk, int value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk)); + chunk.plus(MAP_OFFSET).store(value); + } + + static int getMap(Address chunk) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk)); + int rtn = chunk.plus(MAP_OFFSET).loadInt(); + return (rtn < 0) ? -rtn : rtn; + } + + static void resetLineMarksAndDefragStateTable(Address chunk, short threshold) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk)); + Address markStateBase = Block.getBlockMarkStateAddress(chunk); + Address defragStateBase = Block.getDefragStateAddress(chunk); + Address lineMarkBase = Line.getChunkMarkTable(chunk); + for (int b = FIRST_USABLE_BLOCK_INDEX; b < BLOCKS_IN_CHUNK; b++) { + Block.resetLineMarksAndDefragStateTable(threshold, markStateBase, defragStateBase, lineMarkBase, b); + } + } + + static Address getFirstUsableBlock(Address chunk) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk)); + Address rtn = chunk.plus(ROUNDED_METADATA_BYTES_PER_CHUNK); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn.EQ(Block.align(rtn))); + return rtn; + } + + private static final int LOG_BYTES_IN_HIGHWATER_ENTRY = LOG_BYTES_IN_ADDRESS; + private static final int HIGHWATER_BYTES = 1<>LOG_BYTES_IN_PAGE; + public static final int FIRST_USABLE_BLOCK_INDEX = ROUNDED_METADATA_BYTES_PER_CHUNK>>LOG_BYTES_IN_BLOCK; +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,183 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy.immix; + +import org.mmtk.plan.Plan; +import org.mmtk.policy.Space; +import org.mmtk.utility.Constants; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.AddressArray; + + at Uninterruptible +public final class ChunkList implements Constants { + private static final int LOG_PAGES_IN_CHUNK_MAP_BLOCK = 0; + private static final int ENTRIES_IN_CHUNK_MAP_BLOCK = (BYTES_IN_PAGE<>LOG_BYTES_IN_ADDRESS; + private static final int CHUNK_MAP_BLOCKS = 1<<4; + private static final int MAX_ENTRIES_IN_CHUNK_MAP = ENTRIES_IN_CHUNK_MAP_BLOCK * CHUNK_MAP_BLOCKS; + private AddressArray chunkMap = AddressArray.create(CHUNK_MAP_BLOCKS); + private int chunkMapLimit = -1; + private int chunkMapCursor = -1; + + void reset() { + chunkMapLimit = chunkMapCursor; + } + + public Address getHeadChunk() { + if (chunkMapLimit < 0) + return Address.zero(); + else + return getMapAddress(0).loadAddress(); + } + + public Address getTailChunk() { + if (chunkMapLimit < 0) + return Address.zero(); + else + return getMapAddress(chunkMapLimit).loadAddress(); + } + + void addNewChunkToMap(Address chunk) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk)); + if (chunkMapCursor == MAX_ENTRIES_IN_CHUNK_MAP - 1) + consolidateMap(); + chunkMapCursor++; + int index = getChunkIndex(chunkMapCursor); + int map = getChunkMap(chunkMapCursor); + if (map >= CHUNK_MAP_BLOCKS) { + Space.printUsageMB(); + VM.assertions.fail("Overflow of chunk map!"); + } + if (chunkMap.get(map).isZero()) { + Address tmp = Plan.metaDataSpace.acquire(1<= 0); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(entry <= chunkMapCursor); + int index = getChunkIndex(entry); + int map = getChunkMap(entry); + return chunkMap.get(map).plus(index< chunkMapLimit) { entry = entry % stride; } + chunk = getMapAddress(entry).loadAddress(); + } while (chunk.isZero() && entry != start); + return entry == start ? Address.zero() : chunk; + } + + public Address firstChunk(int ordinal, int stride) { + if (ordinal > chunkMapCursor) return Address.zero(); + if (VM.VERIFY_ASSERTIONS) checkMap(); + Address chunk = getMapAddress(ordinal).loadAddress(); + return chunk.isZero() ? nextChunk(ordinal, ordinal, stride) : chunk; + } + + private void checkMap() { + VM.assertions._assert(chunkMapLimit <= chunkMapCursor); + for (int entry = 0; entry <= chunkMapCursor; entry++) { + Address chunk = getMapAddress(entry).loadAddress(); + if (!chunk.isZero()) + VM.assertions._assert(Chunk.getMap(chunk) == entry); + } + } + + public void consolidateMap() { + int oldCursor = 0; + int newCursor = -1; + while (oldCursor <= chunkMapCursor) { + Address chunk = getMapAddress(oldCursor).loadAddress(); + if (!chunk.isZero()) { + getMapAddress(++newCursor).store(chunk); + Chunk.setMap(chunk, newCursor); + } + oldCursor++; + } + chunkMapCursor = newCursor; + chunkMapLimit = newCursor; + if (VM.VERIFY_ASSERTIONS) checkMap(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,114 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy.immix; + +import static org.mmtk.policy.immix.ImmixConstants.*; + +import org.mmtk.utility.Constants; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; + +/** + * This class implements unsynchronized (local) elements of an + * immix collector. Marking is done using both a bit in + * each header's object word, and a mark byte. Sweeping is + * performed lazily.

+ * + */ + at Uninterruptible +public final class CollectorLocal implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + + /**************************************************************************** + * + * Instance variables + */ + private final ImmixSpace immixSpace; + private final ChunkList chunkMap; + private final Defrag defrag; + + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param space The mark-sweep space to which this allocator + * instances is bound. + */ + public CollectorLocal(ImmixSpace space) { + immixSpace = space; + chunkMap = immixSpace.getChunkMap(); + defrag = immixSpace.getDefrag(); + } + + /**************************************************************************** + * + * Collection + */ + + /** + * Prepare for a collection. If paranoid, perform a sanity check. + */ + public void prepare(boolean majorGC) { + int ordinal = VM.collection.activeGCThreadOrdinal(); + if (majorGC) { + if (immixSpace.inImmixDefragCollection()) { + short threshold = Defrag.defragSpillThreshold; + resetLineMarksAndDefragStateTable(ordinal, threshold); + } + } + } + + private void resetLineMarksAndDefragStateTable(int ordinal, final short threshold) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(immixSpace.inImmixDefragCollection()); + int stride = VM.collection.activeGCThreads(); + Address chunk = chunkMap.firstChunk(ordinal, stride); + while (!chunk.isZero()) { + Chunk.resetLineMarksAndDefragStateTable(chunk, threshold); + chunk = chunkMap.nextChunk(chunk, ordinal, stride); + } + } + + /** + * Finish up after a collection. + * + * We help sweeping all the blocks in parallel. + */ + public void release(boolean majorGC) { + sweepAllBlocks(majorGC); + } + + private void sweepAllBlocks(boolean majorGC) { + int stride = VM.collection.activeGCThreads(); + int ordinal = VM.collection.activeGCThreadOrdinal(); + int[] markSpillHisto = defrag.getAndZeroSpillMarkHistogram(ordinal); + Address chunk = chunkMap.firstChunk(ordinal, stride); + final byte markValue = immixSpace.lineMarkState; + final boolean resetMarks = majorGC && markValue == MAX_LINE_MARK_STATE; + while (!chunk.isZero()) { + Chunk.sweep(chunk, Chunk.getHighWater(chunk), immixSpace, markSpillHisto, markValue, resetMarks); + chunk = chunkMap.nextChunk(chunk, ordinal, stride); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,189 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ + +package org.mmtk.policy.immix; + +import static org.mmtk.policy.immix.ImmixConstants.*; + + +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; +import org.mmtk.utility.heap.FreeListPageResource; +import org.mmtk.utility.options.DefragFreeHeadroom; +import org.mmtk.utility.options.DefragFreeHeadroomFraction; +import org.mmtk.utility.options.DefragHeadroom; +import org.mmtk.utility.options.DefragHeadroomFraction; +import org.mmtk.utility.options.DefragLineReuseRatio; +import org.mmtk.utility.options.DefragSimpleSpillThreshold; +import org.mmtk.utility.options.DefragStress; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.statistics.EventCounter; +import org.mmtk.utility.statistics.SizeCounter; +import org.mmtk.vm.Collection; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.Uninterruptible; + + at Uninterruptible +public class Defrag implements Constants { + + + private int defragHeadroomPages = 0; + private int defragFreeHeadroomPages = 0; + private boolean inDefragCollection = false; + private int debugBytesDefraged = 0; + private int availableCleanPagesForDefrag; + private boolean defragSpaceExhausted = true; + private int[][] spillMarkHistograms = new int[MAX_COLLECTORS][SPILL_HISTOGRAM_BUCKETS]; + private int[] spillAvailHistogram = new int[SPILL_HISTOGRAM_BUCKETS]; + public static SizeCounter defragCleanBytesUsed = new SizeCounter("cleanUsed"); + /* verbose stats (used only on stats runs since they induce overhead when gathred) */ + public static SizeCounter defragBytesNotFreed = new SizeCounter("bytesNotFreed"); + public static SizeCounter defragBytesFreed = new SizeCounter("bytesFreed"); + public static SizeCounter defragCleanBytesAvailable = new SizeCounter("cleanAvail"); + + private final FreeListPageResource pr; + private boolean debugCollectionTypeDetermined = false; + static short defragSpillThreshold = 0; + static short defragReusableMarkStateThreshold = 0; + public static EventCounter defrags = new EventCounter("defrags"); + + static { + Options.defragLineReuseRatio = new DefragLineReuseRatio(); + Options.defragHeadroom = new DefragHeadroom(); + Options.defragHeadroomFraction = new DefragHeadroomFraction(); + Options.defragFreeHeadroom = new DefragFreeHeadroom(); + Options.defragFreeHeadroomFraction = new DefragFreeHeadroomFraction(); + Options.defragSimpleSpillThreshold = new DefragSimpleSpillThreshold(); + Options.defragStress = new DefragStress(); + defragReusableMarkStateThreshold = (short) (Options.defragLineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE); + } + + Defrag(FreeListPageResource pr) { + this.pr = pr; + } + + boolean inDefrag() { return inDefragCollection; } + + void prepare(ChunkList chunkMap, ImmixSpace space) { + if (defragHeadroomPages > 0) + pr.unconditionallyReleasePages(defragHeadroomPages); + + availableCleanPagesForDefrag = VM.activePlan.global().getTotalPages() - VM.activePlan.global().getPagesReserved(); + if (availableCleanPagesForDefrag < 0) availableCleanPagesForDefrag = 0; + defragSpaceExhausted = false; + availableCleanPagesForDefrag += defragFreeHeadroomPages; + if (inDefragCollection) { + if (Options.verbose.getValue() > 0) { + Log.write("[Defrag]"); + } + chunkMap.consolidateMap(); + establishDefragSpillThreshold(chunkMap, space); + defrags.inc(); + defragCleanBytesAvailable.inc(availableCleanPagesForDefrag< 0) + defragHeadroomPages = Options.defragHeadroom.getPages(); + else if (Options.defragHeadroomFraction.getValue() > 0) + defragHeadroomPages = (int) (pr.reservedPages() * Options.defragHeadroomFraction.getValue()); + else + defragHeadroomPages = 0; + if (Options.defragFreeHeadroom.getPages() > 0) + defragFreeHeadroomPages = Options.defragFreeHeadroom.getPages(); + else if (Options.defragFreeHeadroomFraction.getValue() > 0) + defragFreeHeadroomPages = (int) (pr.reservedPages() * Options.defragFreeHeadroomFraction.getValue()); + else + defragFreeHeadroomPages = 0; + + if (defragHeadroomPages > 0) + pr.unconditionallyReservePages(defragHeadroomPages); + + if (inDefragCollection && Options.verbose.getValue() > 2) { + Log.write("(Defrag summary: cu: "); defragCleanBytesUsed.printCurrentVolume(); + Log.write(" nf: "); defragBytesNotFreed.printCurrentVolume(); + Log.write(" fr: "); defragBytesFreed.printCurrentVolume(); + Log.write(" av: "); defragCleanBytesAvailable.printCurrentVolume(); + Log.write(")"); + } + + inDefragCollection = false; + debugCollectionTypeDetermined = false; + } + + void decideWhetherToDefrag(boolean emergencyCollection, boolean collectWholeHeap, int collectionAttempt, int collectionTrigger, boolean exhaustedReusableSpace) { + boolean userTriggered = collectionTrigger == Collection.EXTERNAL_GC_TRIGGER && Options.fullHeapSystemGC.getValue(); + inDefragCollection = (collectionAttempt > 1) || + emergencyCollection || + collectWholeHeap && (Options.defragStress.getValue() || userTriggered); + if (inDefragCollection) { + debugBytesDefraged = 0; + } + debugCollectionTypeDetermined = true; + } + + boolean determined(boolean inDefrag) { return debugCollectionTypeDetermined && !(inDefrag ^ inDefragCollection); } + + void getBlock() { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!inDefragCollection || !defragSpaceExhausted); + if (availableCleanPagesForDefrag <= 0) + defragSpaceExhausted = true; + availableCleanPagesForDefrag -= PAGES_IN_BLOCK; + debugBytesDefraged += BYTES_IN_BLOCK; + Defrag.defragCleanBytesUsed.inc(BYTES_IN_BLOCK); + } + + private void establishDefragSpillThreshold(ChunkList chunkMap, ImmixSpace space) { + int cleanLines = space.getAvailableLines(spillAvailHistogram); + int availableLines = cleanLines + availableCleanPagesForDefrag<<(LOG_BYTES_IN_PAGE - LOG_BYTES_IN_LINE); + + int requiredLines = 0; + short threshold = (short) MAX_CONSV_SPILL_COUNT; + int limit = (int) (availableLines / Options.defragLineReuseRatio.getValue()); + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() > 2) { + Log.write("[threshold: "); Log.write("cl: "); Log.write(cleanLines); + Log.write(" al: "); Log.write(availableLines); + Log.write(" lm: "); Log.write(limit); + } + int collectors = VM.activePlan.collectorCount(); + for (short index = MAX_CONSV_SPILL_COUNT; index >= TMP_MIN_SPILL_THRESHOLD && limit > requiredLines; index--) { + threshold = (short) index; + int thisBucketMark = 0; + int thisBucketAvail = 0; + for (int c = 0; c < collectors; c++) thisBucketMark += spillMarkHistograms[c][threshold]; + + thisBucketAvail = spillAvailHistogram[threshold]; + limit -= thisBucketAvail; + requiredLines += thisBucketMark; + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() > 2) { + Log.write(" ("); Log.write(index); Log.write(" "); Log.write(limit); Log.write(","); Log.write(requiredLines); Log.write(")"); + } + } + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() > 2) { + Log.write(" threshold: "); Log.write(threshold); Log.write("]"); + } + defragSpillThreshold = threshold; + } + + + boolean spaceExhausted() { return defragSpaceExhausted; } + + int[] getAndZeroSpillMarkHistogram(int ordinal) { + int[] rtn = spillMarkHistograms[ordinal]; + for (int i = 0; i < SPILL_HISTOGRAM_BUCKETS; i++) + rtn[i] = 0; + return rtn; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,78 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy.immix; + +import static org.mmtk.policy.Space.BYTES_IN_CHUNK; +import static org.mmtk.policy.Space.LOG_BYTES_IN_CHUNK; +import static org.mmtk.utility.Constants.LOG_BYTES_IN_PAGE; + +import org.mmtk.plan.Plan; +import org.mmtk.vm.VM; +import org.vmmagic.unboxed.Word; + +public class ImmixConstants { + public static final boolean BUILD_FOR_STICKYIMMIX = Plan.NEEDS_LOG_BIT_IN_HEADER; + + /* start temporary experimental constants --- should not be allowed to lurk longer than necessary */ + public static final int TMP_MIN_SPILL_THRESHOLD = 2; + public static final boolean TMP_PREFER_COPY_ON_NURSERY_GC = true; + /* end temporary experimental constants */ + + static final byte MAX_LINE_MARK_STATE = 127; + static final byte RESET_LINE_MARK_STATE = 1; + + public static final boolean MARK_LINE_AT_SCAN_TIME = true; // else do it at mark time + + public static final boolean SANITY_CHECK_LINE_MARKS = false && VM.VERIFY_ASSERTIONS; + + public static final float DEFAULT_LINE_REUSE_RATIO = (float) 0.99; + public static final float DEFAULT_DEFRAG_LINE_REUSE_RATIO = (float) 0.99; + public static final float DEFAULT_SIMPLE_SPILL_THRESHOLD = (float) 0.25; + public static final int DEFAULT_DEFRAG_HEADROOM = 0; // number of pages. + public static final float DEFAULT_DEFRAG_HEADROOM_FRACTION = (float) 0.020; + public static final int DEFAULT_DEFRAG_FREE_HEADROOM = 0; // number of pages. This should only deviate from zero for analytical purposes. Otherwise the defragmenter is cheating! + public static final float DEFAULT_DEFRAG_FREE_HEADROOM_FRACTION = (float) 0.0; + /* sizes etc */ + static final int LOG_BYTES_IN_BLOCK = (LOG_BYTES_IN_PAGE > 15 ? LOG_BYTES_IN_PAGE : 15); + public static final int BYTES_IN_BLOCK = 1<>1; + + private static final int LOG_BLOCKS_IN_RECYCLE_ALLOC_CHUNK = 4; // 3 + 15 -> 19 (512KB) + private static final int LOG_BYTES_IN_RECYCLE_ALLOC_CHUNK = LOG_BLOCKS_IN_RECYCLE_ALLOC_CHUNK + LOG_BYTES_IN_BLOCK; + static final int BYTES_IN_RECYCLE_ALLOC_CHUNK = 1< Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,756 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.policy.immix; + +import static org.mmtk.policy.immix.ImmixConstants.*; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.policy.Space; +import org.mmtk.utility.heap.*; +import org.mmtk.utility.options.LineReuseRatio; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; + +import org.mmtk.vm.Lock; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Each instance of this class corresponds to one immix *space*. + * Each of the instance methods of this class may be called by any + * thread (i.e. synchronization must be explicit in any instance or + * class method). This contrasts with the SquishLocal, where + * instances correspond to *plan* instances and therefore to kernel + * threads. Thus unlike this class, synchronization is not necessary + * in the instance methods of SquishLocal. + * + */ + at Uninterruptible +public final class ImmixSpace extends Space implements Constants { + + /**************************************************************************** + * + * Class variables + */ + private static short reusableMarkStateThreshold = 0; + + /**************************************************************************** + * + * Instance variables + */ + private Word markState = ObjectHeader.MARK_BASE_VALUE; + byte lineMarkState = RESET_LINE_MARK_STATE; + private byte lineUnavailState = RESET_LINE_MARK_STATE; + private boolean inCollection; + private int linesConsumed = 0; + + private Lock mutatorLock = VM.newLock(getName()+"mutator"); + private Lock gcLock = VM.newLock(getName()+"gc"); + + private Address allocBlockCursor = Address.zero(); + private Address allocBlockSentinel = Address.zero(); + private boolean exhaustedReusableSpace = true; + + private final ChunkList chunkMap = new ChunkList(); + private final Defrag defrag; + + /**************************************************************************** + * + * Initialization + */ + + static { + Options.lineReuseRatio = new LineReuseRatio(); + reusableMarkStateThreshold = (short) (Options.lineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE); + } + + /** + * The caller specifies the region of virtual memory to be used for + * this space. If this region conflicts with an existing space, + * then the constructor will fail. + * + * @param name The name of this space (used when printing error messages etc) + * @param pageBudget The number of pages this space may consume before consulting the plan + * @param vmRequest The virtual memory request + */ + public ImmixSpace(String name, int pageBudget, VMRequest vmRequest) { + super(name, false, false, vmRequest); + if (vmRequest.isDiscontiguous()) + pr = new FreeListPageResource(pageBudget, this, Chunk.getRequiredMetaDataPages()); + else + pr = new FreeListPageResource(pageBudget, this, start, extent, Chunk.getRequiredMetaDataPages()); + defrag = new Defrag((FreeListPageResource) pr); + } + + /**************************************************************************** + * + * Global prepare and release + */ + + /** + * Prepare for a new collection increment. + */ + public void prepare(boolean majorGC) { + if (majorGC) { + markState = ObjectHeader.deltaMarkState(markState, true); + lineMarkState++; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(lineMarkState <= MAX_LINE_MARK_STATE); + } + chunkMap.reset(); + defrag.prepare(chunkMap, this); + inCollection = true; + + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(VM.activePlan.collectorCount() <= MAX_COLLECTORS); + } + + /** + * A new collection increment has completed. Release global resources. + * @param majorGC TODO + */ + public boolean release(boolean majorGC) { + boolean didDefrag = defrag.inDefrag(); + if (majorGC) { + if (lineMarkState == MAX_LINE_MARK_STATE) + lineMarkState = RESET_LINE_MARK_STATE; + lineUnavailState = lineMarkState; + } + chunkMap.reset(); + defrag.globalRelease(); + inCollection = false; + + /* set up reusable space */ + if (allocBlockCursor.isZero()) allocBlockCursor = chunkMap.getHeadChunk(); + allocBlockSentinel = allocBlockCursor; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isRecycleAllocChunkAligned(allocBlockSentinel)); + exhaustedReusableSpace = false; + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.write("gr[allocBlockCursor: "); Log.write(allocBlockCursor); Log.write(" allocBlockSentinel: "); Log.write(allocBlockSentinel); Log.writeln("]"); + } + + /* really just want this to happen once after options are booted, but no harm in re-doing it */ + reusableMarkStateThreshold = (short) (Options.lineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE); + Defrag.defragReusableMarkStateThreshold = (short) (Options.defragLineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE); + + linesConsumed = 0; + return didDefrag; + } + + /** + * Determine the collection kind. + * + * @param emergencyCollection Is this collection an emergency (last did not yield enough)? + * @param collectWholeHeap Is this a whole heap collection? + * @param collectionAttempt Which attempt is this to collect? + * @param collectionTrigger What is triggering the collection? + */ + public void decideWhetherToDefrag(boolean emergencyCollection, boolean collectWholeHeap, int collectionAttempt, int collectionTrigger) { + defrag.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, collectionTrigger, exhaustedReusableSpace); + } + + /**************************************************************************** + * + * Collection state access methods + */ + + /** + * Return true if this space is currently being collected. + * + * @return True if this space is currently being collected. + */ + @Inline + public boolean inImmixCollection() { + return inCollection; + } + + /** + * Return true if this space is currently being defraged. + * + * @return True if this space is currently being defraged. + */ + @Inline + public boolean inImmixDefragCollection() { + return inCollection && defrag.inDefrag(); + } + + /** + * Return the number of pages allocated since the last collection + * + * @return The number of pages allocated since the last collection + */ + public int getPagesAllocated() { + return linesConsumed>>(LOG_BYTES_IN_PAGE-LOG_BYTES_IN_LINE); + } + + /** + * Return the reusable mark state threshold, which determines how + * eagerly lines should be recycled (by default these values are + * set so that all lines are recycled). + * + * @param forDefrag The query is the context of a defragmenting collection + * @return The reusable mark state threshold + */ + @Inline + public static short getReusuableMarkStateThreshold(boolean forDefrag) { + return forDefrag ? Defrag.defragReusableMarkStateThreshold : reusableMarkStateThreshold; + } + + /**************************************************************************** + * + * Allocation + */ + + /** + * Return a pointer to a set of new usable blocks, or null if none are available. + * Use different block selection heuristics depending on whether the allocation + * request is "hot" or "cold". + * + * @param hot True if the requesting context is for hot allocations (used for + * allocations from high allocation volume sites). + * @return The pointer into the alloc table containing usable blocks. + */ + public Address getSpace(boolean hot, boolean copy, int lineUseCount) { + Address rtn; + if (copy) + defrag.getBlock(); + + linesConsumed += lineUseCount; + + rtn = acquire(PAGES_IN_BLOCK); + + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(Block.isAligned(rtn)); + VM.assertions._assert(!(copy && Block.isDefragSource(rtn))); + } + + if (!rtn.isZero()) { + Block.setBlockAsInUse(rtn); + Chunk.updateHighWater(rtn); + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.write("gs["); Log.write(rtn); Log.write(" -> "); Log.write(rtn.plus(BYTES_IN_BLOCK-1)); Log.write(" copy: "); Log.write(copy); Log.writeln("]"); + } + } + + return rtn; + } + + /** + * This hook is called by page resources each time a space grows. The space may + * tap into the hook to monitor heap growth. The call is made from within the + * page resources' critical region, immediately before yielding the lock. + * + * @param start The start of the newly allocated space + * @param bytes The size of the newly allocated space + * @param newChunk True if the new space encroached upon or started a new chunk or chunks. + */ + @Override + public void growSpace(Address start, Extent bytes, boolean newChunk) { + super.growSpace(start, bytes, newChunk); + if (newChunk) { + Address chunk = chunkAlign(start.plus(bytes), true); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(chunkAlign(start.plus(bytes), true).EQ(chunk)); + Chunk.clearMetaData(chunk); + chunkMap.addNewChunkToMap(chunk); + } + } + + public Address acquireReusableBlocks() { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(isRecycleAllocChunkAligned(allocBlockCursor)); + VM.assertions._assert(isRecycleAllocChunkAligned(allocBlockSentinel)); + } + Address rtn; + + lock(); + if (exhaustedReusableSpace) + rtn = Address.zero(); + else { + rtn = allocBlockCursor; + Address lastAllocChunk = chunkAlign(allocBlockCursor, true); + allocBlockCursor = allocBlockCursor.plus(BYTES_IN_RECYCLE_ALLOC_CHUNK); + if (allocBlockCursor.GT(Chunk.getHighWater(lastAllocChunk))) + allocBlockCursor = chunkMap.nextChunk(lastAllocChunk); + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.write("arb[ rtn: "); Log.write(rtn); Log.write(" allocBlockCursor: "); Log.write(allocBlockCursor); Log.write(" allocBlockSentinel: "); Log.write(allocBlockSentinel); Log.writeln("]"); + } + + if (allocBlockCursor.isZero() || allocBlockCursor.EQ(allocBlockSentinel)) { + exhaustedReusableSpace = true; + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.writeln("[Reusable space exhausted]"); + } + } + } + unlock(); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isRecycleAllocChunkAligned(rtn)); + return rtn; + } + + /** + * Release a block. A block is free, so call the underlying page allocator + * to release the associated storage. + * + * @param block The address of the block to be released + */ + @Inline + public void release(Address block) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block)); + Block.setBlockAsUnallocated(block); + ((FreeListPageResource) pr).releasePages(block); + } + + /** + * Release one or more contiguous chunks associated with a discontiguous + * space. This hook is called by the page level allocators whenever a + * complete discontiguous chunk is released. + * + * @param chunk THe address of the start of the contiguous chunk or chunks + * @return The number of chunks freed + */ + @Override + public int releaseDiscontiguousChunks(Address chunk) { + chunkMap.removeChunkFromMap(chunk); + return super.releaseDiscontiguousChunks(chunk); + } + + /**************************************************************************** + * + * Header manipulation + */ + + /** + * Perform any required post allocation initialization + * + * @param object the object ref to the storage to be initialized + */ + @Inline + public void postAlloc(ObjectReference object, int bytes) { + if (bytes > BYTES_IN_LINE) + ObjectHeader.markAsStraddling(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(ObjectHeader.isNewObject(object)); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!ObjectHeader.isForwardedOrBeingForwarded(object)); + } + + /** + * Perform any required post copy (i.e. in-GC allocation) initialization. + * This is relevant (for example) when Squish is used as the mature space in + * a copying GC. + * + * @param object the object ref to the storage to be initialized + * @param majorGC Is this copy happening during a major gc? + */ + @Inline + public void postCopy(ObjectReference object, int bytes, boolean majorGC) { + ObjectHeader.writeMarkState(object, markState, bytes > BYTES_IN_LINE); + if (!MARK_LINE_AT_SCAN_TIME && majorGC) markLines(object); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!ObjectHeader.isForwardedOrBeingForwarded(object)); + if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(object)); + } + + /**************************************************************************** + * + * Object tracing + */ + + /** + * Trace a reference to an object. If the object header is not already + * marked, mark the object and enqueue it for subsequent processing. + * + * @param trace The trace performing the transitive closure + * @param object The object to be traced. + * @param allocator The allocator to which any copying should be directed + * @return The object, which may have been moved. + */ + @Inline + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object, int allocator) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(defrag.determined(true)); + + ObjectReference rtn = object; + if (isDefragSource(object)) + rtn = traceObjectWithOpportunisticCopy(trace, object, allocator, false); + else + traceObjectWithoutMoving(trace, object); + + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(!rtn.isNull()); + VM.assertions._assert(defrag.spaceExhausted() || !isDefragSource(rtn) || (ObjectHeader.isPinnedObject(rtn))); + } + return rtn; + } + + /** + * Trace a reference to an object in the context of a non-moving collection. This + * call is optimized for the simpler non-moving case. + * + * @param trace The trace performing the transitive closure + * @param object The object to be traced. + * @return The object (there is no object forwarding in this + * trace method, so we always return the same object: this could be a + * void method but for compliance to a more general interface). + */ + @Inline + public ObjectReference fastTraceObject(TransitiveClosure trace, ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(defrag.determined(false)); + traceObjectWithoutMoving(trace, object); + return object; + } + + /** + * Trace a reference to an object during a nursery collection for + * a sticky mark bits implementation of immix. If the object header + * is not already marked, mark the object and enqueue it for subsequent + * processing. + * + * @param trace The trace performing the transitive closure + * @param object The object to be traced. + * @param allocator The allocator to which any copying should be directed + * @return Either the object or a forwarded object, depending on + * the policy in place. + */ + @Inline + public ObjectReference nurseryTraceObject(TransitiveClosure trace, ObjectReference object, int allocator) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!defrag.inDefrag()); + if (TMP_PREFER_COPY_ON_NURSERY_GC) + return traceObjectWithOpportunisticCopy(trace, object, allocator, true); + else + return fastTraceObject(trace, object); + } + + /** + * Trace a reference to an object. This interface is not supported by immix, since + * we require the allocator to be identified except for the special case of the fast + * trace. + * + * @param trace The trace performing the transitive closure + * @param object The object to be traced. + * @return null and fail. + */ + public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { + VM.assertions.fail("unsupported interface"); + return null; + } + + /** + * Trace a reference to an object in the context of a non-moving collection. This + * call is optimized for the simpler non-moving case. + * + * @param trace The trace performing the transitive closure + * @param object The object to be traced. + */ + @Inline + private void traceObjectWithoutMoving(TransitiveClosure trace, ObjectReference object) { + Word markValue = Plan.NEEDS_LOG_BIT_IN_HEADER ? markState.or(ObjectHeader.UNLOGGED_BIT) : markState; + Word oldMarkState = ObjectHeader.testAndMark(object, markValue); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!defrag.inDefrag() || defrag.spaceExhausted() || !isDefragSource(object)); + if (oldMarkState != markValue) { + if (!MARK_LINE_AT_SCAN_TIME) + markLines(object); + trace.processNode(object); + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!ObjectHeader.isForwardedOrBeingForwarded(object)); + if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(object)); + } + + /** + * Trace a reference to an object, forwarding the object if appropriate + * If the object is not already marked, mark the object and enqueue it + * for subsequent processing. + * + * @param trace The trace performing the transitive closure + * @param object The object to be traced. + * @param allocator The allocator to which any copying should be directed + * @return Either the object or a forwarded object, if it was forwarded. + */ + @Inline + private ObjectReference traceObjectWithOpportunisticCopy(TransitiveClosure trace, ObjectReference object, int allocator, boolean nurseryCollection) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(nurseryCollection || (defrag.determined(true) && isDefragSource(object))); + + /* now race to be the (potential) forwarder */ + Word priorForwardingWord = ObjectHeader.attemptToBeForwarder(object); + if (ObjectHeader.isForwardedOrBeingForwarded(priorForwardingWord)) { + /* We lost the race; the object is either forwarded or being forwarded by another thread. */ + /* Note that the concurrent attempt to forward the object may fail, so the object may remain in-place */ + ObjectReference rtn = ObjectHeader.spinAndGetForwardedObject(object, priorForwardingWord); + if (VM.VERIFY_ASSERTIONS && rtn == object) VM.assertions._assert((nurseryCollection && ObjectHeader.testMarkState(object, markState)) || defrag.spaceExhausted() || ObjectHeader.isPinnedObject(object)); + if (VM.VERIFY_ASSERTIONS && rtn != object) VM.assertions._assert(nurseryCollection || !isDefragSource(rtn)); + if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(rtn)); + return rtn; + } else { + /* the object is unforwarded, either because this is the first thread to reach it, or because the object can't be forwarded */ + if (ObjectHeader.testMarkState(priorForwardingWord, markState)) { + /* the object has not been forwarded, but has the correct mark state; unlock and return unmoved object */ + /* Note that in a sticky mark bits collector, the mark state does not change at each GC, so correct mark state does not imply another thread got there first */ + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(nurseryCollection || defrag.spaceExhausted() || ObjectHeader.isPinnedObject(object)); + ObjectHeader.setForwardingWordAndEnsureUnlogged(object, priorForwardingWord); // return to uncontested state + if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(object)); + return object; + } else { + /* we are the first to reach the object; either mark in place or forward it */ + ObjectReference newObject; + if (ObjectHeader.isPinnedObject(object) || defrag.spaceExhausted()) { + /* mark in place */ + ObjectHeader.setMarkStateUnlogAndUnlock(object, priorForwardingWord, markState); + newObject = object; + if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(newObject)); + } else { + /* forward */ + newObject = ObjectHeader.forwardObject(object, allocator); + if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(newObject)); + } + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.write("C["); Log.write(object); Log.write("/"); + Log.write(getName()); Log.write("] -> "); + Log.write(newObject); Log.write("/"); + Log.write(Space.getSpaceForObject(newObject).getName()); + Log.writeln("]"); + } + if (!MARK_LINE_AT_SCAN_TIME) + markLines(newObject); + trace.processNode(newObject); + if (VM.VERIFY_ASSERTIONS) { + if (!((getSpaceForObject(newObject) != this) || + (newObject == object) || + (nurseryCollection && willNotMoveThisNurseryGC(newObject)) || + (defrag.inDefrag() && willNotMoveThisGC(newObject)) + )) { + Log.write(" object: "); Log.writeln(object); + Log.write("newObject: "); Log.writeln(newObject); + Log.write(" space: "); Log.writeln(getName()); + Log.write(" nursery?: "); Log.writeln(nurseryCollection); + Log.write(" mature?: "); Log.writeln(ObjectHeader.isMatureObject(object)); + Log.write(" wnmngc?: "); Log.writeln(willNotMoveThisNurseryGC(newObject)); + Log.write(" pinned?: "); Log.writeln(ObjectHeader.isPinnedObject(object)); + Space otherSpace = getSpaceForObject(newObject); + Log.write(" space(o): "); Log.writeln(otherSpace == null ? "" : otherSpace.getName()); + VM.assertions._assert(false); + } + } + return newObject; + } + } + } + + /** + * Mark the line/s associated with a given object. This is distinct from the + * above tracing code because line marks are stored separately from the + * object headers (thus both must be set), and also because we found empirically + * that it was more efficient to perform the line mark of the object during + * the scan phase (which occurs after the trace phase), presumably because + * the latency of the associated memory operations was better hidden in the + * context of that code + * + * @param object The object which is live and for which the associated lines + * must be marked. + */ + public void markLines(ObjectReference object) { + Address address = VM.objectModel.objectStartRef(object); + Line.mark(address, lineMarkState); + if (ObjectHeader.isStraddlingObject(object)) + Line.markMultiLine(address, object, lineMarkState); + } + + public int getNextUnavailableLine(Address baseLineAvailAddress, int line) { + return Line.getNextUnavailable(baseLineAvailAddress, line, lineUnavailState); + } + + public int getNextAvailableLine(Address baseLineAvailAddress, int line) { + return Line.getNextAvailable(baseLineAvailAddress, line, lineUnavailState); + } + + /**************************************************************************** + * + * Establish available lines + */ + + /** + * Establish the number of recyclable lines lines available for allocation + * during defragmentation, populating the spillAvailHistogram, which buckets + * available lines according to the number of holes on the block on which + * the available lines reside. + * + * @param spillAvailHistogram A histogram of availability to be populated + * @return The number of available recyclable lines + */ + int getAvailableLines(int[] spillAvailHistogram) { + int availableLines; + if (allocBlockCursor.isZero() || exhaustedReusableSpace) { + availableLines = 0; + } else { + if (allocBlockCursor.EQ(allocBlockSentinel)) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!exhaustedReusableSpace); + allocBlockCursor = chunkMap.getHeadChunk(); + allocBlockSentinel = allocBlockCursor; + } + availableLines = getUsableLinesInRegion(allocBlockCursor, allocBlockSentinel, spillAvailHistogram); + } + return availableLines; + } + + /** + * Return the number of lines usable for allocation during defragmentation in the + * address range specified by start and end. Populate a histogram to indicate where + * the usable lines reside as a function of block hole count. + * + * @param start The start of the region to be checked for availability + * @param end The end of the region to be checked for availability + * @param spillAvailHistogram The histogram which will be populated + * @return The number of usable lines + */ + private int getUsableLinesInRegion(Address start, Address end, int[] spillAvailHistogram) { + int usableLines = 0; + Address blockCursor = Chunk.isAligned(start) ? start.plus(Chunk.FIRST_USABLE_BLOCK_INDEX<= 0 && bucket <= MAX_CONSV_SPILL_COUNT); + spillAvailHistogram[bucket] += usable; + usableLines += usable; + } + blockCursor = blockCursor.plus(BYTES_IN_BLOCK); + if (blockCursor.GT(highwater)) { + chunkCursor = chunkMap.nextChunk(chunkCursor); + if (chunkCursor.isZero()) break; + blockCursor = chunkCursor.plus(Chunk.FIRST_USABLE_BLOCK_INDEX<= 0 && line <= LINES_IN_BLOCK); + return line; + } + + @Inline + public static int getNextAvailable(Address baseLineAvailAddress, int line, final byte unavailableState) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line < LINES_IN_BLOCK); + byte last = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<= 0 && line <= LINES_IN_BLOCK); + return line; + } + + private static Address getMetaAddress(Address address, final int tableOffset) { + Address chunk = Chunk.align(address); + int index = getChunkIndex(address); + Address rtn = chunk.plus(tableOffset + (index<free() with + * the index of the first unit as the argument.

+ * + * Properties/Constraints:

    + *
  • The allocator consumes one word per allocatable unit (plus + * a fixed overhead of about 128 words).
  • + *
  • The allocator can only deal with MAX_UNITS units (see below for + * the value).
  • + *
+ * + * The basic data structure used by the algorithm is a large table, + * with one word per allocatable unit. Each word is used in a + * number of different ways, some combination of "undefined" (32), + * "free/used" (1), "multi/single" (1), "prev" (15), "next" (15) & + * "size" (15) where field sizes in bits are in parenthesis. + *
+ *                       +-+-+-----------+-----------+
+ *                       |f|m|    prev   | next/size |
+ *                       +-+-+-----------+-----------+
+ *
+ *   - single free unit: "free", "single", "prev", "next"
+ *   - single used unit: "used", "single"
+ *    - contiguous free units
+ *     . first unit: "free", "multi", "prev", "next"
+ *     . second unit: "free", "multi", "size"
+ *     . last unit: "free", "multi", "size"
+ *    - contiguous used units
+ *     . first unit: "used", "multi", "prev", "next"
+ *     . second unit: "used", "multi", "size"
+ *     . last unit: "used", "multi", "size"
+ *    - any other unit: undefined
+ *
+ *                       +-+-+-----------+-----------+
+ *   top sentinel        |0|0|    tail   |   head    |  [-1]
+ *                       +-+-+-----------+-----------+
+ *                                     ....
+ *            /--------  +-+-+-----------+-----------+
+ *            |          |1|1|   prev    |   next    |  [j]
+ *            |          +-+-+-----------+-----------+
+ *            |          |1|1|           |   size    |  [j+1]
+ *         free multi    +-+-+-----------+-----------+
+ *         unit block    |              ...          |  ...
+ *            |          +-+-+-----------+-----------+
+ *            |          |1|1|           |   size    |
+ *           >--------  +-+-+-----------+-----------+
+ *   single free unit    |1|0|   prev    |   next    |
+ *           >--------  +-+-+-----------+-----------+
+ *   single used unit    |0|0|                       |
+ *           >--------  +-+-+-----------------------+
+ *            |          |0|1|                       |
+ *            |          +-+-+-----------+-----------+
+ *            |          |0|1|           |   size    |
+ *         used multi    +-+-+-----------+-----------+
+ *         unit block    |              ...          |
+ *            |          +-+-+-----------+-----------+
+ *            |          |0|1|           |   size    |
+ *            \--------  +-+-+-----------+-----------+
+ *                                     ....
+ *                       +-+-+-----------------------+
+ *   bottom sentinel     |0|0|                       |  [N]
+ *                       +-+-+-----------------------+
+ * 
+ * The sentinels serve as guards against out of range coalescing + * because they both appear as "used" blocks and so will never + * coalesce. The top sentinel also serves as the head and tail of + * the doubly linked list of free blocks. + */ + at Uninterruptible abstract class BaseGenericFreeList implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Allocate size units. Return the unit ID + * + * @param size The number of units to be allocated + * @return The index of the first of the size + * contiguous units, or -1 if the request can't be satisfied + */ + public final int alloc(int size) { + // Note: -1 is both the default return value *and* the start sentinel index + int unit = head; // HEAD = -1 + int s = 0; + while (((unit = getNext(unit)) != head) && ((s = getSize(unit)) < size)); + + return (unit == head) ? FAILURE : alloc(size, unit, s); + } + + /** + * Would an allocation of size units succeed? + * + * @param size The number of units to test for + * @return True if such a request could be satisfied. + */ + public final boolean couldAlloc(int size) { + // Note: -1 is both the default return value *and* the start sentinel index + int unit = head; // HEAD = -1 + while (((unit = getNext(unit)) != head) && (getSize(unit) < size)); + + return (unit != head); + } + + /** + * Allocate size units. Return the unit ID + * + * @param size The number of units to be allocated + * @return The index of the first of the size + * contiguous units, or -1 if the request can't be satisfied + */ + public final int alloc(int size, int unit) { + int s = 0; + + if (getFree(unit) && (s = getSize(unit)) >= size) + return alloc(size, unit, s); + else + return FAILURE; + } + + /** + * Allocate size units. Return the unit ID + * + * @param size The number of units to be allocated + * @return The index of the first of the size + * contiguous units, or -1 if the request can't be satisfied + */ + private int alloc(int size, int unit, int unitSize) { + if (unitSize >= size) { + if (unitSize > size) + split(unit, size); + removeFromFree(unit); + setFree(unit, false); + } + + if (DEBUG) dbgPrintFree(); + + return unit; + } + + /** + * Free a previously allocated contiguous lump of units. + * + * @param unit The index of the first unit. + * @return return the size of the unit which was freed. + */ + public final int free(int unit) { + return free(unit, false); + } + + /** + * Free a previously allocated contiguous lump of units. + * + * @param unit The index of the first unit. + * @param returnCoalescedSize if true, return the coalesced size + * @return The number of units freed. if returnCoalescedSize is + * false, return the size of the unit which was freed. Otherwise + * return the size of the unit now available (the coalesced size) + */ + public final int free(int unit, boolean returnCoalescedSize) { + int freed = getSize(unit); + int left = getLeft(unit); + int start = isCoalescable(unit) && getFree(left) ? left : unit; + int right = getRight(unit); + int end = isCoalescable(right) && getFree(right) ? right : unit; + if (start != end) + coalesce(start, end); + + if (returnCoalescedSize) + freed = getSize(start); + addToFree(start); + + if (DEBUG) dbgPrintFree(); + return freed; + } + + /** + * Return the size of the specified lump of units + * + * @param unit The index of the first unit in the lump. + * @return The size of the lump, in units. + */ + public final int size(int unit) { + return getSize(unit); + } + + /**************************************************************************** + * + * Private fields and methods + */ + + /** + * Initialize a new heap. Fabricate a free list entry containing + * everything + * + * @param units The number of units in the heap + */ + protected final void initializeHeap(int units) { + initializeHeap(units, units); + } + + /** + * Initialize a new heap. Fabricate a free list entry containing + * everything + * + * @param units The number of units in the heap + */ + protected final void initializeHeap(int units, int grain) { + // Initialize the sentinels + for (int i = 1; i <= heads; i++) + setSentinel(-i); + setSentinel(units); + + // create the free list item + int offset = units % grain; + int cursor = units - offset; + if (offset > 0) { + setSize(cursor, offset); + addToFree(cursor); + } + cursor -= grain; + while (cursor >= 0) { + setSize(cursor, grain); + addToFree(cursor); + cursor -= grain; + } + if (DEBUG) dbgPrintFree(); + } + + /** + * Reduce a lump of units to size, freeing any excess. + * + * @param unit The index of the first unit + * @param size The size of the first part + */ + private void split(int unit, int size) { + int basesize = getSize(unit); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(basesize > size); + setSize(unit, size); + setSize(unit + size, basesize - size); + addToFree(unit + size); + if (DEBUG) dbgPrintFree(); + } + + /** + * Coalesce two or three contiguous lumps of units, removing start + * and end lumps from the free list as necessary. + * @param start The index of the start of the first lump + * @param end The index of the start of the last lump + */ + private void coalesce(int start, int end) { + if (getFree(end)) + removeFromFree(end); + if (getFree(start)) + removeFromFree(start); + + setSize(start, end - start + getSize(end)); + } + + /** + * Add a lump of units to the free list + * + * @param unit The first unit in the lump of units to be added + */ + private void addToFree(int unit) { + setFree(unit, true); + int next = getNext(head); + setNext(unit, next); + setNext(head, unit); + setPrev(unit, head); + setPrev(next, unit); + } + + /** + * Remove a lump of units from the free list + * + * @param unit The first unit in the lump of units to be removed + */ + private void removeFromFree(int unit) { + int next = getNext(unit); + int prev = getPrev(unit); + setNext(prev, next); + setPrev(next, prev); + if (DEBUG) dbgPrintFree(); + } + + /** + * Get the lump to the "right" of the current lump (i.e. "below" it) + * + * @param unit The index of the first unit in the lump in question + * @return The index of the first unit in the lump to the + * "right"/"below" the lump in question. + */ + private int getRight(int unit) { + return unit + getSize(unit); + } + + + /** + * Print the free list (for debugging purposes) + */ + void dbgPrintFree() { + if (DEBUG) { + Log.write("FL["); + int i = head; + while ((i = getNext(i)) != head) { + boolean f = getFree(i); + int s = getSize(i); + if (!f) + Log.write("->"); + Log.write(i); + if (!f) + Log.write("<-"); + Log.write("("); + Log.write(s); + Log.write(")"); + Log.write(" "); + Log.flush(); + } + Log.writeln("]FL"); + } + } + + abstract void setSentinel(int unit); + abstract int getSize(int unit); + abstract void setSize(int unit, int size); + abstract boolean getFree(int unit); + abstract void setFree(int unit, boolean isFree); + abstract int getNext(int unit); + abstract void setNext(int unit, int next); + abstract int getPrev(int unit); + abstract void setPrev(int unit, int prev); + abstract int getLeft(int unit); + abstract boolean isCoalescable(int unit); + + protected static final boolean DEBUG = false; + public static final int FAILURE = -1; + protected static final int MAX_HEADS = 128; // somewhat arbitrary + + protected int heads = 1; + protected int head = -heads; +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,18 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +/* + */ +public class CallSite { +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,145 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.mmtk.utility.alloc.EmbeddedMetaData; +import org.mmtk.vm.VM; + +/** + * MMTk follows the pattern set by Jikes RVM for defining sizes of + * primitive types thus: + * + *
+ * static final int LOG_BYTES_IN_INT = 2;
+ * static final int BYTES_IN_INT = 1<
+ */
+public interface Constants {
+
+  /****************************************************************************
+   *
+   * MMTk constants
+   */
+  int PUTFIELD_WRITE_BARRIER = 0;
+  int GETFIELD_READ_BARRIER = 0;
+  int PUTSTATIC_WRITE_BARRIER = 1;
+  int GETSTATIC_READ_BARRIER = 1;
+  int AASTORE_WRITE_BARRIER = 2;
+  int AALOAD_READ_BARRIER = 2;
+
+
+  /****************************************************************************
+   *
+   * Generic sizes
+   */
+  byte LOG_BYTES_IN_BYTE = 0;
+  int BYTES_IN_BYTE = 1;
+  byte LOG_BITS_IN_BYTE = 3;
+  int BITS_IN_BYTE = 1 << LOG_BITS_IN_BYTE;
+
+  byte LOG_BYTES_IN_MBYTE = 20;
+  int BYTES_IN_MBYTE = 1 << LOG_BYTES_IN_MBYTE;
+
+  byte LOG_BYTES_IN_KBYTE = 10;
+  int BYTES_IN_KBYTE = 1 << LOG_BYTES_IN_KBYTE;
+
+  /****************************************************************************
+   *
+   * Card scanning
+   */
+  boolean SUPPORT_CARD_SCANNING = false;
+  int LOG_CARD_META_SIZE = 2;// each card consumes four bytes of metadata
+  int LOG_CARD_UNITS = 10;  // number of units tracked per card
+  int LOG_CARD_GRAIN = 0;   // track at byte grain, save shifting
+  int LOG_CARD_BYTES = LOG_CARD_UNITS + LOG_CARD_GRAIN;
+  int LOG_CARD_META_BYTES = EmbeddedMetaData.LOG_BYTES_IN_REGION - LOG_CARD_BYTES + LOG_CARD_META_SIZE;
+  int LOG_CARD_META_PAGES = LOG_CARD_META_BYTES - VM.LOG_BYTES_IN_PAGE;
+  int CARD_META_PAGES_PER_REGION = SUPPORT_CARD_SCANNING ? (1<minimum allocation alignment
+   * requirement of the VM.  When making allocation requests, both
+   * align and offset must be multiples of
+   * MIN_ALIGNMENT.
+   *
+   * This value is required to be a power of 2.
+   */
+  byte LOG_MIN_ALIGNMENT = VM.LOG_MIN_ALIGNMENT;
+  int MIN_ALIGNMENT = 1 << LOG_MIN_ALIGNMENT;
+
+  /**
+   * The maximum alignment request the vm will make. This must be a
+   * power of two multiple of the minimum alignment.
+   */
+  int MAX_ALIGNMENT = MIN_ALIGNMENT<>> LOG_BYTES_IN_MBYTE) - 1)) >>> (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_MBYTE);
+  }
+
+  public static int bytesToMmapChunksUp(Extent bytes) {
+    return bytes.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES).toInt();
+  }
+
+  public static int pagesToMmapChunksUp(int pages) {
+    return bytesToMmapChunksUp(pagesToBytes(pages));
+  }
+
+  public static int addressToMmapChunksDown(Address addr) {
+    Word chunk = addr.toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
+    return chunk.toInt();
+  }
+
+  public static int addressToPagesDown(Address addr) {
+    Word chunk = addr.toWord().rshl(LOG_BYTES_IN_PAGE);
+    return chunk.toInt();
+  }
+
+  public static int addressToPages(Address addr) {
+    int page = addressToPagesDown(addr);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(page).EQ(addr));
+    return page;
+  }
+
+  public static Address pagesToAddress(int pages) {
+    return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toAddress();
+  }
+
+  public static int addressToMmapChunksUp(Address addr) {
+    Word chunk = addr.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
+    return chunk.toInt();
+  }
+
+  public static Extent pagesToBytes(int pages) {
+    return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toExtent();
+  }
+
+  public static int pagesToMBytes(int pages) {
+    return pages >> (LOG_BYTES_IN_MBYTE - LOG_BYTES_IN_PAGE);
+  }
+
+  public static int pagesToKBytes(int pages) {
+    return pages << (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_KBYTE);
+  }
+
+  /**
+    @deprecated : use int bytesToPagesUp(Extent bytes) if possible
+   */
+  @Deprecated
+  public static int bytesToPagesUp(int bytes) {
+    return bytesToPagesUp(Extent.fromIntZeroExtend(bytes));
+  }
+
+  /**
+    @deprecated : use int bytesToPagesUp(Extent bytes) if possible
+   */
+  @Deprecated
+  public static int bytesToPages(int bytes) {
+    return bytesToPages(Extent.fromIntZeroExtend(bytes));
+  }
+
+  public static int bytesToPagesUp(Extent bytes) {
+    return bytes.plus(BYTES_IN_PAGE-1).toWord().rshl(LOG_BYTES_IN_PAGE).toInt();
+  }
+
+  public static int bytesToPages(Extent bytes) {
+    int pages = bytesToPagesUp(bytes);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(pages).toWord().toExtent().EQ(bytes));
+    return pages;
+  }
+
+  public static int bytesToPages(Offset bytes) {
+    if (VM.VERIFY_ASSERTIONS) {
+      long val = bytes.toLong();
+      VM.assertions._assert(val >= MIN_INT && val <= MAX_INT);
+    }
+    if (bytes.sGE(Offset.zero()))
+      return bytesToPagesUp(Extent.fromIntSignExtend(bytes.toInt()));
+    else
+      return -bytesToPagesUp(Extent.fromIntSignExtend(-bytes.toInt()));
+  }
+
+  public static Address mmapChunksToAddress(int chunk) {
+    return Word.fromIntZeroExtend(chunk).lsh(Mmapper.LOG_MMAP_CHUNK_BYTES).toAddress();
+  }
+
+  public static Address pageAlign(Address address) {
+    return address.toWord().rshl(LOG_BYTES_IN_PAGE).lsh(LOG_BYTES_IN_PAGE).toAddress();
+  }
+
+  public static int pageAlign(int value) {
+    return (value>>LOG_BYTES_IN_PAGE)< "); Log.write(cur);
+    }
+    Log.writeln();
+    if (lock != null) lock.release();
+  }
+
+
+  /**
+   * Gather data for GCSpy
+   * @param driver the GCSpy space driver
+   */
+  void gcspyGatherData(AbstractDriver driver) {
+    // GCSpy doesn't need a lock (in its stop the world config)
+    Address cur = head;
+    while (!cur.isZero()) {
+      driver.scan(cur);
+      cur = cur.loadAddress(NEXT_OFFSET);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,383 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This is a very simple, generic malloc-free allocator.  It works
+ * abstractly, in "units", which the user may associate with some
+ * other allocatable resource (e.g. heap blocks).  The user issues
+ * requests for N units and the allocator returns the index of the
+ * first of a contiguous set of N units or fails, returning -1.  The
+ * user frees the block of N units by calling free() with
+ * the index of the first unit as the argument.

+ * + * Properties/Constraints:

    + *
  • The allocator consumes one word per allocatable unit (plus + * a fixed overhead of about 128 words).
  • + *
  • The allocator can only deal with MAX_UNITS units (see below for + * the value).
  • + *
+ * + * The basic data structure used by the algorithm is a large table, + * with one word per allocatable unit. Each word is used in a + * number of different ways, some combination of "undefined" (32), + * "free/used" (1), "multi/single" (1), "prev" (15), "next" (15) & + * "size" (15) where field sizes in bits are in parenthesis. + *
+ *                       +-+-+-----------+-----------+
+ *                       |f|m|    prev   | next/size |
+ *                       +-+-+-----------+-----------+
+ *
+ *   - single free unit: "free", "single", "prev", "next"
+ *   - single used unit: "used", "single"
+ *    - contiguous free units
+ *     . first unit: "free", "multi", "prev", "next"
+ *     . second unit: "free", "multi", "size"
+ *     . last unit: "free", "multi", "size"
+ *    - contiguous used units
+ *     . first unit: "used", "multi", "prev", "next"
+ *     . second unit: "used", "multi", "size"
+ *     . last unit: "used", "multi", "size"
+ *    - any other unit: undefined
+ *
+ *                       +-+-+-----------+-----------+
+ *   top sentinel        |0|0|    tail   |   head    |  [-1]
+ *                       +-+-+-----------+-----------+
+ *                                     ....
+ *            /--------  +-+-+-----------+-----------+
+ *            |          |1|1|   prev    |   next    |  [j]
+ *            |          +-+-+-----------+-----------+
+ *            |          |1|1|           |   size    |  [j+1]
+ *         free multi    +-+-+-----------+-----------+
+ *         unit block    |              ...          |  ...
+ *            |          +-+-+-----------+-----------+
+ *            |          |1|1|           |   size    |
+ *           >--------  +-+-+-----------+-----------+
+ *   single free unit    |1|0|   prev    |   next    |
+ *           >--------  +-+-+-----------+-----------+
+ *   single used unit    |0|0|                       |
+ *           >--------  +-+-+-----------------------+
+ *            |          |0|1|                       |
+ *            |          +-+-+-----------+-----------+
+ *            |          |0|1|           |   size    |
+ *         used multi    +-+-+-----------+-----------+
+ *         unit block    |              ...          |
+ *            |          +-+-+-----------+-----------+
+ *            |          |0|1|           |   size    |
+ *            \--------  +-+-+-----------+-----------+
+ *                                     ....
+ *                       +-+-+-----------------------+
+ *   bottom sentinel     |0|0|                       |  [N]
+ *                       +-+-+-----------------------+
+ * 
+ * The sentinels serve as guards against out of range coalescing + * because they both appear as "used" blocks and so will never + * coalesce. The top sentinel also serves as the head and tail of + * the doubly linked list of free blocks. + */ + at Uninterruptible +public final class GenericFreeList extends BaseGenericFreeList implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param units The number of allocatable units for this free list + */ + public GenericFreeList(int units) { + this(units, units); + } + + /** + * Constructor + * + * @param units The number of allocatable units for this free list + * @param grain Units are allocated such that they will never cross this granularity boundary + */ + public GenericFreeList(int units, int grain) { + this(units, grain, 1); + } + + /** + * Constructor + * + * @param units The number of allocatable units for this free list + * @param grain Units are allocated such that they will never cross this granularity boundary + * @param heads The number of free lists which will share this instance + */ + public GenericFreeList(int units, int grain, int heads) { + this.parent = null; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(units <= MAX_UNITS && heads <= MAX_HEADS); + this.heads = heads; + head = -1; + + // allocate the data structure, including space for top & bottom sentinels + table = new int[(units + 1 + heads) << 1]; + initializeHeap(units, grain); + } + + /** + * Resize the free list for a parent free list. + * This must not be called dynamically (ie not after bootstrap). + * + * @param units The number of allocatable units for this free list + * @param grain Units are allocated such that they will never cross this granularity boundary + */ + @Interruptible + public void resizeFreeList(int units, int grain) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(parent == null && !Plan.isInitialized()); + table = new int[(units + 1 + heads) << 1]; + initializeHeap(units, grain); + } + + /** + * Resize the free list for a child free list. + * This must not be called dynamically (ie not after bootstrap). + */ + @Interruptible + public void resizeFreeList() { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(parent != null && !Plan.isInitialized()); + table = parent.getTable(); + } + + /** + * Constructor + * + * @param parent The parent, owning the data structures this instance will share + * @param ordinal The ordinal number of this child + */ + public GenericFreeList(GenericFreeList parent, int ordinal) { + this.parent = parent; + this.table = parent.getTable(); + this.heads = parent.getHeads(); + this.head = -(1 + ordinal); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(-this.head <= this.heads); + } + + /** Getter */ + int[] getTable() { return table; } + int getHeads() { return heads; } + + /** + * Initialize a unit as a sentinel + * + * @param unit The unit to be initialized + */ + protected void setSentinel(int unit) { + setLoEntry(unit, NEXT_MASK & unit); + setHiEntry(unit, PREV_MASK & unit); + } + + /** + * Get the size of a lump of units + * + * @param unit The first unit in the lump of units + * @return The size of the lump of units + */ + protected int getSize(int unit) { + if ((getHiEntry(unit) & MULTI_MASK) == MULTI_MASK) + return (getHiEntry(unit + 1) & SIZE_MASK); + else + return 1; + } + + /** + * Set the size of lump of units + * + * @param unit The first unit in the lump of units + * @param size The size of the lump of units + */ + protected void setSize(int unit, int size) { + if (size > 1) { + setHiEntry(unit, getHiEntry(unit) | MULTI_MASK); + setHiEntry(unit + 1, MULTI_MASK | size); + setHiEntry(unit + size - 1, MULTI_MASK | size); + } else + setHiEntry(unit, getHiEntry(unit) & ~MULTI_MASK); + } + + /** + * Establish whether a lump of units is free + * + * @param unit The first or last unit in the lump + * @return True if the lump is free + */ + protected boolean getFree(int unit) { + return ((getLoEntry(unit) & FREE_MASK) == FREE_MASK); + } + + /** + * Set the "free" flag for a lump of units (both the first and last + * units in the lump are set. + * + * @param unit The first unit in the lump + * @param isFree True if the lump is to be marked as free + */ + protected void setFree(int unit, boolean isFree) { + int size; + if (isFree) { + setLoEntry(unit, getLoEntry(unit) | FREE_MASK); + if ((size = getSize(unit)) > 1) + setLoEntry(unit + size - 1, getLoEntry(unit + size - 1) | FREE_MASK); + } else { + setLoEntry(unit, getLoEntry(unit) & ~FREE_MASK); + if ((size = getSize(unit)) > 1) + setLoEntry(unit + size - 1, getLoEntry(unit + size - 1) & ~FREE_MASK); + } + } + + /** + * Get the next lump in the doubly linked free list + * + * @param unit The index of the first unit in the current lump + * @return The index of the first unit of the next lump of units in the list + */ + protected int getNext(int unit) { + int next = getHiEntry(unit) & NEXT_MASK; + return (next <= MAX_UNITS) ? next : head; + } + + /** + * Set the next lump in the doubly linked free list + * + * @param unit The index of the first unit in the lump to be set + * @param next The value to be set. + */ + protected void setNext(int unit, int next) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((next >= -heads) && (next <= MAX_UNITS)); + int oldValue = getHiEntry(unit); + int newValue = (oldValue & ~NEXT_MASK) | (next & NEXT_MASK); + setHiEntry(unit, newValue); + } + + /** + * Get the previous lump in the doubly linked free list + * + * @param unit The index of the first unit in the current lump + * @return The index of the first unit of the previous lump of units + * in the list + */ + protected int getPrev(int unit) { + int prev = getLoEntry(unit) & PREV_MASK; + return (prev <= MAX_UNITS) ? prev : head; + } + + /** + * Set the previous lump in the doubly linked free list + * + * @param unit The index of the first unit in the lump to be set + * @param prev The value to be set. + */ + protected void setPrev(int unit, int prev) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((prev >= -heads) && (prev <= MAX_UNITS)); + int oldValue = getLoEntry(unit); + int newValue = (oldValue & ~PREV_MASK) | (prev & PREV_MASK); + setLoEntry(unit, newValue); + } + + /** + * Set the uncoalescable bit associated with this unit. + * This ensures this unit cannot be coalesced with units below + * it. + * + * @param unit The unit whose uncoalescable bit is to be set + */ + public void setUncoalescable(int unit) { + setLoEntry(unit, getLoEntry(unit) | COALESC_MASK); + } + + /** + * Clear the uncoalescable bit associated with this unit. + * This allows this unit to be coalesced with units below + * it. + * + * @param unit The unit whose uncoalescable bit is to be cleared + */ + public void clearUncoalescable(int unit) { + setLoEntry(unit, getLoEntry(unit) & ~COALESC_MASK); + } + + /** + * Return true if this unit may be coalesced with the unit below it. + * + * @param unit The unit in question + * @return True if this unit may be coalesced with the unit below it. + */ + @Override + public boolean isCoalescable(int unit) { + return (getLoEntry(unit) & COALESC_MASK) == 0; + } + + /** + * Get the lump to the "left" of the current lump (i.e. "above" it) + * + * @param unit The index of the first unit in the lump in question + * @return The index of the first unit in the lump to the + * "left"/"above" the lump in question. + */ + protected int getLeft(int unit) { + if ((getHiEntry(unit - 1) & MULTI_MASK) == MULTI_MASK) + return unit - (getHiEntry(unit - 1) & SIZE_MASK); + else + return unit - 1; + } + + + /** + * Get the contents of an entry + * + * @param unit The index of the unit + * @return The contents of the unit + */ + private int getLoEntry(int unit) { + return table[(unit + heads) << 1]; + } + private int getHiEntry(int unit) { + return table[((unit + heads) << 1) + 1]; + } + + /** + * Set the contents of an entry + * + * @param unit The index of the unit + * @param value The contents of the unit + */ + private void setLoEntry(int unit, int value) { + table[(unit + heads) << 1] = value; + } + private void setHiEntry(int unit, int value) { + table[((unit + heads) << 1) + 1] = value; + } + + private static final int TOTAL_BITS = 32; + private static final int UNIT_BITS = (TOTAL_BITS - 2); + public static final int MAX_UNITS = (int) (((((long) 1) << UNIT_BITS) - 1) - MAX_HEADS - 1); + private static final int NEXT_MASK = (int) ((((long) 1) << UNIT_BITS) - 1); + private static final int PREV_MASK = (int) ((((long) 1) << UNIT_BITS) - 1); + private static final int FREE_MASK = 1 << (TOTAL_BITS - 1); + private static final int MULTI_MASK = 1 << (TOTAL_BITS - 1); + private static final int COALESC_MASK = 1 << (TOTAL_BITS - 2); + private static final int SIZE_MASK = (int) ((((long) 1) << UNIT_BITS) - 1); + + private int[] table; + private final GenericFreeList parent; +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,842 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Error and trace logging. + */ + at Uninterruptible +public class Log implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + /** + * characters in the write buffer for the caller's message. This + * does not include characters reserved for the overflow message. + * + * This needs to be large because Jikes RVM's implementation of Lock.java + * logs a lot of information when there is potential GC deadlock. + */ + private static final int MESSAGE_BUFFER_SIZE = 3000; + + /** message added when the write buffer has overflown */ + private static final String OVERFLOW_MESSAGE = "... WARNING: Text truncated.\n"; + + private static final char OVERFLOW_MESSAGE_FIRST_CHAR = OVERFLOW_MESSAGE.charAt(0); + + /** characters in the overflow message, including the (optional) final + * newline */ + private static final int OVERFLOW_SIZE = OVERFLOW_MESSAGE.length(); + + /** + * characters in buffer for building string representations of + * longs. A long is a signed 64-bit integer in the range -2^63 to + * 2^63+1. The number of digits in the decimal representation of + * 2^63 is ceiling(log10(2^63)) == ceiling(63 * log10(2)) == 19. An + * extra character may be required for a minus sign (-). So the + * maximum number of characters is 20. + */ + private static final int TEMP_BUFFER_SIZE = 20; + + /** string that prefixes numbers logged in hexadecimal */ + private static final String HEX_PREFIX = "0x"; + + /** + * log2 of number of bits represented by a single hexidemimal digit + */ + private static final int LOG_BITS_IN_HEX_DIGIT = 2; + + /** + * log2 of number of digits in the unsigned hexadecimal + * representation of a byte + */ + private static final int LOG_HEX_DIGITS_IN_BYTE = LOG_BITS_IN_BYTE - LOG_BITS_IN_HEX_DIGIT; + + /** + * map of hexadecimal digit values to their character representations + */ + private static final char [] hexDigitCharacter = + { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + /** new line character. Emitted by writeln methods. */ + private static final char NEW_LINE_CHAR = '\n'; + + /** log instance used at build time. */ + private static Log log = new Log(); + + /**************************************************************************** + * + * Instance variables + */ + + /** buffer to store written message until flushing */ + private char [] buffer = new char[MESSAGE_BUFFER_SIZE + OVERFLOW_SIZE]; + + /** location of next character to be written */ + private int bufferIndex = 0; + + /** true if the buffer has overflown */ + private boolean overflow = false; + + /** The last character that was written by #addToBuffer(char). This is + used to check whether we want to newline-terminate the text. */ + private char overflowLastChar = '\0'; + + /** true if a thread id will be prepended */ + private boolean threadIdFlag = false; + + /** buffer for building string representations of longs */ + private char[] tempBuffer = new char[TEMP_BUFFER_SIZE]; + + /** constructor */ + public Log() { + for (int i = 0; i < OVERFLOW_SIZE; i++) { + buffer[MESSAGE_BUFFER_SIZE + i] = OVERFLOW_MESSAGE.charAt(i); + } + } + + /** + * writes a boolean. Either "true" or "false" is logged. + * + * @param b boolean value to be logged. + */ + public static void write(boolean b) { + write(b ? "true" : "false"); + } + + /** + * writes a character + * + * @param c character to be logged + */ + public static void write(char c) { + add(c); + } + + /** + * writes a long, in decimal. The value is not padded and no + * thousands seperator is logged. If the value is negative a + * leading minus sign (-) is logged. + * + * + * @param l long value to be logged + */ + public static void write(long l) { + boolean negative = l < 0; + int nextDigit; + char nextChar; + int index = TEMP_BUFFER_SIZE - 1; + char[] intBuffer = getIntBuffer(); + + nextDigit = (int) (l % 10); + nextChar = hexDigitCharacter[negative ? - nextDigit : nextDigit]; + intBuffer[index--] = nextChar; + l = l / 10; + + while (l != 0) { + nextDigit = (int) (l % 10); + nextChar = hexDigitCharacter[negative ? - nextDigit : nextDigit]; + intBuffer[index--] = nextChar; + l = l / 10; + } + + if (negative) { + intBuffer[index--] = '-'; + } + + for (index++; index < TEMP_BUFFER_SIZE; index++) { + add(intBuffer[index]); + } + } + + /** + * writes a double. Two digits after the decimal point + * are always logged. The value is not padded and no thousands + * seperator is used. If the value is negative a leading + * hyphen-minus (-) is logged. The decimal point is a full stop + * (.). + * + * @param d the double to be logged + */ + public static void write(double d) { write(d, 2); } + + /** + * writes a double. The number of digits after the + * decimal point is determined by postDecimalDigits. + * The value is not padded and not thousands seperator is used. If + * the value is negative a leading hyphen-minus (-) is logged. The + * decimal point is a full stop (.) and is logged even if + * is zero. If d is greater + * than the largest representable value of type int, it + * is logged as "TooBig". Similarly, if it is less than + * the negative of the largest representable value, it is logged as + * "TooSmall". If d is NaN is is logged as "NaN". + * + * @param d the double to be logged + * @param postDecimalDigits the number of digits to be logged after + * the decimal point. If less than or equal to zero no digits are + * logged, but the decimal point is. + */ + public static void write(double d, int postDecimalDigits) { + if (d != d) { + write("NaN"); + return; + } + if (d > Integer.MAX_VALUE) { + write("TooBig"); + return; + } + if (d < -Integer.MAX_VALUE) { + write("TooSmall"); + return; + } + + boolean negative = (d < 0.0); + d = negative ? (-d) : d; // Take absolute value + int ones = (int) d; + int multiplier = 1; + while (postDecimalDigits-- > 0) + multiplier *= 10; + int remainder = (int) (multiplier * (d - ones)); + if (remainder < 0) remainder = 0; + if (negative) write('-'); + write(ones); + write('.'); + while (multiplier > 1) { + multiplier /= 10; + write(remainder / multiplier); + remainder %= multiplier; + } + } + + /** + * writes an array of characters + * + * @param c the array of characters to be logged + */ + public static void write(char[] c) { + write(c, c.length); + } + + /** + * writes the start of an array of characters + * + * @param c the array of characters + * @param len the number of characters to be logged, starting with + * the first character + */ + public static void write(char[] c, int len) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(len <= c.length); + for (int i = 0; i < len; i++) { + add(c[i]); + } + } + + /** + * writes an array of bytes. The bytes are interpretted + * as characters. + * + * @param b the array of bytes to be logged + */ + public static void write(byte[] b) { + for (int i = 0; i < b.length; i++) { + add((char)b[i]); + } + } + + /** + * writes a string + * + * @param s the string to be logged + */ + public static void write(String s) { + add(s); + } + + /** + * writes a word, in hexadecimal. It is zero-padded to the size of + * an address. + * + * @param w the word to be logged + */ + public static void write(Word w) { + writeHex(w, BYTES_IN_ADDRESS); + } + + /** + * writes a word, in decimal. + * + * @param w the word to be logged + */ + public static void writeDec(Word w) { + if (BYTES_IN_ADDRESS == 4) { + write(w.toInt()); + } else { + write(w.toLong()); + } + } + + /** + * writes an address, in hexademical. It is zero-padded. + * + * @param a the address to be logged + */ + public static void write(Address a) { + writeHex(a.toWord(), BYTES_IN_ADDRESS); + } + + /** + * writes a string followed by an address, in hexademical. + * @see #write(String) + * @see #write(Address) + * + * @param s the string to be logged + * @param a the address to be logged + */ + public static void write(String s, Address a) { + write(s); + write(a); + } + + /** + * Write a string followed by a long + * @see #write(String) + * @see #write(long) + * + * @param s the string to be logged + * @param l the long to be logged + */ + public static void write(String s, long l) { + write(s); + write(l); + } + + /** + * writes an object reference, in hexademical. It is zero-padded. + * + * @param o the object reference to be logged + */ + public static void write(ObjectReference o) { + writeHex(o.toAddress().toWord(), BYTES_IN_ADDRESS); + } + + /** + * writes an offset, in hexademical. It is zero-padded. + * + * @param o the offset to be logged + */ + public static void write(Offset o) { + writeHex(o.toWord(), BYTES_IN_ADDRESS); + } + + /** + * writes an extent, in hexademical. It is zero-padded. + * + * @param e the extent to be logged + */ + public static void write(Extent e) { + writeHex(e.toWord(), BYTES_IN_ADDRESS); + } + + /** + * write a new-line and flushes the buffer + */ + public static void writeln() { + writelnWithFlush(true); + } + + /** + * writes a boolean and a new-line, then flushes the buffer. + * @see #write(boolean) + * + * @param b boolean value to be logged. + */ + public static void writeln(boolean b) { writeln(b, true); } + + /** + * writes a character and a new-line, then flushes the buffer. + * @see #write(char) + * + * @param c character to be logged + */ + public static void writeln(char c) { writeln(c, true); } + + /** + * writes a long, in decimal, and a new-line, then flushes the buffer. + * @see #write(long) + * + * @param l long value to be logged + */ + public static void writeln(long l) { writeln(l, true); } + + /** + * writes a double and a new-line, then flushes the buffer. + * @see #write(double) + * + * @param d the double to be logged + */ + public static void writeln(double d) { writeln(d, true); } + + /** + * writes a double and a new-line, then flushes the buffer. + * @see #write(double, int) + * + * @param d the double to be logged + */ + public static void writeln(double d, int postDecimalDigits) { + writeln(d, postDecimalDigits, true); } + + /** + * writes an array of characters and a new-line, then flushes the buffer. + * @see #write(char []) + * + * @param ca the array of characters to be logged + */ + public static void writeln(char [] ca) { writeln(ca, true); } + + /** + * writes the start of an array of characters and a new-line, then + * flushes the buffer. + * @see #write(char[], int) + * + * @param ca the array of characters + * @param len the number of characters to be logged, starting with + * the first character + */ + public static void writeln(char [] ca, int len) { writeln(ca, len, true); } + + /** + * writes an array of bytes and a new-line, then + * flushes the buffer. + * @see #write(byte[]) + * + * @param b the array of bytes to be logged + */ + public static void writeln(byte [] b) { writeln(b, true); } + + /** + * writes a string and a new-line, then flushes the buffer. + * + * @param s the string to be logged + */ + public static void writeln(String s) { writeln(s, true); } + + /** + * writes a word, in hexadecimal, and a new-line, then flushes the buffer. + * @see #write(Word) + * + * @param w the word to be logged + */ + public static void writeln(Word w) { writeln(w, true); } + + /** + * writes an address, in hexademical, and a new-line, then flushes + * the buffer. + * @see #write(Address) + * + * @param a the address to be logged + */ + public static void writeln(Address a) { writeln(a, true); } + + /** + * writes an object reference, in hexademical, and a new-line, then + * flushes the buffer. + * @see #write(ObjectReference) + * + * @param o the object reference to be logged + */ + public static void writeln(ObjectReference o) { writeln(o, true); } + + /** + * writes an offset, in hexademical, and a new-line, then flushes the buffer. + * @see #write(Offset) + * + * @param o the offset to be logged + */ + public static void writeln(Offset o) { writeln(o, true); } + + /** + * writes an extent, in hexademical, and a new-line, then flushes the buffer. + * @see #write(Extent) + * + * @param e the extent to be logged + */ + public static void writeln(Extent e) { writeln(e, true); } + + /** + * writes a new-line without flushing the buffer + */ + public static void writelnNoFlush() { + writelnWithFlush(false); + } + + /** + * writes a boolean and a new-line, then optionally flushes the buffer. + * @see #write(boolean) + * + * @param b boolean value to be logged. + * @param flush if true then flushes the buffer + */ + public static void writeln(boolean b, boolean flush) { + write(b); + writelnWithFlush(flush); + } + + /** + * writes a character and a new-line, then optionally flushes the + * buffer. + * @see #write(char) + * + * @param c character to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(char c, boolean flush) { + write(c); + writelnWithFlush(flush); + } + + /** + * writes a long, in decimal, and a new-line, then optionally flushes + * the buffer. + * @see #write(long) + * + * @param l long value to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(long l, boolean flush) { + write(l); + writelnWithFlush(flush); + } + + /** + * writes a double and a new-line, then optionally flushes + * the buffer. + * @see #write(double) + * + * @param d the double to be logged + * @param flush if true then flush the buffer + */ + public static void writeln(double d, boolean flush) { + write(d); + writelnWithFlush(flush); + } + + /** + * writes a double and a new-line, then optionally flushes + * the buffer. + * @see #write(double, int) + * + * @param d the double to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(double d, int postDecimalDigits, boolean flush) { + write(d, postDecimalDigits); + writelnWithFlush(flush); + } + + + /** + * writes an array of characters and a new-line, then optionally + * flushes the buffer. + * @see #write(char []) + * + * @param ca the array of characters to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(char[] ca, boolean flush) { + write(ca); + writelnWithFlush(flush); + } + + /** + * writes the start of an array of characters and a new-line, then + * optionally flushes the buffer. + * @see #write(char[], int) + * + * @param ca the array of characters + * @param len the number of characters to be logged, starting with + * the first character + * @param flush if true then flushes the buffer + */ + public static void writeln(char[] ca, int len, boolean flush) { + write(ca, len); + writelnWithFlush(flush); + } + + /** + * writes an array of bytes and a new-line, then optionally flushes the + * buffer. + * @see #write(byte[]) + * + * @param b the array of bytes to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(byte[] b, boolean flush) { + write(b); + writelnWithFlush(flush); + } + + /** + * writes a string and a new-line, then optionally flushes the buffer. + * + * @param s the string to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(String s, boolean flush) { + write(s); + writelnWithFlush(flush); + } + + public static void writeln(String s, long l) { + write(s); + writeln(l); + } + + + /** + * writes a word, in hexadecimal, and a new-line, then optionally + * flushes the buffer. + * @see #write(Word) + * + * @param w the word to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(Word w, boolean flush) { + write(w); + writelnWithFlush(flush); + } + + + /** + * writes an address, in hexademical, and a new-line, then optionally + * flushes the buffer. + * @see #write(Address) + * + * @param a the address to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(Address a, boolean flush) { + write(a); + writelnWithFlush(flush); + } + + /** + * writes an object reference, in hexademical, and a new-line, then + * optionally flushes the buffer. + * @see #write(ObjectReference) + * + * @param o the object reference to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(ObjectReference o, boolean flush) { + write(o); + writelnWithFlush(flush); + } + + /** + * writes an offset, in hexademical, and a new-line, then optionally + * flushes the buffer. + * @see #write(Offset) + * + * @param o the offset to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(Offset o, boolean flush) { + write(o); + writelnWithFlush(flush); + } + + /** + * writes an extent, in hexademical, and a new-line, then optionally + * flushes the buffer. + * @see #write(Extent) + * + * @param e the extent to be logged + * @param flush if true then flushes the buffer + */ + public static void writeln(Extent e, boolean flush) { + write(e); + writelnWithFlush(flush); + } + + /** + * writes a string followed by a Address + * @see #write(String) + * @see #write(Address) + * + * @param s the string to be logged + * @param a the Address to be logged + */ + public static void writeln(String s, Address a) { + write(s); + writeln(a); + } + + /** + * Log a thread identifier at the start of the next message flushed. + */ + public static void prependThreadId() { + getLog().setThreadIdFlag(); + } + + /** + * flushes the buffer. The buffered effected of writes since the last + * flush will be logged in one block without output from other + * thread's logging interleaving. + */ + public static void flush() { + getLog().flushBuffer(); + } + + /** + * writes a new-line and optionally flushes the buffer + * + * @param flush if true the buffer is flushed + */ + private static void writelnWithFlush(boolean flush) { + add(NEW_LINE_CHAR); + if (flush) { + flush(); + } + } + + /** + * writes a long in hexadecimal + * + * @param w the Word to be logged + * @param bytes the number of bytes from the long to be logged. If + * less than 8 then the least significant bytes are logged and some + * of the most significant bytes are ignored. + */ + private static void writeHex(Word w, int bytes) { + int hexDigits = bytes * (1 << LOG_HEX_DIGITS_IN_BYTE); + int nextDigit; + + write(HEX_PREFIX); + + for (int digitNumber = hexDigits - 1; digitNumber >= 0; digitNumber--) { + nextDigit = w.rshl(digitNumber << LOG_BITS_IN_HEX_DIGIT).toInt() & 0xf; + char nextChar = hexDigitCharacter[nextDigit]; + add(nextChar); + } + } + + /** + * adds a character to the buffer + * + * @param c the character to add + */ + private static void add(char c) { + getLog().addToBuffer(c); + } + + /** + * adds a string to the buffer + * + * @param s the string to add + */ + private static void add(String s) { + getLog().addToBuffer(s); + } + + private static Log getLog() { + if (VM.assertions.runningVM()) { + return VM.activePlan.log(); + } else { + return log; + } + } + + /** + * adds a character to the buffer + * + * @param c the character to add + */ + private void addToBuffer(char c) { + if (bufferIndex < MESSAGE_BUFFER_SIZE) { + buffer[bufferIndex++] = c; + } else { + overflow = true; + overflowLastChar = c; + } + } + + /** + * adds a string to the buffer + * + * @param s the string to add + */ + private void addToBuffer(String s) { + if (bufferIndex < MESSAGE_BUFFER_SIZE) { + bufferIndex += VM.strings.copyStringToChars(s, buffer, bufferIndex, MESSAGE_BUFFER_SIZE + 1); + if (bufferIndex == MESSAGE_BUFFER_SIZE + 1) { + overflow = true; + // We don't bother setting OVERFLOW_LAST_CHAR, since we don't have an + // MMTk method that lets us peek into a string. Anyway, it's just a + // convenience to get the newline right. + buffer[MESSAGE_BUFFER_SIZE] = OVERFLOW_MESSAGE_FIRST_CHAR; + bufferIndex--; + } + } else { + overflow = true; + } + } + + /** + * flushes the buffer + */ + private void flushBuffer() { + int newlineAdjust = overflowLastChar == NEW_LINE_CHAR ? 0 : -1; + int totalMessageSize = overflow ? (MESSAGE_BUFFER_SIZE + OVERFLOW_SIZE + newlineAdjust) : bufferIndex; + if (threadIdFlag) { + VM.strings.writeThreadId(buffer, totalMessageSize); + } else { + VM.strings.write(buffer, totalMessageSize); + } + threadIdFlag = false; + overflow = false; + overflowLastChar = '\0'; + bufferIndex = 0; + } + + /** + * sets the flag so that a thread identifier will be included before + * the logged message + */ + private void setThreadIdFlag() { + threadIdFlag = true; + } + + /** + * gets the buffer for building string representations of integers. + * There is one of these buffers for each Log instance. + */ + private static char[] getIntBuffer() { + return getLog().getTempBuffer(); + } + + /** + * gets the buffer for building string representations of integers. + */ + private char[] getTempBuffer() { + return tempBuffer; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,216 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements basic memory copying, setting and clearing + * operations. + * + * NOTE: Most of the operations in this class are performed at teh + * granularity of a Java integer (ie 4-byte units) + * + * FIXME: Why can't these operations be performed at word-granularity? + */ + at Uninterruptible +public class Memory implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + /** zero operations greater than this size are done using the + * underlying OS implementation of zero() */ + private static final int SMALL_REGION_THRESHOLD = 1<<8; // empirically chosen + + + /**************************************************************************** + * + * Basic memory setting and zeroing operations + */ + + /** + * Zero a region of memory + * + * @param start The start of the region to be zeroed (must be 4-byte aligned) + * @param bytes The number of bytes to be zeroed (must be 4-byte aligned) + */ + @Inline + public static void zero(Address start, Extent bytes) { + if (VM.VERIFY_ASSERTIONS) { + assertAligned(start); + assertAligned(bytes); + } + if (bytes.GT(Extent.fromIntZeroExtend(SMALL_REGION_THRESHOLD))) + VM.memory.zero(start, bytes); + else + zeroSmall(start, bytes); + } + + /** + * Zero a small region of memory + * + * @param start The start of the region to be zeroed (must be 4-byte aligned) + * @param bytes The number of bytes to be zeroed (must be 4-byte aligned) + */ + @Inline + public static void zeroSmall(Address start, Extent bytes) { + if (VM.VERIFY_ASSERTIONS) { + assertAligned(start); + assertAligned(bytes); + } + Address end = start.plus(bytes); + for (Address addr = start; addr.LT(end); addr = addr.plus(BYTES_IN_INT)) + addr.store(0); + } + + /** + * Set a region of memory + * + * @param start The start of the region to be zeroed (must be 4-byte aligned) + * @param bytes The number of bytes to be zeroed (must be 4-byte aligned) + * @param value The value to which the integers in the region should be set + */ + @Inline + public static void set(Address start, int bytes, int value) { + if (VM.VERIFY_ASSERTIONS) { + assertAligned(start); + assertAligned(bytes); + } + Address end = start.plus(bytes); + for (Address addr = start; addr.LT(end); addr = addr.plus(BYTES_IN_INT)) + addr.store(value); + } + + + /**************************************************************************** + * + * Helper methods + */ + + /** + * Check that a memory range is zeroed + * + * @param start The start address of the range to be checked + * @param bytes The size of the region to be checked, in bytes + * @return True if the region is zeroed + */ + @Inline + public static boolean IsZeroed(Address start, int bytes) { + return isSet(start, bytes, false, 0); + } + + /** + * Assert that a memory range is zeroed. An assertion failure will + * occur if the region is not zeroed. + * + * this is in the inline allocation sequence when + * VM.VERIFY_ASSERTIONS is true, it is carefully written to + * reduce the impact on code space. + * + * @param start The start address of the range to be checked + * @param bytes The size of the region to be checked, in bytes + */ + @NoInline + public static void assertIsZeroed(Address start, int bytes) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isSet(start, bytes, true, 0)); + } + + /** + * Verbosely check and return true if a memory range is set to some + * integer value + * + * @param start The start address of the range to be checked + * @param bytes The size of the region to be checked, in bytes + * @param value The value to which this region should be set + * @return True if the region has been correctly set + */ + @Inline + public static boolean isSet(Address start, int bytes, int value) { + return isSet(start, bytes, true, value); + } + + /** + * Assert appropriate alignment, triggering an assertion failure if + * the value does not satisify the alignment requirement of the + * memory operations. + * + * @param value The value to be tested + */ + private static void assertAligned(int value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & (BYTES_IN_INT - 1)) == 0); + } + + private static void assertAligned(Word value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(Word.fromIntSignExtend(BYTES_IN_INT-1)).isZero()); + } + + private static void assertAligned(Extent value) { + assertAligned(value.toWord()); + } + + private static void assertAligned(Address value) { + assertAligned(value.toWord()); + } + + /** + * Test whether a memory range is set to a given integer value + * + * @param start The address to start checking at + * @param bytes The size of the region to check, in bytes + * @param verbose If true, produce verbose output + * @param value The value to which the memory should be set + */ + @NoInline + private static boolean isSet(Address start, int bytes, boolean verbose, + int value) + /* Inlining this loop into the uninterruptible code can + * cause/encourage the GCP into moving a get_obj_tib into the + * interruptible region where the tib is being installed via an + * int_store + */ { + if (VM.VERIFY_ASSERTIONS) assertAligned(bytes); + for (int i = 0; i < bytes; i += BYTES_IN_INT) + if (start.loadInt(Offset.fromIntSignExtend(i)) != value) { + if (verbose) { + Log.prependThreadId(); + Log.write("VM range does not contain only value "); + Log.writeln(value); + Log.write("Non-zero range: "); Log.write(start); + Log.write(" .. "); Log.writeln(start.plus(bytes)); + Log.write("First bad value at "); Log.writeln(start.plus(i)); + dumpMemory(start, 0, bytes); + } + return false; + } + return true; + } + + /** + * Dump the contents of memory around a given address + * + * @param addr The address around which the memory should be dumped + * @param beforeBytes The number of bytes before the address to be + * included in the dump + * @param afterBytes The number of bytes after the address to be + * included in the dump + */ + public static void dumpMemory(Address addr, int beforeBytes, int afterBytes) { + VM.memory.dumpMemory(addr, beforeBytes, afterBytes); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,232 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.mmtk.policy.RawPageSpace; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements a simple hashtable. It is intended for use + * in sanity checking or debugging, not high-performance algorithms.

+ * + * This class is not thread safe. + */ + at Uninterruptible public abstract class SimpleHashtable implements Constants { + /** The number of low order bits to ignore */ + private static final int HASH_SHIFT = 3; + + /** Offset to the key */ + private static final Offset KEY_OFFSET = Offset.zero(); + + /** Offset to the data */ + private static final Offset DATA_OFFSET = Offset.fromIntSignExtend(BYTES_IN_WORD); + + /** The size of each entry in the table */ + private final Extent entrySize; + + /** The mask to use to get the hash code */ + private final Word mask; + + /** The start address of the data table */ + private Address base; + + /** The full size of the table */ + private final Extent size; + + /** The space to use for allocating the data structure */ + private final RawPageSpace space; + + /** Is this table valid (created) */ + private boolean valid; + + /** + * Create a new data table of a specified size. + * + * @param rps The space to acquire the data structure from. + * @param logSize The log of the number of table entries. + * @param es The size of each entry. + */ + protected SimpleHashtable(RawPageSpace rps, int logSize, Extent es) { + mask = Word.fromIntZeroExtend((1 << logSize) - 1); + entrySize = es.plus(BYTES_IN_WORD); + size = Extent.fromIntZeroExtend((1 << logSize) * entrySize.toInt()); + base = Address.zero(); + space = rps; + valid = false; + } + + /** + * Create a (zeroed) table. + */ + public final void acquireTable() { + base = space.acquire(Conversions.bytesToPages(size)); + VM.memory.zero(base, size); + valid = true; + } + + /** + * Drop the table (after collection). + */ + public final void releaseTable() { + space.release(base); + valid = false; + } + + /** + * @return True if this table has backing data and is ready for use. + */ + public final boolean isValid() { + return valid; + } + + /** + * Retrieve a pointer to the entry for the given object, or zero if one + * does not exist, unless create is passed.

+ * + * If create is true, the return is guaranteed to be non-null. + * + * @param key The key used to lookup. + * @param create Create a new entry if not found. + * @return A pointer to the reference or null. + */ + @Inline + public final Address getEntry(Word key, boolean create) { + int startIndex = computeHash(key); + int index = startIndex; + Word curAddress; + Address entry; + do { + entry = getEntry(index); + curAddress = entry.loadWord(KEY_OFFSET); + index = (index + 1) & mask.toInt(); + } while(curAddress.NE(key) && + !curAddress.isZero() && + index != startIndex); + + if (index == startIndex) { + VM.assertions.fail("No room left in table!"); + } + + if (curAddress.isZero()) { + if (!create) return Address.zero(); + entry.store(key, KEY_OFFSET); + } + + return entry; + } + + /** + * Compute the hashtable index for a given object. + * + * @param key The key. + * @return The index. + */ + @Inline + private int computeHash(Word key) { + return key.rshl(HASH_SHIFT).and(mask).toInt(); + } + + /** + * Return the address of a specified entry in the table. + * + * @param index The index of the entry. + * @return An address to the entry. + */ + @Inline + private Address getEntry(int index) { + return base.plus(Extent.fromIntZeroExtend(index * entrySize.toInt())); + } + + /** + * Does the passed object have an entry in the table? + * + * @param key The key to find an entry for + * @return True if there is an entry for that object. + */ + public final boolean contains(Word key) { + return !getEntry(key, false).isZero(); + } + + /** + * @return The first non-zero element in the table, or null if + * the table is empty. + */ + public final Address getFirst() { + return getNext(base.minus(entrySize)); + } + + /** + * The next element in the table after the passed entry, or + * null if it is the last entry. + * + * @param curr The object to look for the next entry from. + * @return The next entry or null. + */ + public final Address getNext(Address curr) { + Address entry = curr.plus(entrySize); + while (entry.LT(base.plus(size))) { + if (!entry.loadWord().isZero()) return entry; + entry = entry.plus(entrySize); + } + return Address.zero(); + } + + /** + * Given an address of an entry, return a pointer to the payload. + * + * @param entry The entry + * @return The object reference. + */ + public static Address getPayloadAddress(Address entry) { + return entry.plus(DATA_OFFSET); + } + + /** + * Given a key, return a pointer to the payload. + * + * @param key The key + * @return The object reference. + */ + public final Address getPayloadAddress(Word key) { + Address entry = getEntry(key, false); + if (entry.isZero()) return Address.zero(); + + return entry.plus(DATA_OFFSET); + } + + + /** + * Return the key for a given entry. + * + * @param entry The entry. + * @return The key. + */ + public static Word getKey(Address entry) { + return entry.loadWord(KEY_OFFSET); + } + + /** + * Update the key for a given entry. This operation is not + * safe without rehashing + * + * @param entry The entry to update. + * @param key The new key. + */ + public static void replaceKey(Address entry, Word key) { + entry.store(key, KEY_OFFSET); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,22 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.vmmagic.pragma.*; + +/* + */ + at Uninterruptible public class Synchronize{ + + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,410 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.semispace.gctrace.GCTrace; +import org.mmtk.plan.TraceLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.deque.*; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.options.TraceRate; + +import org.mmtk.vm.VM; +import org.mmtk.vm.Collection; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * Class that supports scanning Objects and Arrays for references + * during tracing, handling those references, and computing death times + */ + at Uninterruptible public final class TraceGenerator + implements Constants, TracingConstants { + + + /*********************************************************************** + * + * Class variables + */ + + /* Type of lifetime analysis to be used */ + public static final boolean MERLIN_ANALYSIS = true; + + /* include the notion of build-time allocation to our list of allocators */ + private static final int ALLOC_BOOT = GCTrace.ALLOCATORS; + private static final int ALLOCATORS = ALLOC_BOOT + 1; + + /* Fields for tracing */ + private static SortTODSharedDeque tracePool; // Buffers to hold raw trace + private static TraceBuffer trace; + private static boolean traceBusy; // If we are building the trace + private static Word lastGC; // Last time GC was performed + private static ObjectReferenceArray objectLinks; // Lists of active objs + + /* Fields needed for Merlin lifetime analysis */ + private static SortTODSharedDeque workListPool; // Holds objs to process + private static SortTODObjectReferenceStack worklist; // Objs to process + private static Word agePropagate; // Death time propagating + + static { + traceBusy = false; + lastGC = Word.fromIntZeroExtend(4); + Options.traceRate = new TraceRate(); + } + + + /*********************************************************************** + * + * Public analysis methods + */ + + /** + * This is called at "build-time" and passes the necessary build image + * objects to the trace processor. + * + * @param worklist_ The dequeue that serves as the worklist for + * death time propagation + * @param trace_ The dequeue used to store and then output the trace + */ + @Interruptible + public static void init(SortTODSharedDeque worklist_, + SortTODSharedDeque trace_) { + /* Objects are only needed for merlin tracing */ + if (MERLIN_ANALYSIS) { + workListPool = worklist_; + worklist = new SortTODObjectReferenceStack(workListPool); + } + + /* Trace objects */ + tracePool = trace_; + trace = new TraceBuffer(tracePool); + objectLinks = ObjectReferenceArray.create(Space.MAX_SPACES); + } + + /** + * This is called immediately before Jikes terminates. It will perform + * any death time processing that the analysis requires and then output + * any remaining information in the trace buffer. + * + * @param value The integer value for the reason Jikes is terminating + */ + public static void notifyExit(int value) { + if (MERLIN_ANALYSIS) + findDeaths(); + trace.process(); + } + + /** + * Add a newly allocated object into the linked list of objects in a region. + * This is typically called after each object allocation. + * + * @param ref The address of the object to be added to the linked list + * @param linkSpace The region to which the object should be added + */ + public static void addTraceObject(ObjectReference ref, int linkSpace) { + VM.traceInterface.setLink(ref, objectLinks.get(linkSpace)); + objectLinks.set(linkSpace, ref); + } + + /** + * Do the work necessary following each garbage collection. This HAS to be + * called after EACH collection. + */ + public static void postCollection() { + /* Find and output the object deaths */ + traceBusy = true; + findDeaths(); + traceBusy = false; + trace.process(); + } + + + /*********************************************************************** + * + * Trace generation code + */ + + /** + * Add the information in the bootImage to the trace. This should be + * called before any allocations and pointer updates have occured. + * + * @param bootStart The address at which the bootimage starts + */ + public static void boot(Address bootStart) { + Word nextOID = VM.traceInterface.getOID(); + ObjectReference trav = VM.traceInterface.getBootImageLink().plus(bootStart.toWord().toOffset()).toObjectReference(); + objectLinks.set(ALLOC_BOOT, trav); + /* Loop through all the objects within boot image */ + while (!trav.isNull()) { + ObjectReference next = VM.traceInterface.getLink(trav); + Word thisOID = VM.traceInterface.getOID(trav); + /* Add the boot image object to the trace. */ + trace.push(TRACE_BOOT_ALLOC); + trace.push(thisOID); + trace.push(nextOID.minus(thisOID).lsh(LOG_BYTES_IN_ADDRESS)); + nextOID = thisOID; + /* Move to the next object & adjust for starting address of + the bootImage */ + if (!next.isNull()) { + next = next.toAddress().plus(bootStart.toWord().toOffset()).toObjectReference(); + VM.traceInterface.setLink(trav, next); + } + trav = next; + } + } + + /** + * Do any tracing work required at each a pointer store operation. This + * will add the pointer store to the trace buffer and, when Merlin lifetime + * analysis is being used, performs the necessary timestamping. + * + * @param isScalar If this is a pointer store to a scalar object + * @param src The address of the source object + * @param slot The address within src into which + * tgt will be stored + * @param tgt The target of the pointer store + */ + @NoInline + public static void processPointerUpdate(boolean isScalar, + ObjectReference src, + Address slot, ObjectReference tgt) { + // The trace can be busy only if this is a pointer update as a result of + // the garbage collection needed by tracing. For the moment, we will + // not report these updates. + if (!traceBusy) { + /* Process the old target potentially becoming unreachable when needed. */ + if (MERLIN_ANALYSIS) { + ObjectReference oldTgt = slot.loadObjectReference(); + if (!oldTgt.isNull()) + VM.traceInterface.updateDeathTime(oldTgt); + } + + traceBusy = true; + /* Add the pointer store to the trace */ + Offset traceOffset = VM.traceInterface.adjustSlotOffset(isScalar, src, slot); + if (isScalar) + trace.push(TRACE_FIELD_SET); + else + trace.push(TRACE_ARRAY_SET); + trace.push(VM.traceInterface.getOID(src)); + trace.push(traceOffset.toWord()); + if (tgt.isNull()) + trace.push(Word.zero()); + else + trace.push(VM.traceInterface.getOID(tgt)); + traceBusy = false; + } + } + + /** + * Do any tracing work required at each object allocation. This will add the + * object allocation to the trace buffer, triggers the necessary collection + * work at exact allocations, and output the data in the trace buffer. + * + * @param ref The address of the object just allocated. + * @param typeRef the type reference for the instance being created + * @param bytes The size of the object being allocated + */ + @LogicallyUninterruptible + @NoInline + public static void traceAlloc(boolean isImmortal, ObjectReference ref, + ObjectReference typeRef, int bytes) { + boolean gcAllowed = VM.traceInterface.gcEnabled() && Plan.isInitialized() && !Plan.gcInProgress(); + /* Test if it is time/possible for an exact allocation. */ + Word oid = VM.traceInterface.getOID(ref); + Word allocType; + if (gcAllowed && (oid.GE(lastGC.plus(Word.fromIntZeroExtend(Options.traceRate.getValue()))))) + allocType = TRACE_EXACT_ALLOC; + else { + allocType = TRACE_ALLOC; + } + /* Add the allocation into the trace. */ + traceBusy = true; + /* When legally permissible, add the record to the trace buffer */ + if (MERLIN_ANALYSIS) { + Address fp = (TraceBuffer.OMIT_ALLOCS) ? Address.zero() : VM.traceInterface.skipOwnFramesAndDump(typeRef); + + if (isImmortal && allocType.EQ(TRACE_EXACT_ALLOC)) + trace.push(TRACE_EXACT_IMMORTAL_ALLOC); + else if (isImmortal) + trace.push(TRACE_IMMORTAL_ALLOC); + else + trace.push(allocType); + trace.push(VM.traceInterface.getOID(ref)); + trace.push(Word.fromIntZeroExtend(bytes - VM.traceInterface.getHeaderSize())); + trace.push(fp.toWord()); + trace.push(Word.zero()); /* Magic.getThreadId() */ + trace.push(TRACE_TIB_SET); + trace.push(VM.traceInterface.getOID(ref)); + trace.push(VM.traceInterface.getOID(typeRef)); + } + /* Perform the necessary work for death times. */ + if (allocType.EQ(TRACE_EXACT_ALLOC)) { + if (MERLIN_ANALYSIS) { + lastGC = VM.traceInterface.getOID(ref); + VM.traceInterface.updateTime(lastGC); + VM.collection.triggerCollection(Collection.INTERNAL_GC_TRIGGER); + } else { + VM.collection.triggerCollection(Collection.RESOURCE_GC_TRIGGER); + lastGC = VM.traceInterface.getOID(ref); + } + } + /* Add the allocation record to the buffer if we have not yet done so. */ + if (!MERLIN_ANALYSIS) { + Address fp = (TraceBuffer.OMIT_ALLOCS) ? Address.zero() : VM.traceInterface.skipOwnFramesAndDump(typeRef); + if (isImmortal && allocType.EQ(TRACE_EXACT_ALLOC)) + trace.push(TRACE_EXACT_IMMORTAL_ALLOC); + else if (isImmortal) + trace.push(TRACE_IMMORTAL_ALLOC); + else + trace.push(allocType); + trace.push(VM.traceInterface.getOID(ref)); + trace.push(Word.fromIntZeroExtend(bytes - VM.traceInterface.getHeaderSize())); + trace.push(fp.toWord()); + trace.push(Word.zero()); /* Magic.getThreadId() */ + trace.push(TRACE_TIB_SET); + trace.push(VM.traceInterface.getOID(ref)); + trace.push(VM.traceInterface.getOID(typeRef)); + } + trace.process(); + traceBusy = false; + } + + /*********************************************************************** + * + * Merlin lifetime analysis methods + */ + + /** + * This computes and adds to the trace buffer the unreachable time for + * all of the objects that are _provably_ unreachable. This method + * should be called after garbage collection (but before the space has + * been reclaimed) and at program termination. + */ + private static void findDeaths() { + /* Only the merlin analysis needs to compute death times */ + if (MERLIN_ANALYSIS) { + /* Start with an empty stack. */ + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(worklist.isEmpty()); + /* Scan the linked list of objects within each region */ + for (int allocator = 0; allocator < ALLOCATORS; allocator++) { + ObjectReference thisRef = objectLinks.get(allocator); + /* Start at the top of each linked list */ + while (!thisRef.isNull()) { + /* Add the unreachable objects onto the worklist. */ + if (!getTraceLocal().isReachable(thisRef)) + worklist.push(thisRef); + thisRef = VM.traceInterface.getLink(thisRef); + } + } + /* Sort the objects on the worklist by their timestamp */ + if (!worklist.isEmpty()) + worklist.sort(); + /* Now compute the death times. */ + computeTransitiveClosure(); + } + /* Output the death times for each object */ + for (int allocator = 0; allocator < ALLOCATORS; allocator++) { + ObjectReference thisRef = objectLinks.get(allocator); + ObjectReference prevRef = ObjectReference.nullReference(); // the last live object seen + while (!thisRef.isNull()) { + ObjectReference nextRef = VM.traceInterface.getLink(thisRef); + /* Maintain reachable objects on the linked list of allocated objects */ + if (getTraceLocal().isReachable(thisRef)) { + thisRef = getTraceLocal().getForwardedReference(thisRef); + VM.traceInterface.setLink(thisRef, prevRef); + prevRef = thisRef; + } else { + /* For brute force lifetime analysis, objects become + unreachable "now" */ + Word deadTime; + if (MERLIN_ANALYSIS) + deadTime = VM.traceInterface.getDeathTime(thisRef); + else + deadTime = lastGC; + /* Add the death record to the trace for unreachable objects. */ + trace.push(TRACE_DEATH); + trace.push(VM.traceInterface.getOID(thisRef)); + trace.push(deadTime); + } + thisRef = nextRef; + } + /* Purge the list of unreachable objects... */ + objectLinks.set(allocator, prevRef); + } + } + + /** + * This method is called for each root-referenced object at every Merlin + * root enumeration. The method will update the death time of the parameter + * to the current trace time. + * + * @param obj The root-referenced object + */ + public static void rootEnumerate(ObjectReference obj) { + VM.traceInterface.updateDeathTime(obj); + } + + /** + * This propagates the death time being computed to the object passed as an + * address. If we find the unreachable time for the parameter, it will be + * pushed on to the processing stack. + * + * @param ref The address of the object to examine + */ + public static void propagateDeathTime(ObjectReference ref) { + /* If this death time is more accurate, set it. */ + if (VM.traceInterface.getDeathTime(ref).LT(agePropagate)) { + /* If we should add the object for further processing. */ + if (!getTraceLocal().isReachable(ref)) { + VM.traceInterface.setDeathTime(ref, agePropagate); + worklist.push(ref); + } else { + VM.traceInterface.setDeathTime(getTraceLocal().getForwardedReference(ref), agePropagate); + } + } + } + + /** + * This finds all object death times by computing the (limited) + * transitive closure of the dead objects. Death times are computed + * as the latest reaching death time to an object. + */ + private static void computeTransitiveClosure() { + if (!worklist.isEmpty()) { + /* The latest time an object can die. */ + agePropagate = Word.max(); + /* Process through the entire buffer. */ + ObjectReference ref = worklist.pop(); + while (!ref.isNull()) { + Word currentAge = VM.traceInterface.getDeathTime(ref); + /* This is a cheap and simple test to process objects only once. */ + if (currentAge.LE(agePropagate)) { + /* Set the "new" dead age. */ + agePropagate = currentAge; + /* Scan the object, pushing the survivors */ + VM.scanning.scanObject(getTraceLocal(), ref); + } + /* Get the next object to process */ + ref = worklist.pop(); + } + } + } + + private static TraceLocal getTraceLocal() { + return VM.activePlan.collector().getCurrentTrace(); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,41 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.vmmagic.unboxed.*; + +/** + * The constants needed when storing events and then generating the trace. + */ +public interface TracingConstants { + Word TRACE_EXACT_ALLOC = Word.zero(); + Word TRACE_BOOT_ALLOC = Word.one().lsh(0); + Word TRACE_ALLOC = Word.one().lsh(1); + Word TRACE_DEATH = Word.one().lsh(2); + Word TRACE_FIELD_SET = Word.one().lsh(3); + Word TRACE_ARRAY_SET = Word.one().lsh(4); + Word TRACE_TIB_SET = Word.one().lsh(5); + Word TRACE_STATIC_SET = Word.one().lsh(6); + Word TRACE_BOOTSTART = Word.one().lsh(7); + Word TRACE_BOOTEND = Word.one().lsh(8); + Word TRACE_GCSTART = Word.one().lsh(9); + Word TRACE_GCEND = Word.one().lsh(10); + Word TRACE_GCROOT = Word.one().lsh(11); + Word TRACE_GCBAR = Word.one().lsh(12); + Word TRACE_THREAD_SWITCH = Word.one().lsh(13); + Word TRACE_STACKDELTA = Word.one().lsh(14); + Word TRACE_ROOTPTR = Word.one().lsh(15); + Word TRACE_EXACT_IMMORTAL_ALLOC = Word.one().lsh(16); + Word TRACE_IMMORTAL_ALLOC = Word.one().lsh(17); +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,187 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility; + +import org.mmtk.utility.gcspy.drivers.TreadmillDriver; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * FIXME The DoublyLinkedList class, upon which this depends, must be + * re-written as it makes the assumption that the implementation + * language (Java) and the language being implemented are the same. + * This is true in the case of Jikes RVM, but it is not true for any + * VM implementing a language other than Java. + * + * Each instance of this class is a doubly-linked list, in which + * each item or node is a piece of memory. The first two words of each node + * contains the forward and backward links. The third word contains + * the treadmill. The remaining portion is the payload. + * + * The treadmill object itself must not be moved. + * + * Access to the instances may be synchronized depending on the constructor argument. + */ + at Uninterruptible +public final class Treadmill implements Constants { + + /**************************************************************************** + * + * Instance variables + */ + private DoublyLinkedList fromSpace; + private DoublyLinkedList toSpace; + private DoublyLinkedList collectNursery; + private DoublyLinkedList allocNursery; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + */ + public Treadmill(int granularity, boolean shared) { + fromSpace = new DoublyLinkedList(granularity, shared); + toSpace = new DoublyLinkedList(granularity, shared); + allocNursery = new DoublyLinkedList(granularity, shared); + collectNursery = new DoublyLinkedList(granularity, shared); + } + + /** + * Add a node to the treadmill. This is usually performed on allocation. + */ + @Inline + public void addToTreadmill(Address node, boolean nursery) { + if (nursery) + allocNursery.add(node); + else + toSpace.add(node); + } + + /** + * Remove a node from the nursery list. + */ + @Inline + public Address popNursery() { + return collectNursery.pop(); + } + + /** + * Remove a node from the mature list. + */ + @Inline + public Address pop() { + return fromSpace.pop(); + } + + /** + * Copy a node (during gc tracing). + */ + @Inline + public void copy(Address node, boolean isInNursery) { + if (isInNursery) { + collectNursery.remove(node); + } else { + fromSpace.remove(node); + } + toSpace.add(node); + } + + /** + * Is the to-space empty? + */ + @Inline + public boolean toSpaceEmpty() { + return toSpace.isEmpty(); + } + + /** + * Is the from-space empty? + */ + @Inline + public boolean fromSpaceEmpty() { + return fromSpace.isEmpty(); + } + + /** + * Is the nursery empty? + */ + @Inline + public boolean nurseryEmpty() { + return collectNursery.isEmpty(); + } + + /** + * Flip the roles of the spaces in preparation for a collection. + */ + public void flip(boolean fullHeap) { + DoublyLinkedList tmp = allocNursery; + allocNursery = collectNursery; + collectNursery = tmp; + if (fullHeap) { + tmp = fromSpace; + fromSpace = toSpace; + toSpace = tmp; + } + } + + /**************************************************************************** + * + * Misc header manipulation + */ + + @Inline + public static int headerSize() { + return DoublyLinkedList.headerSize(); + } + + @Inline + public static Address nodeToPayload(Address payload) { + return DoublyLinkedList.nodeToPayload(payload); + } + + @Inline + public static Address midPayloadToNode(Address payload) { + return DoublyLinkedList.midPayloadToNode(payload); + } + + /**************************************************************************** + * + * GCSpy + */ + + /** + * Gather data for GCSpy from the nursery + * @param event the gc event + * @param tmDriver the GCSpy space driver + */ + public void gcspyGatherData(int event, TreadmillDriver tmDriver) { + this.allocNursery.gcspyGatherData(tmDriver); + } + + /** + * Gather data for GCSpy + * @param event the gc event + * @param tmDriver the GCSpy space driver + * @param tospace gather from tospace? + */ + public void gcspyGatherData(int event, TreadmillDriver tmDriver, boolean tospace) { + if (tospace) + toSpace.gcspyGatherData(tmDriver); + else + fromSpace.gcspyGatherData(tmDriver); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,263 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.plan.Plan; +import org.mmtk.policy.Space; +import org.mmtk.utility.*; +import org.mmtk.utility.statistics.*; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This abstract base class provides the basis for processor-local + * allocation. The key functionality provided is the retry mechanism + * that is necessary to correctly handle the fact that a "slow-path" + * allocation can cause a GC which violate the uninterruptability assumption. + * This results in the thread being moved to a different processor so that + * the allocator object it is using is not actually the one for the processor + * it is running on. + * + * This class also includes functionality to assist allocators with + * ensuring that requests are aligned according to requests. + * + * Failing to handle this properly will lead to very hard to trace bugs + * where the allocation that caused a GC or allocations immediately following + * GC are run incorrectly. + */ + at Uninterruptible public abstract class Allocator implements Constants { + + /** + * Return the space this allocator is currently bound to. + * + * @return The Space. + */ + protected abstract Space getSpace(); + + /** + * Aligns up an allocation request. The allocation request accepts a + * region, that must be at least particle aligned, an alignment + * request (some power of two number of particles) and an offset (a + * number of particles). There is also a knownAlignment parameter to + * allow a more optimised check when the particular allocator in use + * always aligns at a coarser grain than individual particles, such + * as some free lists. + * + * @param region The region to align up. + * @param alignment The requested alignment + * @param offset The offset from the alignment + * @param knownAlignment The statically known minimum alignment. + * @return The aligned up address. + */ + @Inline + public static Address alignAllocation(Address region, int alignment, int offset, int knownAlignment, boolean fillAlignmentGap) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(knownAlignment >= MIN_ALIGNMENT); + VM.assertions._assert(MIN_ALIGNMENT >= BYTES_IN_INT); + VM.assertions._assert(!(fillAlignmentGap && region.isZero())); + VM.assertions._assert(alignment <= MAX_ALIGNMENT); + VM.assertions._assert(offset >= 0); + VM.assertions._assert(region.toWord().and(Word.fromIntSignExtend(MIN_ALIGNMENT-1)).isZero()); + VM.assertions._assert((alignment & (MIN_ALIGNMENT - 1)) == 0); + VM.assertions._assert((offset & (MIN_ALIGNMENT - 1)) == 0); + } + + // No alignment ever required. + if (alignment <= knownAlignment || MAX_ALIGNMENT <= MIN_ALIGNMENT) + return region; + + // May require an alignment + Word mask = Word.fromIntSignExtend(alignment - 1); + Word negOff = Word.fromIntSignExtend(-offset); + Offset delta = negOff.minus(region.toWord()).and(mask).toOffset(); + + if (fillAlignmentGap && ALIGNMENT_VALUE != 0) { + if ((MAX_ALIGNMENT - MIN_ALIGNMENT) == BYTES_IN_WORD) { + // At most a single hole + if (delta.toInt() == (BYTES_IN_WORD)) { + region.store(Word.fromIntSignExtend(ALIGNMENT_VALUE)); + region = region.plus(delta); + return region; + } + } else { + while (delta.toInt() >= (BYTES_IN_WORD)) { + region.store(Word.fromIntSignExtend(ALIGNMENT_VALUE)); + region = region.plus(BYTES_IN_WORD); + delta = delta.minus(BYTES_IN_WORD); + } + } + } + + return region.plus(delta); + } + + /** + * Fill the specified region with the alignment value. + * + * @param start The start of the region. + * @param end A pointer past the end of the region. + */ + @Inline + public static void fillAlignmentGap(Address start, Address end) { + if ((MAX_ALIGNMENT - MIN_ALIGNMENT) == BYTES_IN_INT) { + // At most a single hole + if (!end.diff(start).isZero()) { + start.store(ALIGNMENT_VALUE); + } + } else { + while (start.LT(end)) { + start.store(ALIGNMENT_VALUE); + start = start.plus(BYTES_IN_INT); + } + } + } + + /** + * Aligns up an allocation request. The allocation request accepts a + * region, that must be at least particle aligned, an alignment + * request (some power of two number of particles) and an offset (a + * number of particles). + * + * @param region The region to align up. + * @param alignment The requested alignment + * @param offset The offset from the alignment + * @return The aligned up address. + */ + @Inline + public static Address alignAllocation(Address region, int alignment, int offset) { + return alignAllocation(region, alignment, offset, MIN_ALIGNMENT, true); + } + + /** + * Aligns up an allocation request. The allocation request accepts a + * region, that must be at least particle aligned, an alignment + * request (some power of two number of particles) and an offset (a + * number of particles). + * + * @param region The region to align up. + * @param alignment The requested alignment + * @param offset The offset from the alignment + * @return The aligned up address. + */ + @Inline + public static Address alignAllocationNoFill(Address region, int alignment, int offset) { + return alignAllocation(region, alignment, offset, MIN_ALIGNMENT, false); + } + + /** + * This method calculates the minimum size that will guarantee the allocation + * of a specified number of bytes at the specified alignment. + * + * @param size The number of bytes (not aligned). + * @param alignment The requested alignment (some factor of 2). + */ + @Inline + public static int getMaximumAlignedSize(int size, int alignment) { + return getMaximumAlignedSize(size, alignment, MIN_ALIGNMENT); + } + + /** + * This method calculates the minimum size that will guarantee the allocation + * of a specified number of bytes at the specified alignment. + * + * @param size The number of bytes (not aligned). + * @param alignment The requested alignment (some factor of 2). + * @param knownAlignment The known minimum alignment. Specifically for use in + * allocators that enforce greater than particle alignment. It is a precondition + * that size is aligned to knownAlignment, and that knownAlignment >= MIN_ALGINMENT. + */ + @Inline + public static int getMaximumAlignedSize(int size, int alignment, int knownAlignment) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(size == Conversions.roundDown(size, knownAlignment)); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(knownAlignment >= MIN_ALIGNMENT); + + if (MAX_ALIGNMENT <= MIN_ALIGNMENT || alignment <= knownAlignment) { + return size; + } else { + return size + alignment - knownAlignment; + } + } + + /** + * Single slow path allocation attempt. This is called by allocSlow. + * + * @param bytes The size of the allocation request + * @param alignment The required alignment + * @param offset The alignment offset + * @return The start address of the region, or zero if allocation fails + */ + protected abstract Address allocSlowOnce(int bytes, int alignment, int offset); + + /** + * Out-of-line slow path allocation. This method forces slow path + * allocation to be out of line (typically desirable, but not when the + * calling context is already explicitly out-of-line). + * + * @param bytes The size of the allocation request + * @param alignment The required alignment + * @param offset The alignment offset + * @return The start address of the region, or zero if allocation fails + */ + @NoInline + public final Address allocSlow(int bytes, int alignment, int offset) { + return allocSlowInline(bytes, alignment, offset); + } + + /** + * Inline slow path allocation. This method attempts allocSlowOnce + * several times, and allows collection to occur, and ensures that execution + * safely resumes by taking care of potential thread/mutator context affinity + * changes. All allocators should use this as the trampoline for slow + * path allocation. + * + * @param bytes The size of the allocation request + * @param alignment The required alignment + * @param offset The alignment offset + * @return The start address of the region, or zero if allocation fails + */ + @Inline + public final Address allocSlowInline(int bytes, int alignment, int offset) { + int gcCountStart = Stats.gcCount(); + Allocator current = this; + Space space = current.getSpace(); + for (int i = 0; i < Plan.MAX_COLLECTION_ATTEMPTS; i++) { + Address result = current.allocSlowOnce(bytes, alignment, offset); + if (!result.isZero()) { + return result; + } + if (!Plan.gcInProgress()) { + /* This is in case a GC occurs, and our mutator context is stale. + * In some VMs the scheduler can change the affinity between the + * current thread and the mutator context. This is possible for + * VMs that dynamically multiplex Java threads onto multiple mutator + * contexts, */ + current = VM.activePlan.mutator().getAllocatorFromSpace(space); + } + } + Log.write("GC Error: Allocator.allocSlow failed on request of "); + Log.write(bytes); + Log.write(" on space "); + Log.writeln(space.getName()); + Log.write("gcCountStart = "); + Log.writeln(gcCountStart); + Log.write("gcCount (now) = "); + Log.writeln(Stats.gcCount()); + Space.printUsageMB(); + VM.assertions.fail("Allocation Failed!"); + /* NOTREACHED */ + return Address.zero(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,335 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.policy.Space; +import org.mmtk.utility.*; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements "block" data structures of various sizes.

+ * + * Blocks are a non-shared (thread-local) coarse-grained unit of + * storage. Blocks are available in power-of-two sizes. + * + * Virtual memory space is taken from a VM resource, and pages + * consumed by blocks are accounted for by a memory resource. + */ + at Uninterruptible +public final class BlockAllocator implements Constants { + /**************************************************************************** + * + * Class variables + */ + + // block freelist + public static final int LOG_MIN_BLOCK = 12; // 4K bytes + public static final int LOG_MAX_BLOCK = 15; // 32K bytes + public static final byte MAX_BLOCK_SIZE_CLASS = LOG_MAX_BLOCK - LOG_MIN_BLOCK; + public static final int BLOCK_SIZE_CLASSES = MAX_BLOCK_SIZE_CLASS + 1; + + // metadata + private static final Offset NEXT_OFFSET = Offset.zero(); + private static final Offset BMD_OFFSET = NEXT_OFFSET.plus(BYTES_IN_ADDRESS); + private static final Offset CSC_OFFSET = BMD_OFFSET.plus(1); + private static final Offset IU_OFFSET = CSC_OFFSET.plus(1); + private static final Offset FL_META_OFFSET = IU_OFFSET.plus(BYTES_IN_SHORT); + private static final byte BLOCK_SC_MASK = 0xf; // lower 4 bits + private static final int BLOCK_PAGE_OFFSET_SHIFT = 4; // higher 4 bits + private static final int MAX_BLOCK_PAGE_OFFSET = (1<<4)-1; // 4 bits + private static final int LOG_BYTES_IN_BLOCK_META = LOG_BYTES_IN_ADDRESS + 2; + private static final int LOG_BYTE_COVERAGE = LOG_MIN_BLOCK - LOG_BYTES_IN_BLOCK_META; + + public static final int META_DATA_BYTES_PER_REGION = 1 << (EmbeddedMetaData.LOG_BYTES_IN_REGION - LOG_BYTE_COVERAGE); + public static final Extent META_DATA_EXTENT = Extent.fromIntSignExtend(META_DATA_BYTES_PER_REGION); + + /**************************************************************************** + * + * Allocation & freeing + */ + + /** + * Allocate a block, returning the address of the first usable byte + * in the block. + * + * @param blockSizeClass The size class for the block to be allocated. + * @return The address of the first usable byte in the block, or + * zero on failure. + */ + public static Address alloc(Space space, int blockSizeClass) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((blockSizeClass >= 0) && (blockSizeClass <= MAX_BLOCK_SIZE_CLASS)); + int pages = pagesForSizeClass(blockSizeClass); + Address result = space.acquire(pages); + if (!result.isZero()) { + setBlkSizeMetaData(result, (byte) blockSizeClass); + } + return result; + } + + /** + * Free a block. If the block is a sub-page block and the page is + * not completely free, then the block is added to the free list. + * Otherwise the block is returned to the virtual memory resource. + * + * @param block The address of the block to be freed + */ + public static void free(Space space, Address block) { + space.release(block); + } + + /** + * Return the size in bytes of a block of a given size class + * + * @param blockSizeClass The size class in question + * @return The size in bytes of a block of this size class + */ + @Inline + public static int blockSize(int blockSizeClass) { + return 1 << (LOG_MIN_BLOCK + blockSizeClass); + } + + /** + * Return the number of pages required when allocating space for + * this size class. + * + * @param blockSizeClass The size class in question + * @return The number of pages required when allocating a block (or + * blocks) of this size class. + */ + @Inline + private static int pagesForSizeClass(int blockSizeClass) { + return 1 << (LOG_MIN_BLOCK + blockSizeClass - LOG_BYTES_IN_PAGE); + } + + /**************************************************************************** + * + * Block meta-data manipulation + */ + + /** + * Set the block size class meta data field for a given + * address (all blocks on a given page are homogeneous with respect + * to block size class). + * + * @param block The address of interest + * @param sc The value to which this field is to be set + */ + @Inline + private static void setBlkSizeMetaData(Address block, byte sc) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(block.EQ(Conversions.pageAlign(block))); + VM.assertions._assert(pagesForSizeClass(sc) - 1 <= MAX_BLOCK_PAGE_OFFSET); + } + Address address = block; + for (int i = 0; i < pagesForSizeClass(sc); i++) { + byte value = (byte) ((i << BLOCK_PAGE_OFFSET_SHIFT) | sc); + getMetaAddress(address).store(value, BMD_OFFSET); + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(getBlkStart(address).EQ(block)); + VM.assertions._assert(getBlkSizeClass(address) == sc); + } + address = address.plus(1<block size class meta data field for a given page + * (all blocks on a given page are homogeneous with respect to block + * size class). + * + * @param address The address of interest + * @return The size class field for the block containing the given address + */ + @Inline + private static byte getBlkSizeClass(Address address) { + address = Conversions.pageAlign(address); + byte rtn = (byte) (getMetaAddress(address).loadByte(BMD_OFFSET) & BLOCK_SC_MASK); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn >= 0 && rtn <= MAX_BLOCK_SIZE_CLASS); + return rtn; + } + + /** + * Get the address of the start of a block size class a given page + * within the block. + * + * @param address The address of interest + * @return The address of the block containing the address + */ + @Inline + public static Address getBlkStart(Address address) { + address = Conversions.pageAlign(address); + byte offset = (byte) (getMetaAddress(address).loadByte(BMD_OFFSET) >>> BLOCK_PAGE_OFFSET_SHIFT); + return address.minus(offset<client size class meta data field for a given + * address (all blocks on a given page are homogeneous with respect + * to block size class). + * + * @param block The address of interest + * @param sc The value to which this field is to be set + */ + @Inline + public static void setAllClientSizeClass(Address block, int blocksc, byte sc) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(block.EQ(Conversions.pageAlign(block))); + Address address = block; + for (int i = 0; i < pagesForSizeClass(blocksc); i++) { + getMetaAddress(address).store(sc, CSC_OFFSET); + address = address.plus(1<client size class meta data field for a given page + * (all blocks on a given page are homogeneous with respect to block + * size class). + * + * @param address The address of interest + * @return The size class field for the block containing the given address + */ + @Inline + public static byte getClientSizeClass(Address address) { + address = Conversions.pageAlign(address); + byte rtn = getMetaAddress(address).loadByte(CSC_OFFSET); + return rtn; + } + + /** + * Set the free list meta data field for a given address (this is + * per-block meta data that is stored along with the block metadata + * but not used by the block allocator). + * + * @param address The address of interest + * @param value The value to which this field is to be set + */ + @Inline + public static void setFreeListMeta(Address address, Address value) { + getMetaAddress(address).plus(FL_META_OFFSET).store(value); + } + + /** + * Get the free list meta data field for a given address (this is + * per-block meta data that is stored along with the block metadata + * but not used by the block allocator). + * + * @param address The address of interest + * @return The free list meta data field for the block containing + * the given address + */ + @Inline + public static Address getFreeListMeta(Address address) { + return getMetaAddress(address).plus(FL_META_OFFSET).loadAddress(); + } + + /** + * Set the prev meta data field for a given address + * + * @param address The address of interest + * @param prev The value to which this field is to be set + */ + @Inline + public static void setNext(Address address, Address prev) { + getMetaAddress(address, NEXT_OFFSET).store(prev); + } + + /** + * Get the prev meta data field for a given address + * + * @param address The address of interest + * @return The prev field for the block containing the given address + */ + @Inline + public static Address getNext(Address address) { + return getMetaAddress(address, NEXT_OFFSET).loadAddress(); + } + + /** + * Get the address of some metadata given the address for which the + * metadata is required and the offset into the metadata that is of + * interest. + * + * @param address The address for which the metadata is required + * @return The address of the specified meta data + */ + @Inline + private static Address getMetaAddress(Address address) { + return getMetaAddress(address, Offset.zero()); + } + + /** + * Get the address of some metadata given the address for which the + * metadata is required and the offset into the metadata that is of + * interest. + * + * @param address The address for which the metadata is required + * @param offset The offset (in bytes) into the metadata block (eg + * for the prev pointer, or next pointer) + * @return The address of the specified meta data + */ + @Inline + private static Address getMetaAddress(Address address, Offset offset) { + return EmbeddedMetaData.getMetaDataBase(address).plus( + EmbeddedMetaData.getMetaDataOffset(address, LOG_BYTE_COVERAGE, LOG_BYTES_IN_BLOCK_META)).plus(offset); + } + + /**************************************************************************** + * + * Block marking + */ + + /** + * Mark the metadata for this block. + * + * @param ref + */ + @Inline + public static void markBlockMeta(ObjectReference ref) { + getMetaAddress(VM.objectModel.refToAddress(ref)).plus(FL_META_OFFSET).store(Word.one()); + } + + /** + * Mark the metadata for this block. + * + * @param block The block address + */ + @Inline + public static void markBlockMeta(Address block) { + getMetaAddress(block).plus(FL_META_OFFSET).store(Word.one()); + } + + /** + * Return true if the metadata for this block was set. + * + * @param block The block address + * @return value of the meta data. + */ + @Inline + public static boolean checkBlockMeta(Address block) { + return getMetaAddress(block).plus(FL_META_OFFSET).loadWord().EQ(Word.one()); + } + + /** + * Clear the metadata for this block + * + * @param block The block address + */ + @Inline + public static void clearBlockMeta(Address block) { + getMetaAddress(block).plus(FL_META_OFFSET).store(Word.zero()); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,459 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.policy.Space; +import org.mmtk.utility.*; +import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class implements a bump pointer allocator that allows linearly + * scanning through the allocated objects. In order to achieve this in the + * face of parallelism it maintains a header at a region (1 or more blocks) + * granularity. + * + * Intra-block allocation is fast, requiring only a load, addition comparison + * and store. If a block boundary is encountered the allocator will + * request more memory (virtual and actual). + * + * In the current implementation the scanned objects maintain affinity + * with the thread that allocated the objects in the region. In the future + * it is anticipated that subclasses should be allowed to choose to improve + * load balancing during the parallel scan. + * + * Each region is laid out as follows: + * + * +-------------+-------------+-------------+--------------- + * | Region End | Next Region | Data End | Data --> + * +-------------+-------------+-------------+--------------- + * + * The minimum region size is 32768 bytes, so the 3 or 4 word overhead is + * less than 0.05% of all space. + * + * An intended enhancement is to facilitate a reallocation operation + * where a second cursor is maintained over earlier regions (and at the + * limit a lower location in the same region). This would be accompianied + * with an alternative slow path that would allow reuse of empty regions. + * + * This class relies on the supporting virtual machine implementing the + * getNextObject and related operations. + */ + at Uninterruptible public class BumpPointer extends Allocator + implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + // Block size defines slow path periodicity. + private static final int LOG_DEFAULT_STEP_SIZE = 30; // 1G: let the external slow path dominate + private static final int STEP_SIZE = 1<<(SUPPORT_CARD_SCANNING ? LOG_CARD_BYTES : LOG_DEFAULT_STEP_SIZE); + protected static final int LOG_BLOCK_SIZE = LOG_BYTES_IN_PAGE + 3; + protected static final Word BLOCK_MASK = Word.one().lsh(LOG_BLOCK_SIZE).minus(Word.one()); + + // Offsets into header + protected static final Offset REGION_LIMIT_OFFSET = Offset.zero(); + protected static final Offset NEXT_REGION_OFFSET = REGION_LIMIT_OFFSET.plus(BYTES_IN_ADDRESS); + protected static final Offset DATA_END_OFFSET = NEXT_REGION_OFFSET.plus(BYTES_IN_ADDRESS); + + // Data must start particle-aligned. + protected static final Offset DATA_START_OFFSET = alignAllocationNoFill( + Address.zero().plus(DATA_END_OFFSET.plus(BYTES_IN_ADDRESS)), + MIN_ALIGNMENT, 0).toWord().toOffset(); + protected static final Offset MAX_DATA_START_OFFSET = alignAllocationNoFill( + Address.zero().plus(DATA_END_OFFSET.plus(BYTES_IN_ADDRESS)), + MAX_ALIGNMENT, 0).toWord().toOffset(); + + /**************************************************************************** + * + * Instance variables + */ + protected Address cursor; // insertion point + private Address internalLimit; // current internal slow-path sentinal for bump pointer + private Address limit; // current external slow-path sentinal for bump pointer + protected Space space; // space this bump pointer is associated with + protected Address initialRegion; // first contiguous region + protected final boolean allowScanning; // linear scanning is permitted if true + protected Address region; // current contiguous region + + + /** + * Constructor. + * + * @param space The space to bump point into. + * @param allowScanning Allow linear scanning of this region of memory. + */ + protected BumpPointer(Space space, boolean allowScanning) { + this.space = space; + this.allowScanning = allowScanning; + reset(); + } + + /** + * Reset the allocator. Note that this does not reset the space. + * This is must be done by the caller. + */ + public final void reset() { + cursor = Address.zero(); + limit = Address.zero(); + internalLimit = Address.zero(); + initialRegion = Address.zero(); + region = Address.zero(); + } + + /** + * Re-associate this bump pointer with a different space. Also + * reset the bump pointer so that it will use the new space + * on the next call to alloc. + * + * @param space The space to associate the bump pointer with. + */ + public final void rebind(Space space) { + reset(); + this.space = space; + } + + /** + * Allocate space for a new object. This is frequently executed code and + * the coding is deliberaetly sensitive to the optimizing compiler. + * After changing this, always check the IR/MC that is generated. + * + * @param bytes The number of bytes allocated + * @param align The requested alignment + * @param offset The offset from the alignment + * @return The address of the first byte of the allocated region + */ + @Inline + public final Address alloc(int bytes, int align, int offset) { + Address start = alignAllocationNoFill(cursor, align, offset); + Address end = start.plus(bytes); + if (end.GT(internalLimit)) + return allocSlow(start, end, align, offset); + fillAlignmentGap(cursor, start); + cursor = end; + return start; + } + + /** + * Internal allocation slow path. This is called whenever the bump + * pointer reaches the internal limit. The code is forced out of + * line. If required we perform an external slow path take, which + * we inline into this method since this is already out of line. + * + * @param start The start address for the pending allocation + * @param end The end address for the pending allocation + * @param align The requested alignment + * @param offset The offset from the alignment + * @return The address of the first byte of the allocated region + */ + @NoInline + private Address allocSlow(Address start, Address end, int align, + int offset) { + Address rtn = null; + Address card = null; + if (SUPPORT_CARD_SCANNING) + card = getCard(start.plus(CARD_MASK)); // round up + if (end.GT(limit)) { /* external slow path */ + rtn = allocSlowInline(end.diff(start).toInt(), align, offset); + if (SUPPORT_CARD_SCANNING && card.NE(getCard(rtn.plus(CARD_MASK)))) + card = getCard(rtn); // round down + } else { /* internal slow path */ + while (internalLimit.LE(end)) + internalLimit = internalLimit.plus(STEP_SIZE); + if (internalLimit.GT(limit)) + internalLimit = limit; + fillAlignmentGap(cursor, start); + cursor = end; + rtn = start; + } + if (SUPPORT_CARD_SCANNING && !rtn.isZero()) + createCardAnchor(card, rtn, end.diff(start).toInt()); + return rtn; + } + + /** + * Given an allocation which starts a new card, create a record of + * where the start of the object is relative to the start of the + * card. + * + * @param card An address that lies within the card to be marked + * @param start The address of an object which creates a new card. + * @param bytes The size of the pending allocation in bytes (used for debugging) + */ + private void createCardAnchor(Address card, Address start, int bytes) { + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(allowScanning); + VM.assertions._assert(card.EQ(getCard(card))); + VM.assertions._assert(start.diff(card).sLE(MAX_DATA_START_OFFSET)); + VM.assertions._assert(start.diff(card).toInt() >= -CARD_MASK); + } + while (bytes > 0) { + int offset = start.diff(card).toInt(); + getCardMetaData(card).store(offset); + card = card.plus(1 << LOG_CARD_BYTES); + bytes -= (1 << LOG_CARD_BYTES); + } + } + + /** + * Return the start of the card corresponding to a given address. + * + * @param address The address for which the card start is required + * @return The start of the card containing the address + */ + private static Address getCard(Address address) { + return address.toWord().and(Word.fromIntSignExtend(CARD_MASK).not()).toAddress(); + } + + /** + * Return the address of the metadata for a card, given the address of the card. + * @param card The address of some card + * @return The address of the metadata associated with that card + */ + private static Address getCardMetaData(Address card) { + Address metadata = EmbeddedMetaData.getMetaDataBase(card); + return metadata.plus(EmbeddedMetaData.getMetaDataOffset(card, LOG_CARD_BYTES-LOG_CARD_META_SIZE, LOG_CARD_META_SIZE)); + } + + /** + * External allocation slow path (called by superclass when slow path is + * actually taken. This is necessary (rather than a direct call + * from the fast path) because of the possibility of a thread switch + * and corresponding re-association of bump pointers to kernel + * threads. + * + * @param bytes The number of bytes allocated + * @param offset The offset from the alignment + * @param align The requested alignment + * @return The address of the first byte of the allocated region or + * zero on failure + */ + protected final Address allocSlowOnce(int bytes, int align, int offset) { + /* Check we have been bound to a space */ + if (space == null) { + VM.assertions.fail("Allocation on unbound bump pointer."); + } + + /* Check if we already have a block to use */ + if (allowScanning && !region.isZero()) { + Address nextRegion = region.loadAddress(NEXT_REGION_OFFSET); + if (!nextRegion.isZero()) { + return consumeNextRegion(nextRegion, bytes, align, offset); + } + } + + /* Acquire space, block aligned, that can accommodate the request */ + Extent blockSize = Word.fromIntZeroExtend(bytes).plus(BLOCK_MASK) + .and(BLOCK_MASK.not()).toExtent(); + Address start = space.acquire(Conversions.bytesToPages(blockSize)); + + if (start.isZero()) return start; // failed allocation + + if (!allowScanning) { // simple allocator + if (start.NE(limit)) cursor = start; // discontiguous + updateLimit(start.plus(blockSize), start, bytes); + } else // scannable allocator + updateMetaData(start, blockSize, bytes); + return alloc(bytes, align, offset); + } + + /** + * Update the limit pointer. As a side effect update the internal limit + * pointer appropriately. + * + * @param newLimit The new value for the limit pointer + * @param start The start of the region to be allocated into + * @param bytes The size of the pending allocation (if any). + */ + @Inline + protected final void updateLimit(Address newLimit, Address start, int bytes) { + limit = newLimit; + internalLimit = start.plus(STEP_SIZE); + if (internalLimit.GT(limit)) + internalLimit = limit; + else { + while (internalLimit.LT(cursor.plus(bytes))) + internalLimit = internalLimit.plus(STEP_SIZE); + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(internalLimit.LE(limit)); + } + } + + /** + * A bump pointer chuck/region has been consumed but the contiguous region + * is available, so consume it and then return the address of the start + * of a memory region satisfying the outstanding allocation request. This + * is relevant when re-using memory, as in a mark-compact collector. + * + * @param nextRegion The region to be consumed + * @param bytes The number of bytes allocated + * @param align The requested alignment + * @param offset The offset from the alignment + * @return The address of the first byte of the allocated region or + * zero on failure + */ + private Address consumeNextRegion(Address nextRegion, int bytes, int align, + int offset) { + region.plus(DATA_END_OFFSET).store(cursor); + region = nextRegion; + cursor = nextRegion.plus(DATA_START_OFFSET); + updateLimit(nextRegion.loadAddress(REGION_LIMIT_OFFSET), nextRegion, bytes); + nextRegion.store(Address.zero(), DATA_END_OFFSET); + VM.memory.zero(cursor, limit.diff(cursor).toWord().toExtent()); + reusePages(Conversions.bytesToPages(limit.diff(region))); + + return alloc(bytes, align, offset); + } + + /** + * Update the metadata to reflect the addition of a new region. + * + * @param start The start of the new region + * @param size The size of the new region (rounded up to block-alignment) + */ + @Inline + private void updateMetaData(Address start, Extent size, int bytes) { + if (initialRegion.isZero()) { + /* this is the first allocation */ + initialRegion = start; + region = start; + cursor = region.plus(DATA_START_OFFSET); + } else if (limit.NE(start) || + region.diff(start.plus(size)).toWord().toExtent().GT(maximumRegionSize())) { + /* non contiguous or over-size, initialize new region */ + region.plus(NEXT_REGION_OFFSET).store(start); + region.plus(DATA_END_OFFSET).store(cursor); + region = start; + cursor = start.plus(DATA_START_OFFSET); + } + updateLimit(start.plus(size), start, bytes); + region.plus(REGION_LIMIT_OFFSET).store(limit); + } + + /** + * Gather data for GCspy.

+ * This method calls the drivers linear scanner to scan through + * the objects allocated by this bump pointer. + * + * @param driver The GCspy driver for this space. + */ + public void gcspyGatherData(LinearSpaceDriver driver) { + //driver.setRange(space.getStart(), cursor); + driver.setRange(space.getStart(), limit); + this.linearScan(driver.getScanner()); + } + + /** + * Gather data for GCspy.

+ * This method calls the drivers linear scanner to scan through + * the objects allocated by this bump pointer. + * + * @param driver The GCspy driver for this space. + * @param scanSpace The space to scan + */ + public void gcspyGatherData(LinearSpaceDriver driver, Space scanSpace) { + //TODO can scanSpace ever be different to this.space? + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(scanSpace == space, "scanSpace != space"); + + //driver.setRange(scanSpace.getStart(), cursor); + Address start = scanSpace.getStart(); + driver.setRange(start, limit); + + if (false) { + Log.write("\nBumpPointer.gcspyGatherData set Range "); Log.write(scanSpace.getStart()); + Log.write(" to "); Log.writeln(limit); + Log.write("BumpPointergcspyGatherData scan from "); Log.writeln(initialRegion); + } + + linearScan(driver.getScanner()); + } + + + /** + * Perform a linear scan through the objects allocated by this bump pointer. + * + * @param scanner The scan object to delegate scanning to. + */ + @Inline + public final void linearScan(LinearScan scanner) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allowScanning); + /* Has this allocator ever allocated anything? */ + if (initialRegion.isZero()) return; + + /* Loop through active regions or until the last region */ + Address start = initialRegion; + while (!start.isZero()) { + scanRegion(scanner, start); // Scan this region + start = start.plus(NEXT_REGION_OFFSET).loadAddress(); // Move on to next + } + } + + /** + * Perform a linear scan through a single contiguous region + * + * @param scanner The scan object to delegate to. + * @param start The start of this region + */ + @Inline + private void scanRegion(LinearScan scanner, Address start) { + /* Get the end of this region */ + Address dataEnd = start.plus(DATA_END_OFFSET).loadAddress(); + + /* dataEnd = zero represents the current region. */ + Address currentLimit = (dataEnd.isZero() ? cursor : dataEnd); + ObjectReference current = + VM.objectModel.getObjectFromStartAddress(start.plus(DATA_START_OFFSET)); + + while (VM.objectModel.refToAddress(current).LT(currentLimit) && !current.isNull()) { + ObjectReference next = VM.objectModel.getNextObject(current); + scanner.scan(current); // Scan this object. + current = next; + } + } + + /** + * Some pages are about to be re-used to satisfy a slow path request. + * @param pages The number of pages. + */ + protected void reusePages(int pages) { + VM.assertions.fail("Subclasses that reuse regions must override this method."); + } + + /** + * Maximum size of a single region. Important for children that implement + * load balancing or increments based on region size. + * @return the maximum region size + */ + protected Extent maximumRegionSize() { return Extent.max(); } + + /** @return the current cursor value */ + public final Address getCursor() { return cursor; } + /** @return the space associated with this bump pointer */ + public final Space getSpace() { return space; } + + /** + * Print out the status of the allocator (for debugging) + */ + public final void show() { + Log.write("cursor = "); Log.write(cursor); + if (allowScanning) { + Log.write(" region = "); Log.write(region); + } + Log.write(" limit = "); Log.writeln(limit); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,38 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.vm.VM; +import org.mmtk.utility.Log; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Simple linear scan to dump object information. + */ + at Uninterruptible +public final class DumpLinearScan extends LinearScan { + /** + * Scan an object. + * + * @param object The object to scan + */ + @Inline + public void scan(ObjectReference object) { + Log.write("["); + Log.write(object.toAddress()); + Log.write("], SIZE = "); + Log.writeln(VM.objectModel.getCurrentSize(object)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,74 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.utility.Constants; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This plan implements constants and access methods for meta data + * that is embeded in allocation spaces (rather than kept on the + * side). The basic idea is that meta data be embeded at a very + * coarse power of two granularity for fast access, minimal wastage + * and by making the regions coarse, the contiguous meta-data will be + * relatively large and thus the probability of L1 conflict misses + * will be reduced (as compared with embedding meta-data at the start + * of each page which will cause those few cache lines corresponding + * to the start of each page to be heavily conflicted). + */ + at Uninterruptible public final class EmbeddedMetaData implements Constants { + + /* The (log of the) size of each region of meta data management */ + public static final int LOG_BYTES_IN_REGION = 22; + public static final int BYTES_IN_REGION = 1 << LOG_BYTES_IN_REGION; + private static final Word REGION_MASK = Word.fromIntSignExtend(BYTES_IN_REGION - 1); + public static final int LOG_PAGES_IN_REGION = LOG_BYTES_IN_REGION - LOG_BYTES_IN_PAGE; + public static final int PAGES_IN_REGION = 1 << LOG_PAGES_IN_REGION; + + /** + * Given an address, return the begining of the meta data for the + * region containing the address. This is a fast operation because + * it only involves masking out low order bits. + * + * @param address The address whose meta data is sought. + * @return The address of the start of the meta data for the meta + * region in which the address is located. + */ + @Inline + public static Address getMetaDataBase(Address address) { + return address.toWord().and(REGION_MASK.not()).toAddress(); + } + + /** + * Given an address, the density (coverage) of a meta data type, and + * the granularity (alignment) of the meta data, return the offset + * into the meta data the address. + * + * @param address The address whose meta data offset is sought. + * @param logCoverage The log base two of the coverage of the meta + * data in question. For example, a value of 4 would indicate a + * coverage of 16; one metadata byte for every 16 bytes of data. + * @param logAlign The log base two of the aligment or granularity + * of the meta-data (it may be arranged in bytes, words, double + * words etc). + * @return The offset into the meta-data for this region, given the + * specified address and coverage and aligment requirements. + */ + public static Extent getMetaDataOffset(Address address, + int logCoverage, + int logAlign) { + return address.toWord().and(REGION_MASK).rshl(logCoverage+logAlign).lsh(logAlign).toExtent(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,331 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ + +package org.mmtk.utility.alloc; + +import org.mmtk.policy.Space; +import org.mmtk.policy.immix.Block; +import org.mmtk.policy.immix.Chunk; +import org.mmtk.policy.immix.Line; +import org.mmtk.policy.immix.ImmixSpace; +import static org.mmtk.policy.immix.ImmixConstants.*; + +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * + */ + at Uninterruptible +public class ImmixAllocator extends Allocator implements Constants { + + /**************************************************************************** + * + * Instance variables + */ + protected final ImmixSpace space; /* space this allocator is associated with */ + private final boolean hot; + private final boolean copy; + + private Address cursor; /* bump pointer */ + private Address limit; /* limit for bump pointer */ + private Address largeCursor; /* bump pointer for large objects */ + private Address largeLimit; /* limit for bump pointer for large objects */ + private boolean requestForLarge; /* is the current request for large or small? */ + private boolean straddle; /* did the last allocation straddle a line? */ + private int lineUseCount; /* approximation to bytes allocated (measured at 99% accurate) 07/10/30 */ + private Address markTable; + private Address recyclableBlock; + private int line; + private boolean recyclableExhausted; + + /** + * Constructor. + * + * @param space The space to bump point into. + * @param hot TODO + * @param copy TODO + */ + public ImmixAllocator(ImmixSpace space, boolean hot, boolean copy) { + this.space = space; + this.hot = hot; + this.copy = copy; + reset(); + } + + /** + * Reset the allocator. Note that this does not reset the space. + */ + public void reset() { + cursor = Address.zero(); + limit = Address.zero(); + largeCursor = Address.zero(); + largeLimit = Address.zero(); + markTable = Address.zero(); + recyclableBlock = Address.zero(); + requestForLarge = false; + recyclableExhausted = false; + line = LINES_IN_BLOCK; + lineUseCount = 0; + } + + /***************************************************************************** + * + * Public interface + */ + + /** + * Allocate space for a new object. This is frequently executed code and + * the coding is deliberaetly sensitive to the optimizing compiler. + * After changing this, always check the IR/MC that is generated. + * + * @param bytes The number of bytes allocated + * @param align The requested alignment + * @param offset The offset from the alignment + * @return The address of the first byte of the allocated region + */ + @Inline + public final Address alloc(int bytes, int align, int offset) { + /* establish how much we need */ + Address start = alignAllocationNoFill(cursor, align, offset); + Address end = start.plus(bytes); + + /* check whether we've exceeded the limit */ + if (end.GT(limit)) { + if (bytes > BYTES_IN_LINE) + return overflowAlloc(bytes, align, offset); + else + return allocSlowHot(bytes, align, offset); + } + + /* sufficient memory is available, so we can finish performing the allocation */ + fillAlignmentGap(cursor, start); + cursor = end; + + return start; + } + + /** + * Allocate space for a new object. This is frequently executed code and + * the coding is deliberaetly sensitive to the optimizing compiler. + * After changing this, always check the IR/MC that is generated. + * + * @param bytes The number of bytes allocated + * @param align The requested alignment + * @param offset The offset from the alignment + * @return The address of the first byte of the allocated region + */ + public final Address overflowAlloc(int bytes, int align, int offset) { + /* establish how much we need */ + Address start = alignAllocationNoFill(largeCursor, align, offset); + Address end = start.plus(bytes); + + /* check whether we've exceeded the limit */ + if (end.GT(largeLimit)) { + requestForLarge = true; + Address rtn = allocSlowInline(bytes, align, offset); + requestForLarge = false; + return rtn; + } + + /* sufficient memory is available, so we can finish performing the allocation */ + fillAlignmentGap(largeCursor, start); + largeCursor = end; + + return start; + } + + @Inline + public final boolean getLastAllocLineStraddle() { + return straddle; + } + + /** + * External allocation slow path (called by superclass when slow path is + * actually taken. This is necessary (rather than a direct call + * from the fast path) because of the possibility of a thread switch + * and corresponding re-association of bump pointers to kernel + * threads. + * + * @param bytes The number of bytes allocated + * @param align The requested alignment + * @param offset The offset from the alignment + * @return The address of the first byte of the allocated region or + * zero on failure + */ + protected final Address allocSlowOnce(int bytes, int align, int offset) { + boolean success = false; + while (!success) { + Address ptr = space.getSpace(hot, copy, lineUseCount); + + if (ptr.isZero()) { + lineUseCount = 0; + return ptr; // failed allocation --- we will need to GC + } + + /* we have been given a clean block */ + success = true; + lineUseCount = LINES_IN_BLOCK; + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(Block.isAligned(ptr)); + zeroBlock(ptr); + if (requestForLarge) { + largeCursor = ptr; + largeLimit = ptr.plus(BYTES_IN_BLOCK); + } else { + cursor = ptr; + limit = ptr.plus(BYTES_IN_BLOCK); + } + } + return alloc(bytes, align, offset); + } + + /**************************************************************************** + * + * Bump allocation + */ + + /** + * Internal allocation slow path. This is called whenever the bump + * pointer reaches the internal limit. The code is forced out of + * line. If required we perform an external slow path take, which + * we inline into this method since this is already out of line. + * + * @param bytes The number of bytes allocated + * @param align The requested alignment + * @param offset The offset from the alignment + * @return The address of the first byte of the allocated region + */ + @NoInline + private Address allocSlowHot(int bytes, int align, int offset) { + if (acquireRecyclableLines(bytes, align, offset)) + return alloc(bytes, align, offset); + else + return allocSlowInline(bytes, align, offset); + } + + private boolean acquireRecyclableLines(int bytes, int align, int offset) { + while (line < LINES_IN_BLOCK || acquireRecyclableBlock()) { + line = space.getNextAvailableLine(markTable, line); + if (line < LINES_IN_BLOCK) { + int endLine = space.getNextUnavailableLine(markTable, line); + cursor = recyclableBlock.plus(Extent.fromIntSignExtend(line<= 9) { + Log.write("Z["); Log.write(cursor); Log.write("->"); Log.write(limit); Log.writeln("]"); + } + + line = endLine; + if (VM.VERIFY_ASSERTIONS && copy) VM.assertions._assert(!Block.isDefragSource(cursor)); + return true; + } + } + return false; + } + + private boolean acquireRecyclableBlock() { + boolean rtn; + rtn = acquireRecyclableBlockAddressOrder(); + if (rtn) { + markTable = Line.getBlockMarkTable(recyclableBlock); + line = 0; + } + return rtn; + } + + @Inline + private boolean acquireRecyclableBlockAddressOrder() { + if (recyclableExhausted) { + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.writeln("[no recyclable available]"); + } + return false; + } + int markState = 0; + boolean usable = false; + while (!usable) { + Address next = recyclableBlock.plus(BYTES_IN_BLOCK); + if (recyclableBlock.isZero() || ImmixSpace.isRecycleAllocChunkAligned(next)) { + recyclableBlock = space.acquireReusableBlocks(); + if (recyclableBlock.isZero()) { + recyclableExhausted = true; + if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) { + Log.writeln("[recyclable exhausted]"); + } + line = LINES_IN_BLOCK; + return false; + } + } else { + recyclableBlock = next; + } + markState = Block.getBlockMarkState(recyclableBlock); + usable = (markState > 0 && markState <= ImmixSpace.getReusuableMarkStateThreshold(copy)); + if (copy && Block.isDefragSource(recyclableBlock)) + usable = false; + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(recyclableBlock)); + Block.setBlockAsReused(recyclableBlock); + + lineUseCount += (LINES_IN_BLOCK-markState); + return true; // found something good + } + + private void zeroBlock(Address block) { + // FIXME: efficiency check here! + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(block.toWord().and(Word.fromIntSignExtend(BYTES_IN_BLOCK-1)).isZero()); + VM.memory.zero(block, Extent.fromIntZeroExtend(BYTES_IN_BLOCK)); + } + + /** @return the space associated with this squish allocator */ + public final Space getSpace() { return space; } + + /** + * Print out the status of the allocator (for debugging) + */ + public final void show() { + Log.write("cursor = "); Log.write(cursor); + Log.write(" limit = "); Log.writeln(limit); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,113 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.policy.BaseLargeObjectSpace; +import org.mmtk.utility.Constants; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This abstract class implements core functionality for a generic + * large object allocator. The shared VMResource used by each instance + * is the point of global synchronization, and synchronization only + * occurs at the granularity of aquiring (and releasing) chunks of + * memory from the VMResource. Subclasses may require finer grained + * synchronization during a marking phase, for example.

+ * + * This is a first cut implementation, with plenty of room for + * improvement... + */ + at Uninterruptible +public abstract class LargeObjectAllocator extends Allocator implements Constants { + + /**************************************************************************** + * + * Instance variables + */ + protected final BaseLargeObjectSpace space; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param space The space with which this large object allocator + * will be associated. + */ + public LargeObjectAllocator(BaseLargeObjectSpace space) { + this.space = space; + } + + /** + * Return the space this allocator is currently bound to. + * + * @return The Space. + */ + protected final BaseLargeObjectSpace getSpace() { + return this.space; + } + + /**************************************************************************** + * + * Allocation + */ + + /** + * Allocate space for an object + * + * @param bytes The number of bytes allocated + * @param align The requested alignment. + * @param offset The alignment offset. + * @return The address of the first byte of the allocated cell Will + * not return zero. + */ + @NoInline + public final Address alloc(int bytes, int align, int offset) { + Address cell = allocSlow(bytes, align, offset); + return alignAllocation(cell, align, offset); + } + + /** + * Allocate a large object. Large objects are directly allocted and + * freed in page-grained units via the vm resource. This routine + * returned zeroed memory. + * + * @param bytes The required size of this space in bytes. + * @param offset The alignment offset. + * @param align The requested alignment. + * @return The address of the start of the newly allocated region at + * least bytes bytes in size. + */ + protected final Address allocSlowOnce(int bytes, int align, int offset) { + int header = space.getHeaderSize(); + int maxbytes = getMaximumAlignedSize(bytes + header, align); + int pages = (maxbytes + BYTES_IN_PAGE - 1) >> LOG_BYTES_IN_PAGE; + Address sp = space.acquire(pages); + if (sp.isZero()) return sp; + Address cell = sp.plus(header); + return cell; + } + + /**************************************************************************** + * + * Miscellaneous + */ + public void show() { + } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,30 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Callbacks from BumpPointer during a linear scan are dispatched through + * a subclass of this object. + */ + at Uninterruptible +public abstract class LinearScan { + /** + * Scan an object. + * + * @param object The object to scan + */ + public abstract void scan(ObjectReference object); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,119 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.policy.SegregatedFreeListSpace; +import org.mmtk.utility.*; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This abstract class implements the fast past for a segregated free list. + */ + at Uninterruptible +public abstract class SegregatedFreeList extends Allocator implements Constants { + + /**************************************************************************** + * + * Instance variables + */ + + /** The space */ + protected final S space; + + /** The current free lists for the size classes */ + protected final AddressArray freeList; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param space The space with which this allocator will be associated + */ + public SegregatedFreeList(S space) { + this.space = space; + this.freeList = AddressArray.create(sizeClassCount()); + } + + /** + * Return the space this allocator is currently bound to. + * + * @return The Space. + */ + protected final S getSpace() { + return this.space; + } + + /**************************************************************************** + * + * Allocation + */ + + /** + * Allocate bytes contiguous bytes of zeroed memory.

+ * + * This code implements the fast path, and on failure delegates to the slow path. + * + * @param bytes The size of the object to occupy this space, in bytes. + * @param align The requested alignment. + * @param offset The alignment offset. + * @return The address of the first word or zero on failure + */ + @Inline + public final Address alloc(int bytes, int align, int offset) { + int alignedBytes = getMaximumAlignedSize(bytes, align); + int sizeClass = getSizeClass(alignedBytes); + Address cell = freeList.get(sizeClass); + if (!cell.isZero()) { + freeList.set(sizeClass, cell.loadAddress()); + /* Clear the free list link */ + cell.store(Address.zero()); + if (alignedBytes != bytes) { + /* Ensure aligned as requested. */ + cell = alignAllocation(cell, align, offset); + } + return cell; + } + return allocSlow(bytes, align, offset); + } + + /** + * The number of distinct size classes. + * + * NOTE: For optimal performance this call must be implemented in a way + * it can be inlined and optimized within the allocation sequence. + */ + @Inline + private int sizeClassCount() { + return SegregatedFreeListSpace.sizeClassCount(); + } + + /** + * Get the size class for a given number of bytes. + * + * NOTE: For optimal performance this call must be implemented in a way + * it can be inlined and optimized within the allocation sequence. + * + * @param bytes The number of bytes required to accommodate the object + * @return The size class capable of accommodating the allocation request. + */ + @Inline + private int getSizeClass(int bytes) { + return space.getSizeClass(bytes); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,162 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.alloc; + +import org.mmtk.policy.SegregatedFreeListSpace; +import org.mmtk.utility.*; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This abstract class implements a simple segregated free list.

+ * + * See: Wilson, Johnstone, Neely and Boles "Dynamic Storage + * Allocation: A Survey and Critical Review", IWMM 1995, for an + * overview of free list allocation and the various implementation + * strategies, including segregated free lists.

+ * + * We maintain a number of size classes, each size class having a free + * list of available objects of that size (the list may be empty). We + * call the storage elements "cells". Cells reside within chunks of + * memory called "blocks". All cells in a given block are of the same + * size (i.e. blocks are homogeneous with respect to size class). + * Each block maintains its own free list (free cells within that + * block). For each size class a list of blocks is maintained, one of + * which will serve the role of the current free list. When the free + * list on the current block is exhausted, the next block for that + * size class becomes the current block and its free list is used. If + * there are no more blocks the a new block is allocated.

+ */ + at Uninterruptible +public abstract class SegregatedFreeListLocal extends SegregatedFreeList + implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + /**************************************************************************** + * + * Instance variables + */ + protected final AddressArray currentBlock; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param space The space with which this allocator will be associated + */ + public SegregatedFreeListLocal(S space) { + super(space); + this.currentBlock = AddressArray.create(space.sizeClassCount()); + } + + /**************************************************************************** + * + * Allocation + */ + + /** + * Allocate bytes contiguous bytes of non-zeroed + * memory. First check if the fast path works. This is needed + * since this method may be called in the context when the fast + * version was NOT just called. If this fails, it will try finding + * another block with a non-empty free list, or allocating a new + * block.

+ * + * This code should be relatively infrequently executed, so it is + * forced out of line to reduce pressure on the compilation of the + * core alloc routine.

+ * + * Precondition: None + * + * Postconditions: A new cell has been allocated (not zeroed), and + * the block containing the cell has been placed on the appropriate + * free list data structures. The free list itself is not updated + * (the caller must do so).

+ * + * @param bytes The size of the object to occupy this space, in bytes. + * @param offset The alignment offset. + * @param align The requested alignment. + * @return The address of the first word or zero on failure. + */ + @NoInline + public final Address allocSlowOnce(int bytes, int align, int offset) { + // Did a collection occur and provide a free cell? + bytes = getMaximumAlignedSize(bytes, align); + int sizeClass = space.getSizeClass(bytes); + Address cell = freeList.get(sizeClass); + + if (cell.isZero()) { + Address block = currentBlock.get(sizeClass); + if (!block.isZero()) { + // Return the block if we currently own one + space.returnConsumedBlock(block, sizeClass); + currentBlock.set(sizeClass, Address.zero()); + } + + // Get a new block for allocation, if returned, it is guaranteed to have a free cell + block = space.getAllocationBlock(sizeClass, freeList); + + if (!block.isZero()) { + // We have a new current block and free list. + currentBlock.set(sizeClass, block); + cell = freeList.get(sizeClass); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!cell.isZero()); + } else { + // Allocation Failure + return Address.zero(); + } + } + + freeList.set(sizeClass, cell.loadAddress()); + /* Clear the free list link */ + cell.store(Address.zero()); + return alignAllocation(cell, align, offset); + } + + /**************************************************************************** + * + * Preserving (saving & restoring) free lists + */ + + /** + * Zero all of the current free list pointers, and refresh the + * currentBlock values, so instead of the free list + * pointing to free cells, it points to the block containing the + * free cells. Then the free lists for each cell can be + * reestablished during GC. If the free lists are being preserved + * on a per-block basis (eager mark-sweep and reference counting), + * then free lists are remembered for each block. + */ + public final void flush() { + for (int sizeClass = 0; sizeClass < space.sizeClassCount(); sizeClass++) { + Address block = currentBlock.get(sizeClass); + if (!block.isZero()) { + Address cell = freeList.get(sizeClass); + space.returnBlock(block, sizeClass, cell); + currentBlock.set(sizeClass, Address.zero()); + freeList.set(sizeClass, Address.zero()); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,120 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This supports unsynchronized enqueuing and dequeuing of addresses + */ + at Uninterruptible public class AddressDeque extends LocalDeque + implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + public final String name; + + /** + * Constructor + * + * @param queue The shared queue to which this queue will append + * its buffers (when full or flushed) and from which it will aquire new + * buffers when it has exhausted its own. + */ + public AddressDeque(String n, SharedDeque queue) { + super(queue); + name = n; + } + + /** + * Insert an address into the address queue. + * + * @param addr the address to be inserted into the address queue + */ + @Inline + public final void insert(Address addr) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero()); + checkTailInsert(1); + uncheckedTailInsert(addr); + } + + /** + * Insert an address into the address queue, force this out of line + * ("OOL"), in some circumstnaces it is too expensive to have the + * insert inlined, so this call is made. + * + * @param addr the address to be inserted into the address queue + */ + @NoInline + public final void insertOOL(Address addr) { + insert(addr); + } + + /** + * Push an address onto the address queue. + * + * @param addr the address to be pushed onto the address queue + */ + @Inline + public final void push(Address addr) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero()); + checkHeadInsert(1); + uncheckedHeadInsert(addr); + } + + /** + * Push an address onto the address queue, force this out of line + * ("OOL"), in some circumstnaces it is too expensive to have the + * push inlined, so this call is made. + * + * @param addr the address to be pushed onto the address queue + */ + @NoInline + public final void pushOOL(Address addr) { + push(addr); + } + + /** + * Pop an address from the address queue, return zero if the queue + * is empty. + * + * @return The next address in the address queue, or zero if the + * queue is empty + */ + @Inline + public final Address pop() { + if (checkDequeue(1)) { + return uncheckedDequeue(); + } else { + return Address.zero(); + } + } + + @Inline + public final boolean isEmpty() { + return !checkDequeue(1); + } + + @Inline + public final boolean isNonEmpty() { + return checkDequeue(1); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,98 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This supports unsynchronized enqueuing and dequeuing of + * address pairs + */ + at Uninterruptible public class AddressPairDeque extends LocalDeque implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param queue The shared queue to which this queue will append + * its buffers (when full or flushed) and from which it will aquire new + * buffers when it has exhausted its own. + */ + public AddressPairDeque(SharedDeque queue) { + super(queue); + } + + /** + * Insert an address pair into the address queue. + * + * @param addr1 the first address to be inserted into the address queue + * @param addr2 the second address to be inserted into the address queue + */ + public final void insert(Address addr1, Address addr2) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero()); + checkTailInsert(2); + uncheckedTailInsert(addr1); + uncheckedTailInsert(addr2); + } + + /** + * Push an address pair onto the address queue. + * + * @param addr1 the first value to be pushed onto the address queue + * @param addr2 the second value to be pushed onto the address queue + */ + public final void push(Address addr1, Address addr2) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero()); + checkHeadInsert(2); + uncheckedHeadInsert(addr2); + uncheckedHeadInsert(addr1); + } + + /** + * Pop the first address in a pair from the address queue, return + * zero if the queue is empty. + * + * @return The next address in the address queue, or zero if the + * queue is empty + */ + public final Address pop1() { + if (checkDequeue(2)) + return uncheckedDequeue(); + else + return Address.zero(); + } + + /** + * Pop the second address in a pair from the address queue. + * + * @return The next address in the address queue + */ + public final Address pop2() { + return uncheckedDequeue(); + } + + public final boolean isEmpty() { + return !checkDequeue(2); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,111 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.Uninterruptible; + + +/** + * This supports unsynchronized enqueuing and dequeuing of + * address triples + */ + at Uninterruptible public class AddressTripleDeque extends LocalDeque implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param queue The shared queue to which this queue will append its + * buffers (when full or flushed) and from which it will aquire new + * buffers when it has exhausted its own. + */ + AddressTripleDeque(SharedDeque queue) { + super(queue); + } + + /** + * Insert an address triple into the address queue. + * + * @param addr1 the first address to be inserted into the address queue + * @param addr2 the second address to be inserted into the address queue + * @param addr3 the third address to be inserted into the address queue + */ + public final void insert(Address addr1, Address addr2, + Address addr3) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr3.isZero()); + checkTailInsert(3); + uncheckedTailInsert(addr1); + uncheckedTailInsert(addr2); + uncheckedTailInsert(addr3); + } + /** + * Push an address pair onto the address queue. + * + * @param addr1 the first value to be pushed onto the address queue + * @param addr2 the second value to be pushed onto the address queue + * @param addr3 the third address to be pushed onto the address queue + */ + public final void push(Address addr1, Address addr2, Address addr3) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr3.isZero()); + checkHeadInsert(3); + uncheckedHeadInsert(addr3); + uncheckedHeadInsert(addr2); + uncheckedHeadInsert(addr1); + } + + /** + * Pop the first address in a triple from the address queue, return + * zero if the queue is empty. + * + * @return The next address in the address queue, or zero if the + * queue is empty + */ + public final Address pop1() { + if (checkDequeue(3)) + return uncheckedDequeue(); + else + return Address.zero(); + } + + /** + * Pop the second address in a triple from the address queue. + * + * @return The next address in the address queue + */ + public final Address pop2() { + return uncheckedDequeue(); + } + + + /** + * Pop the third address in a triple from the address queue. + * + * @return The next address in the address queue + */ + public final Address pop3() { + return uncheckedDequeue(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,79 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Class that defines a doubly-linked double-ended queue (deque). The + * double-linking increases the space demands slightly, but makes it far + * more efficient to dequeue buffers and, for example, enables sorting of + * its contents. + */ + at Uninterruptible class Deque implements Constants { + + /**************************************************************************** + * + * Protected instance methods + * + * protected int enqueued; + */ + + @Inline + protected final Offset bufferOffset(Address buf) { + return buf.toWord().and(BUFFER_MASK).toOffset(); + } + @Inline + protected final Address bufferStart(Address buf) { + return buf.toWord().and(BUFFER_MASK.not()).toAddress(); + } + @Inline + protected final Address bufferEnd(Address buf) { + return bufferStart(buf).plus(USABLE_BUFFER_BYTES); + } + @Inline + protected final Address bufferFirst(Address buf) { + return bufferStart(buf); + } + @Inline + protected final Address bufferLast(Address buf, int arity) { + return bufferStart(buf).plus(bufferLastOffset(arity)); + } + @Inline + protected final Address bufferLast(Address buf) { + return bufferLast(buf, 1); + } + @Inline + protected final Offset bufferLastOffset(int arity) { + return Offset.fromIntZeroExtend(USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS - + (USABLE_BUFFER_BYTES % (arity << LOG_BYTES_IN_ADDRESS))); + } + + /**************************************************************************** + * + * Private and protected static final fields (aka constants) + */ + protected static final int LOG_PAGES_PER_BUFFER = 0; + protected static final int PAGES_PER_BUFFER = 1 << LOG_PAGES_PER_BUFFER; + private static final int LOG_BUFFER_SIZE = (LOG_BYTES_IN_PAGE + LOG_PAGES_PER_BUFFER); + protected static final int BUFFER_SIZE = 1 << LOG_BUFFER_SIZE; + protected static final Word BUFFER_MASK = Word.one().lsh(LOG_BUFFER_SIZE).minus(Word.one()); + protected static final int NEXT_FIELD_OFFSET = BYTES_IN_ADDRESS; + protected static final int META_DATA_SIZE = 2 * BYTES_IN_ADDRESS; + protected static final int USABLE_BUFFER_BYTES = BUFFER_SIZE - META_DATA_SIZE; + protected static final Address TAIL_INITIAL_VALUE = Address.zero(); + protected static final Address HEAD_INITIAL_VALUE = Address.zero(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,158 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.plan.Plan; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Note this may perform poorly when being used as a FIFO structure with + * insertHead and pop operations operating on the same buffer. This + * only uses the fields inherited from LocalQueue, but adds + * the ability for entries to be added to the head of the deque and popped + * from the rear. + */ + at Uninterruptible public class LocalDeque extends LocalQueue + implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param queue The shared deque to which this local deque will append + * its buffers (when full or flushed). + */ + LocalDeque(SharedDeque queue) { + super(queue); + } + + /** + * Flush the buffer to the shared deque (this will make any entries + * in the buffer visible to any other consumer associated with the + * shared deque). + */ + @Override + public final void flushLocal() { + super.flushLocal(); + if (head.NE(Deque.HEAD_INITIAL_VALUE)) { + closeAndInsertHead(queue.getArity()); + head = Deque.HEAD_INITIAL_VALUE; + } + } + + /**************************************************************************** + * + * Protected instance methods + */ + + /** + * Check whether there is space in the buffer for a pending insert. + * If there is not sufficient space, allocate a new buffer + * (dispatching the full buffer to the shared deque if not null). + * + * @param arity The arity of the values stored in this deque: the + * buffer must contain enough space for this many words. + */ + @Inline + protected final void checkHeadInsert(int arity) { + if (bufferOffset(head).EQ(bufferSentinel(arity)) || + head.EQ(HEAD_INITIAL_VALUE)) + headOverflow(arity); + else if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sLE(bufferLastOffset(arity))); + } + + /** + * Insert a value at the front of the deque (and buffer). This is + * unchecked. The caller must first call + * checkHeadInsert() to ensure the buffer can accommodate + * the insertion. + * + * @param value the value to be inserted. + */ + @Inline + protected final void uncheckedHeadInsert(Address value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sLT(bufferSentinel(queue.getArity()))); + head.store(value); + head = head.plus(BYTES_IN_ADDRESS); + // if (Interface.VerifyAssertions) enqueued++; + } + + /**************************************************************************** + * + * Private instance methods and fields + */ + + /** + * Buffer space has been exhausted, allocate a new buffer and enqueue + * the existing buffer (if any). + * + * @param arity The arity of this buffer (used for sanity test only). + */ + private void headOverflow(int arity) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity()); + if (head.NE(Deque.HEAD_INITIAL_VALUE)) + closeAndInsertHead(arity); + + head = queue.alloc(); + Plan.checkForAsyncCollection(); // possible side-effect of alloc() + } + + /** + * Close the head buffer and enqueue it at the front of the + * shared buffer deque. + * + * @param arity The arity of this buffer. + */ + @Inline + private void closeAndInsertHead(int arity) { + queue.enqueue(head, arity, false); + } + + /** + * The tail is empty (or null), and the shared deque has no buffers + * available. If the head has sufficient entries, consume the head. + * Otherwise try wait on the shared deque until either all other + * clients of the reach exhaustion or a buffer becomes + * available. + * + * @param arity The arity of this buffer + * @return True if the consumer has eaten all of the entries + */ + @SuppressWarnings("unused") + private boolean tailStarved(int arity) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity()); + // entries in tail, so consume tail + if (!bufferOffset(head).isZero()) { + tailBufferEnd = head; + tail = bufferStart(tailBufferEnd); + head = Deque.HEAD_INITIAL_VALUE; + return false; + } + + // Wait for another entry to materialize... + tailBufferEnd = queue.dequeueAndWait(arity, true); + tail = bufferStart(tail); + + // return true if a) there is not a tail buffer or b) it is empty + return (tail.EQ(Deque.TAIL_INITIAL_VALUE) || tail.EQ(tailBufferEnd)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,158 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements a local (unsynchronized) queue. + * A queue is strictly FIFO.

+ * + * Each instance stores word-sized values into a local buffer. When + * the buffer is full, or if the flushLocal() method is + * called, the buffer enqueued at the tail of a + * SharedDeque. + * + * The implementation is intended to be as efficient as possible, in + * time and space, and is the basis for the TraceBuffer used by + * heap trace generation. Each instance adds a single field to those inherited + * from the SSB: a bump pointer. + * + * Preconditions: Buffers are always aligned on buffer-size address + * boundaries.

+ * + * Invariants: Buffers are filled such that tuples (of the specified + * arity) are packed to the low end of the buffer. Thus buffer + * underflows will always arise when then cursor is buffer-size aligned. + */ + at Uninterruptible class LocalQueue extends LocalSSB implements Constants { + + /** + * Constructor + * + * @param queue The shared queue to which this local ssb will append + * its buffers (when full or flushed). + */ + LocalQueue(SharedDeque queue) { + super(queue); + } + + /**************************************************************************** + * + * Protected instance methods and fields + */ + @Entrypoint + protected Address head; // the start of the buffer + + /** + * Reset the local buffer (throwing away any local entries). + */ + public void resetLocal() { + super.resetLocal(); + head = Deque.HEAD_INITIAL_VALUE; + } + + /** + * Check whether there are values in the buffer for a pending dequeue. + * If there is not data, grab the first buffer on the shared queue + * (after freeing the buffer). + * + * @param arity The arity of the values stored in this queue: the + * buffer must contain enough space for this many words. + */ + @Inline + protected final boolean checkDequeue(int arity) { + if (bufferOffset(head).isZero()) { + return dequeueUnderflow(arity); + } else { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sGE(Word.fromIntZeroExtend(arity).lsh(LOG_BYTES_IN_ADDRESS).toOffset())); + return true; + } + } + + /** + * Dequeue a value from the buffer. This is unchecked. The + * caller must first call checkDequeue() to ensure the + * buffer has and entry to be removed. + * + * @return The first entry on the queue. + */ + @Inline + protected final Address uncheckedDequeue(){ + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sGE(Offset.fromIntZeroExtend(BYTES_IN_ADDRESS))); + head = head.minus(BYTES_IN_ADDRESS); + return head.loadAddress(); + } + + /** + * The head is empty (or null), and the shared queue has no buffers + * available. If the tail has sufficient entries, consume the tail. + * Otherwise try wait on the global queue until either all other + * clients of the queue reach exhaustion or a buffer becomes + * available. + * + * @param arity The arity of this buffer + * @return True if the consumer has eaten all the entries + */ + protected final boolean headStarved(int arity) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity()); + + // If the tail has entries... + if (tail.NE(tailBufferEnd)) { + head = normalizeTail(arity).plus(BYTES_IN_ADDRESS); + tail = Deque.TAIL_INITIAL_VALUE; + tailBufferEnd = Deque.TAIL_INITIAL_VALUE; + // Return that we acquired more entries + return false; + } + // Wait for another entry to materialize... + head = queue.dequeueAndWait(arity); + // return true if a) there is a head buffer, and b) it is non-empty + return (head.EQ(Deque.HEAD_INITIAL_VALUE) || bufferOffset(head).isZero()); + } + + /**************************************************************************** + * + * Private instance methods + */ + + /** + * There are not sufficient entries in the head buffer for a pending + * dequeue. Acquire a new head buffer. If the shared queue has no + * buffers available, consume the tail if necessary. Return false + * if entries cannot be acquired. + * + * @param arity The arity of this buffer (used for sanity test only). + * @return True if there the head buffer has been successfully + * replenished. + */ + @NoInline + private boolean dequeueUnderflow(int arity) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity()); + do { + if (head.NE(Deque.HEAD_INITIAL_VALUE)) + queue.free(head); + head = queue.dequeue(arity); + } while (head.NE(Deque.HEAD_INITIAL_VALUE) && bufferOffset(head).isZero()); + + if (head.EQ(Deque.HEAD_INITIAL_VALUE)) + return !headStarved(arity); + + return true; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,214 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.plan.Plan; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements a local (unsynchronized) sequential + * store buffer. An SSB is strictly FIFO (although this class does + * not implement dequeuing).

+ * + * Each instance stores word-sized values into a local buffer. When + * the buffer is full, or if the flushLocal() method is + * called, the buffer enqueued at the tail of a + * SharedDeque. This class provides no mechanism for + * dequeing.

+ * + * The implementation is intended to be as efficient as possible, in + * time and space, as it is used in critical code such as the GC work + * queue and the write buffer used by many "remembering" + * collectors. Each instance has just two fields: a bump pointer and a + * pointer to the SharedDeque

+ * + * Preconditions: Buffers are always aligned on buffer-size address + * boundaries.

+ * + * Invariants: Buffers are filled such that tuples (of the specified + * arity) are packed to the low end of the buffer. Thus buffer + * overflows on inserts and pops (underflow actually) will always arise + * when then cursor is buffer-size aligned. + */ + at Uninterruptible class LocalSSB extends Deque implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param queue The shared queue to which this local ssb will append + * its buffers (when full or flushed). + */ + LocalSSB(SharedDeque queue) { + this.queue = queue; + resetLocal(); + } + + /** + * Flush the buffer and add it to the shared queue (this will + * make any entries in the buffer visible to any consumer associated + * with the shared queue). + */ + public void flushLocal() { + if (tail.NE(Deque.TAIL_INITIAL_VALUE)) { + closeAndEnqueueTail(queue.getArity()); + tail = Deque.TAIL_INITIAL_VALUE; + tailBufferEnd = Deque.TAIL_INITIAL_VALUE; + } + } + + public void reset() { + resetLocal(); + } + + /**************************************************************************** + * + * Protected instance methods and fields + */ + @Entrypoint + protected Address tail; // the location in the buffer + protected Address tailBufferEnd; // the end of the buffer + protected final SharedDeque queue; // the shared queue + + /** + * Reset the local buffer (throwing away any local entries). + */ + public void resetLocal() { + tail = Deque.TAIL_INITIAL_VALUE; + tailBufferEnd = Deque.TAIL_INITIAL_VALUE; + } + + /** + * Check whether there is space in the buffer for a pending insert. + * If there is not sufficient space, allocate a new buffer + * (dispatching the full buffer to the shared queue if not null). + * + * @param arity The arity of the values stored in this SSB: the + * buffer must contain enough space for this many words. + */ + @Inline(value=Inline.When.AssertionsDisabled) + protected final void checkTailInsert(int arity) { + if (bufferOffset(tail).isZero()) + tailOverflow(arity); + else if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(tail).sGE(Word.fromIntZeroExtend(arity).lsh(LOG_BYTES_IN_ADDRESS).toOffset())); + } + + /** + * Insert a value into the buffer. This is unchecked. The + * caller must first call checkInsert() to ensure the + * buffer can accommodate the insertion. + * + * @param value the value to be inserted. + */ + @Inline(value=Inline.When.AssertionsDisabled) + protected final void uncheckedTailInsert(Address value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(tail).sGE(Offset.fromIntZeroExtend(BYTES_IN_ADDRESS))); + tail = tail.minus(BYTES_IN_ADDRESS); + tail.store(value); + // if (Interface.VerifyAssertions) enqueued++; + } + + /** + * In the case where a buffer must be flushed before being + * filled (either to the queue or to the head), the entries must be + * slid to the base of the buffer in order to preserve the invariant + * that all non-tail buffers will have entries starting at the base + * (which allows a simple test against the base to be used when + * popping entries). This is expensive, so should be + * avoided. + * + * @param arity The arity of the buffer in question + * @return The last slot in the normalized buffer that contains an entry + */ + protected final Address normalizeTail(int arity) { + Address src = tail; + Address tgt = bufferFirst(tail); + Address last = tgt.plus(bufferLastOffset(arity).minus(bufferOffset(tail))); + while (tgt.LE(last)) { + tgt.store(src.loadAddress()); + src = src.plus(BYTES_IN_ADDRESS); + tgt = tgt.plus(BYTES_IN_ADDRESS); + } + return last; + } + + /** + * Return the sentinel offset for a buffer of a given arity. This is used + * both to compute the address at the end of the buffer. + * + * @param arity The arity of this buffer + * @return The sentinel offset value for a buffer of the given arity. + */ + @Inline + protected final Offset bufferSentinel(int arity) { + return bufferLastOffset(arity).plus(BYTES_IN_ADDRESS); + } + + /**************************************************************************** + * + * Private instance methods + */ + + /** + * Buffer space has been exhausted, allocate a new buffer and enqueue + * the existing buffer (if any). + * + * @param arity The arity of this buffer (used for sanity test only). + */ + private void tailOverflow(int arity) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity()); + if (tail.NE(Deque.TAIL_INITIAL_VALUE)) { + closeAndEnqueueTail(arity); + } + tail = queue.alloc().plus(bufferSentinel(arity)); + tailBufferEnd = tail; + Plan.checkForAsyncCollection(); // possible side-effect of alloc() + } + + /** + * Close the tail buffer (normalizing if necessary), and enqueue it + * at the tail of the shared buffer queue. + * + * @param arity The arity of this buffer. + */ + @NoInline + private void closeAndEnqueueTail(int arity) { + Address last; + if (!bufferOffset(tail).isZero()) { + // prematurely closed + last = normalizeTail(arity); + } else { + // a full tail buffer + last = tailBufferEnd.minus(BYTES_IN_ADDRESS); + } + queue.enqueue(last.plus(BYTES_IN_ADDRESS), arity, true); + } + + /** + * Return true if this SSB is locally empty + * + * @return true if this SSB is locally empty + */ + public final boolean isFlushed() { + return tail.EQ(Deque.TAIL_INITIAL_VALUE); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,128 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.Constants; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class is a combination of a Deque and a TraceStep, designed to include + * intelligent processing of child references as objects are scanned. + * + * @see org.mmtk.plan.TransitiveClosure + */ + at Uninterruptible +public abstract class ObjectReferenceBuffer extends TransitiveClosure implements Constants { + /**************************************************************************** + * + * Instance variables + */ + private final ObjectReferenceDeque values; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name of the underlying deque. + * @param queue The shared deque that is used. + */ + public ObjectReferenceBuffer(String name, SharedDeque queue) { + values = new ObjectReferenceDeque(name, queue); + } + + /** + * Trace an edge during GC. + * + * @param source The source of the reference. + * @param slot The location containing the object reference. + */ + @Inline + public final void processEdge(ObjectReference source, Address slot) { + ObjectReference object = VM.activePlan.global().loadObjectReference(slot); + process(object); + } + + /** + * This is the method that ensures + * + * @param object The object to process. + */ + protected abstract void process(ObjectReference object); + + /** + * Process each of the child objects for the passed object. + * + * @param object The object to process the children of. + */ + @Inline + public final void processChildren(ObjectReference object) { + VM.scanning.scanObject(this, object); + } + + /** + * Pushes an object onto the queue, forcing an inlined sequence. + * + * @param object The object to push. + */ + @Inline + public final void push(ObjectReference object) { + values.push(object); + } + + /** + * Pushes an object onto the queue, forcing an out of line sequence. + * + * @param object The object to push. + */ + @Inline + public final void pushOOL(ObjectReference object) { + values.pushOOL(object); + } + + /** + * Retrives an object. + * + * @return The object retrieved. + */ + @Inline + public final ObjectReference pop() { + return values.pop(); + } + + @Inline + public final boolean isEmpty() { + return values.isEmpty(); + } + + /** + * Flushes all local state back to the shared queue. + */ + public final void flushLocal() { + values.flushLocal(); + } + + /** + * Return true if this buffer is locally empty + */ + public final boolean isFlushed() { + return values.isFlushed(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,109 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This supports unsynchronized enqueuing and dequeuing of + * object references + */ + at Uninterruptible public class ObjectReferenceDeque extends LocalDeque + implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + public final String name; + + /** + * Constructor + * + * @param queue The shared queue to which this queue will append + * its buffers (when full or flushed) and from which it will aquire new + * buffers when it has exhausted its own. + */ + public ObjectReferenceDeque(String n, SharedDeque queue) { + super(queue); + name = n; + } + + /** + * Insert an object into the object queue. + * + * @param object the object to be inserted into the object queue + */ + @Inline + public final void insert(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull()); + checkTailInsert(1); + uncheckedTailInsert(object.toAddress()); + } + + /** + * Push an object onto the object queue. + * + * @param object the object to be pushed onto the object queue + */ + @Inline + public final void push(ObjectReference object) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull()); + checkHeadInsert(1); + uncheckedHeadInsert(object.toAddress()); + } + + /** + * Push an object onto the object queue, force this out of line + * ("OOL"), in some circumstnaces it is too expensive to have the + * push inlined, so this call is made. + * + * @param object the object to be pushed onto the object queue + */ + @NoInline + public final void pushOOL(ObjectReference object) { + push(object); + } + + /** + * Pop an object from the object queue, return zero if the queue + * is empty. + * + * @return The next object in the object queue, or zero if the + * queue is empty + */ + @Inline + public final ObjectReference pop() { + if (checkDequeue(1)) { + return uncheckedDequeue().toObjectReference(); + } else { + return ObjectReference.nullReference(); + } + } + + @Inline + public final boolean isEmpty() { + return !checkDequeue(1); + } + + @Inline + public final boolean isNonEmpty() { + return checkDequeue(1); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,497 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.policy.RawPageSpace; +import org.mmtk.policy.Space; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; +import org.mmtk.vm.Lock; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.Entrypoint; +import org.vmmagic.pragma.Inline; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Offset; + +/** + * This supports unsynchronized enqueuing and dequeuing of buffers + * for shared use. The data can be added to and removed from either end + * of the deque. + */ + at Uninterruptible +public class SharedDeque extends Deque implements Constants { + private static final boolean DISABLE_WAITING = true; + private static final Offset NEXT_OFFSET = Offset.zero(); + private static final Offset PREV_OFFSET = Offset.fromIntSignExtend(BYTES_IN_ADDRESS); + + private static final boolean TRACE = false; + private static final boolean TRACE_DETAIL = false; + private static final boolean TRACE_BLOCKERS = false; + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + */ + public SharedDeque(String name, RawPageSpace rps, int arity) { + this.rps = rps; + this.arity = arity; + this.name = name; + lock = VM.newLock("SharedDeque"); + clearCompletionFlag(); + head = HEAD_INITIAL_VALUE; + tail = TAIL_INITIAL_VALUE; + } + + /** Get the arity (words per entry) of this queue */ + @Inline + final int getArity() { return arity; } + + /** + * Enqueue a block on the head or tail of the shared queue + * + * @param buf + * @param arity + * @param toTail + */ + final void enqueue(Address buf, int arity, boolean toTail) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == this.arity); + lock(); + if (toTail) { + // Add to the tail of the queue + setNext(buf, Address.zero()); + if (tail.EQ(TAIL_INITIAL_VALUE)) + head = buf; + else + setNext(tail, buf); + setPrev(buf, tail); + tail = buf; + } else { + // Add to the head of the queue + setPrev(buf, Address.zero()); + if (head.EQ(HEAD_INITIAL_VALUE)) + tail = buf; + else + setPrev(head, buf); + setNext(buf, head); + head = buf; + } + bufsenqueued++; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(checkDequeLength(bufsenqueued)); + unlock(); + } + + public final void clearDeque(int arity) { + Address buf = dequeue(arity); + while (!buf.isZero()) { + free(bufferStart(buf)); + buf = dequeue(arity); + } + setCompletionFlag(); + } + + @Inline + final Address dequeue(int arity) { + return dequeue(arity, false); + } + + final Address dequeue(int arity, boolean fromTail) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == this.arity); + return dequeue(false, fromTail); + } + + @Inline + final Address dequeueAndWait(int arity) { + return dequeueAndWait(arity, false); + } + + final Address dequeueAndWait(int arity, boolean fromTail) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == this.arity); + Address buf = dequeue(false, fromTail); + if (buf.isZero() && (!complete())) { + buf = dequeue(true, fromTail); // Wait inside dequeue + } + return buf; + } + + /** + * Prepare for parallel processing. All active GC threads will + * participate, and pop operations will block until all work + * is complete. + */ + public final void prepare() { + if (DISABLE_WAITING) { + prepareNonBlocking(); + } else { + /* This should be the normal mode of operation once performance is fixed */ + prepare(VM.collection.activeGCThreads()); + } + } + + /** + * Prepare for processing where pop operations on the deques + * will never block. + */ + public final void prepareNonBlocking() { + prepare(1); + } + + /** + * Prepare for parallel processing where a specific number + * of threads take part. + * + * @param consumers # threads taking part. + */ + private void prepare(int consumers) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(numConsumersWaiting == 0); + setNumConsumers(consumers); + clearCompletionFlag(); + } + + public final void reset() { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(numConsumersWaiting == 0); + clearCompletionFlag(); + setNumConsumersWaiting(0); + assertExhausted(); + } + + public final void assertExhausted() { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(head.isZero() && tail.isZero()); + } + + @Inline + final Address alloc() { + Address rtn = rps.acquire(PAGES_PER_BUFFER); + if (rtn.isZero()) { + Space.printUsageMB(); + VM.assertions.fail("Failed to allocate space for queue. Is metadata virtual memory exhausted?"); + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn.EQ(bufferStart(rtn))); + return rtn; + } + + @Inline + final void free(Address buf) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(buf.EQ(bufferStart(buf)) && !buf.isZero()); + rps.release(buf); + } + + @Inline + public final int enqueuedPages() { + return (int) (bufsenqueued * PAGES_PER_BUFFER); + } + + /**************************************************************************** + * + * Private instance methods and fields + */ + + /** The name of this shared deque - for diagnostics */ + private final String name; + + /** Raw page space from which to allocate */ + private RawPageSpace rps; + + /** Number of words per entry */ + private final int arity; + + /** Completion flag - set when all consumers have arrived at the barrier */ + @Entrypoint + private volatile int completionFlag; + + /** # active threads - processing is complete when # waiting == this */ + @Entrypoint + private volatile int numConsumers; + + /** # threads waiting */ + @Entrypoint + private volatile int numConsumersWaiting; + + /** Head of the shared deque */ + @Entrypoint + protected volatile Address head; + + /** Tail of the shared deque */ + @Entrypoint + protected volatile Address tail; + @Entrypoint + private volatile int bufsenqueued; + private Lock lock; + + private static final long WARN_PERIOD = (long)(2*1E9); + private static final long TIMEOUT_PERIOD = 10 * WARN_PERIOD; + + /** + * Dequeue a block from the shared pool. If 'waiting' is true, and the + * queue is empty, wait for either a new block to show up or all the + * other consumers to join us. + * + * @param waiting + * @param fromTail + * @return the Address of the block + */ + private Address dequeue(boolean waiting, boolean fromTail) { + lock(); + Address rtn = ((fromTail) ? tail : head); + if (rtn.isZero()) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tail.isZero() && head.isZero()); + // no buffers available + if (waiting) { + int ordinal = TRACE ? 0 : VM.activePlan.collector().getId(); + setNumConsumersWaiting(numConsumersWaiting + 1); + while (rtn.isZero()) { + if (numConsumersWaiting == numConsumers) + setCompletionFlag(); + if (TRACE) { + Log.write("-- ("); Log.write(ordinal); + Log.write(") joining wait queue of SharedDeque("); + Log.write(name); Log.write(") "); + Log.write(numConsumersWaiting); Log.write("/"); + Log.write(numConsumers); + Log.write(" consumers waiting"); + if (complete()) Log.write(" WAIT COMPLETE"); + Log.writeln(); + if (TRACE_BLOCKERS) + VM.assertions.dumpStack(); + } + unlock(); + // Spin and wait + spinWait(fromTail); + + if (complete()) { + if (TRACE) { + Log.write("-- ("); Log.write(ordinal); Log.writeln(") EXITING"); + } + lock(); + setNumConsumersWaiting(numConsumersWaiting - 1); + unlock(); + return Address.zero(); + } + lock(); + // Re-get the list head/tail while holding the lock + rtn = ((fromTail) ? tail : head); + } + setNumConsumersWaiting(numConsumersWaiting - 1); + if (TRACE) { + Log.write("-- ("); Log.write(ordinal); Log.write(") resuming work "); + Log.write(" n="); Log.writeln(numConsumersWaiting); + } + } else { + unlock(); + return Address.zero(); + } + } + if (fromTail) { + // dequeue the tail buffer + setTail(getPrev(tail)); + if (head.EQ(rtn)) { + setHead(Address.zero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tail.isZero()); + } else { + setNext(tail, Address.zero()); + } + } else { + // dequeue the head buffer + setHead(getNext(head)); + if (tail.EQ(rtn)) { + setTail(Address.zero()); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(head.isZero()); + } else { + setPrev(head, Address.zero()); + } + } + bufsenqueued--; + unlock(); + return rtn; + } + + /** + * Spinwait for GC work to arrive + * + * @param fromTail Check the head or the tail ? + */ + private void spinWait(boolean fromTail) { + long startNano = 0; + long lastElapsedNano = 0; + while (true) { + long startCycles = VM.statistics.cycles(); + long endCycles = startCycles + ((long) 1e9); // a few hundred milliseconds more or less. + long nowCycles; + do { + VM.memory.isync(); + Address rtn = ((fromTail) ? tail : head); + if (!rtn.isZero() || complete()) return; + nowCycles = VM.statistics.cycles(); + } while (startCycles < nowCycles && nowCycles < endCycles); /* check against both ends to guard against CPU migration */ + + /* + * According to the cycle counter, we've been spinning for a while. + * Time to check nanoTime and see if we should print a warning and/or fail. + * We lock the deque while doing this to avoid interleaved messages from multiple threads. + */ + lock(); + if (startNano == 0) { + startNano = VM.statistics.nanoTime(); + } else { + long nowNano = VM.statistics.nanoTime(); + long elapsedNano = nowNano - startNano; + if (elapsedNano - lastElapsedNano > WARN_PERIOD) { + Log.write("GC Warning: SharedDeque("); Log.write(name); + Log.write(") wait has reached "); Log.write(VM.statistics.nanosToSecs(elapsedNano)); + Log.write(", "); Log.write(numConsumersWaiting); Log.write("/"); + Log.write(numConsumers); Log.writeln(" threads waiting"); + lastElapsedNano = elapsedNano; + } + if (elapsedNano > TIMEOUT_PERIOD) { + unlock(); // To allow other GC threads to die in turn + VM.assertions.fail("GC Error: SharedDeque Timeout"); + } + } + unlock(); + } + } + + /** + * Set the "next" pointer in a buffer forming the linked buffer chain. + * + * @param buf The buffer whose next field is to be set. + * @param next The reference to which next should point. + */ + private static void setNext(Address buf, Address next) { + buf.store(next, NEXT_OFFSET); + } + + /** + * Get the "next" pointer in a buffer forming the linked buffer chain. + * + * @param buf The buffer whose next field is to be returned. + * @return The next field for this buffer. + */ + protected final Address getNext(Address buf) { + return buf.loadAddress(NEXT_OFFSET); + } + + /** + * Set the "prev" pointer in a buffer forming the linked buffer chain. + * + * @param buf The buffer whose next field is to be set. + * @param prev The reference to which prev should point. + */ + private void setPrev(Address buf, Address prev) { + buf.store(prev, PREV_OFFSET); + } + + /** + * Get the "next" pointer in a buffer forming the linked buffer chain. + * + * @param buf The buffer whose next field is to be returned. + * @return The next field for this buffer. + */ + protected final Address getPrev(Address buf) { + return buf.loadAddress(PREV_OFFSET); + } + + /** + * Check the number of buffers in the work queue (for debugging + * purposes). + * + * @param length The number of buffers believed to be in the queue. + * @return True if the length of the queue matches length. + */ + private boolean checkDequeLength(int length) { + Address top = head; + int l = 0; + while (!top.isZero() && l <= length) { + top = getNext(top); + l++; + } + return l == length; + } + + /** + * Lock this shared queue. We use one simple low-level lock to + * synchronize access to the shared queue of buffers. + */ + private void lock() { + lock.acquire(); + } + + /** + * Release the lock. We use one simple low-level lock to synchronize + * access to the shared queue of buffers. + */ + private void unlock() { + lock.release(); + } + + /** + * Is the current round of processing complete ? + */ + private boolean complete() { + return completionFlag == 1; + } + + /** + * Set the completion flag. + */ + @Inline + private void setCompletionFlag() { + if (TRACE_DETAIL) { + Log.writeln("# setCompletionFlag: "); + } + completionFlag = 1; + } + + /** + * Clear the completion flag. + */ + @Inline + private void clearCompletionFlag() { + if (TRACE_DETAIL) { + Log.writeln("# clearCompletionFlag: "); + } + completionFlag = 0; + } + + @Inline + private void setNumConsumers(int newNumConsumers) { + if (TRACE_DETAIL) { + Log.write("# Num consumers "); Log.writeln(newNumConsumers); + } + numConsumers = newNumConsumers; + } + + @Inline + private void setNumConsumersWaiting(int newNCW) { + if (TRACE_DETAIL) { + Log.write("# Num consumers waiting "); Log.writeln(newNCW); + } + numConsumersWaiting = newNCW; + } + + @Inline + private void setHead(Address newHead) { + head = newHead; + VM.memory.sync(); + } + + @Inline + private void setTail(Address newTail) { + tail = newTail; + VM.memory.sync(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,372 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.policy.RawPageSpace; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This supports unsynchronized enqueuing and dequeuing of buffers + * for shared use. The data can be added to and removed from either end + * of the deque. This class is based upon the SharedQueue class. The sorting + * routines were modified from code written by Narendran Sachindran and + * Matthew Hertz for GCTk. + */ + at Uninterruptible public abstract class SortSharedDeque extends SharedDeque { + + + private static final int BYTES_PUSHED = BYTES_IN_ADDRESS * 5; + private static final int MAX_STACK_SIZE = BYTES_PUSHED * 64; + private static final Offset INSERTION_SORT_LIMIT = Offset.fromIntSignExtend(80); + + /*********************************************************************** + * + * Class variables + */ + + /** + * Constructor + * + * @param rps The space from which the instance should obtain buffers. + */ + public SortSharedDeque(String name, RawPageSpace rps, int arity) { + super(name, rps, arity); + stackBase = AddressArray.create(MAX_STACK_SIZE); + stackLoc = 0; + } + + /*********************************************************************** + * + * Sorting methods, utilities, and instance variables + */ + + + /** + * Return the sorting key for the object passed as a parameter. + * + * @param obj The address of the object whose key is wanted + * @return The value of the sorting key for this object + */ + protected abstract Word getKey(Address obj); + + private static final Word mask16 = Word.fromIntZeroExtend(0xffff0000); + private static final Word mask8 = Word.fromIntZeroExtend(0x0000ff00); + private static final Word mask4 = Word.fromIntZeroExtend(0x000000f0); + private static final Word mask2 = Word.fromIntZeroExtend(0x0000000c); + private static final Word mask1 = Word.fromIntZeroExtend(0x00000002); + + /** + * Find the highest bit that is set in a longword and return a mask + * with only that bit set. + * + * @param addr Value for which the mask needs to be found + * @return The highest bit set in the parameter + */ + private static Word getBitMask(Word addr) { + int shift = 0; + if (!addr.and(mask16).isZero()) { + addr = addr.rshl(16); + shift += 16; + } + if (!addr.and(mask8).isZero()) { + addr = addr.rshl(8); + shift += 8; + } + if (!addr.and(mask4).isZero()) { + addr = addr.rshl(4); + shift += 4; + } + if (!addr.and(mask2).isZero()) { + addr = addr.rshl(2); + shift += 2; + } + if (!addr.and(mask1).isZero()) { + shift += 1; + } + return (Word.one().lsh(shift)); + } + + /** + * Perform insertion sort within an intra-block address range. + * + * @param begin Start address of the range to be sorted + * @param end End address of the range to be sorted + */ + private void insertionSort(Address begin, Address end) { + Address rPtr = begin.minus(BYTES_IN_ADDRESS); + Address lPtr; + + while (rPtr.GE(end)) { + Address rSlot = rPtr.loadAddress(); + Word rKey = getKey(rSlot); + lPtr = rPtr.plus(BYTES_IN_ADDRESS); + while (lPtr.LE(begin)) { + Address lSlot = lPtr.loadAddress(); + Word lKey = getKey(lSlot); + if (lKey.GT(rKey)) { + lPtr.minus(BYTES_IN_ADDRESS).store(lSlot); + lPtr = lPtr.plus(BYTES_IN_ADDRESS); + } else { + break; + } + } + lPtr.minus(BYTES_IN_ADDRESS).store(rSlot); + rPtr = rPtr.minus(BYTES_IN_ADDRESS); + } + } + + /** + * Sort objects using radix exchange sort. An explicit stack is + * maintained to avoid using recursion. + */ + public void sort() { + Address startPtr, startLink, endPtr, endLink; + Word bitMask; + if (!head.EQ(HEAD_INITIAL_VALUE)) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tail.NE(TAIL_INITIAL_VALUE)); + /* Obtain the bitmask for the first iteration and save the start & + end pointers and the bitmask on the stack */ + initStack(); + startPtr = popStack(); + while (!startPtr.isZero()) { + startLink = popStack(); + endPtr = popStack(); + endLink = popStack(); + bitMask = (popStack()).toWord(); + if (startLink.NE(endLink)) { + partition(startPtr, startLink, endPtr, endLink, bitMask); + } else if (startPtr.GT(endPtr)) { + /* Use insertionSort for a limited number of objects within + a single block */ + if (startPtr.diff(endPtr).sLT(INSERTION_SORT_LIMIT)) { + insertionSort(startPtr, endPtr); + } else { + partition(startPtr, startLink, endPtr, endLink, bitMask); + } + } + // Get the next set of data to sort + startPtr = popStack(); + } + } + checkIfSorted(); + } + + /** + * Partition the slots in an address range based on the value in + * a particular bit. Place the start & end addresses of the two + * partitions & a bitmask per partition (which indicates the highest + * bit position at which the max & min of a partition differ) on the + * stack. This works just like the partition in quick sort, except + * that a bit value is being compared here + * + * @param startAddr The start address of the range to be sorted + * @param startLinkAddr The address where the start block has its next field + * @param endAddr The end address of the range to be sorted + * @param endLinkAddr The address where the end block has its next field + * @param bitMask The mask in which the bit to be commpared is set + */ + private void partition(Address startAddr, Address startLinkAddr, + Address endAddr, Address endLinkAddr, + Word bitMask) { + Address travPtr = endAddr; + Address travLink = endLinkAddr; + Address stopPtr = startAddr; + Address stopLink = startLinkAddr; + Address travSlot, stopSlot; + Word travKey, stopKey; + Word lmax = Word.zero(), rmax = Word.zero(); + Word lmin = Word.max(), rmin = Word.max(); + + while (true) { + /* Compute the address range within the current block to compute. */ + Address endOfBlock = travLink; + + /* Move the left pointer until the right pointer is reached + or an address with a 0 value in the bit position is found. */ + while (true) { + travSlot = travPtr.loadAddress(); + travKey = getKey(travSlot); + + /* If we reach the end. */ + if (travPtr.EQ(stopPtr)) + break; + /* If we found a 0 in bit position, break. */ + if (travKey.and(bitMask).isZero()) + break; + if (travKey.GT(rmax)) + rmax = travKey; + if (travKey.LT(rmin)) + rmin = travKey; + /* Move to the next entry. */ + travPtr = travPtr.plus(BYTES_IN_ADDRESS); + /* If at end of remset block, move to next block */ + if (travPtr.EQ(endOfBlock)) { + travLink = getPrev(travPtr); + endOfBlock = travLink; + travPtr = bufferStart(endOfBlock); + } + } + + /* Store the end of the block. */ + endOfBlock = bufferStart(stopPtr); + /* Move the right pointer until the left pointer is reached + or an address with a 1 value in the bit position is found. */ + while (true) { + stopSlot = stopPtr.loadAddress(); + stopKey = getKey(stopSlot); + /* Found a 1 in bit position, break. */ + if (!stopKey.and(bitMask).isZero()) + break; + if (stopKey.GT(lmax)) + lmax = stopKey; + if (stopKey.LT(lmin)) + lmin = stopKey; + if (stopPtr.EQ(travPtr)) + break; + /* Move to the next entry, which may be in the next block. */ + if (stopPtr.EQ(endOfBlock)) { + stopLink = getNext(stopLink); + stopPtr = stopLink; + endOfBlock = bufferStart(stopPtr); + } + stopPtr = stopPtr.minus(BYTES_IN_ADDRESS); + } + if (stopPtr.EQ(travPtr)) + break; + /* interchange the values pointed to by the left and right pointers */ + travPtr.store(stopSlot); + stopPtr.store(travSlot); + } + + /* If max value is not equal to the min value in the right partition, + (not all slots are identical) push the right partition on to the stack */ + if (rmax.GT(rmin)) { + if (travPtr.EQ(bufferStart(travPtr))) { + stopLink = getNext(travLink); + stopPtr = stopLink; + } else { + stopLink = travLink; + stopPtr = travPtr; + } + pushOnStack(getBitMask(rmax.xor(rmin)).toAddress()); + pushOnStack(endLinkAddr); + pushOnStack(endAddr); + pushOnStack(stopLink); + pushOnStack(stopPtr.minus(BYTES_IN_ADDRESS)); + } + /* if max value is not equal to the min value in the left partition, + (not all slots are identical) push the left partition on to the stack */ + if (lmax.GT(lmin)) { + pushOnStack(getBitMask(lmax.xor(lmin)).toAddress()); + pushOnStack(travLink); + pushOnStack(travPtr); + pushOnStack(startLinkAddr); + pushOnStack(startAddr); + } + } + + /************************************************************************* + * + * Sorting Stack management routines + */ + private int stackLoc; + private AddressArray stackBase; + + /* + * Allocate memory for the stack and intialize it with the first range + * to partition + */ + private void initStack() { + stackLoc = 0; + + Address endOfBlock = tail; + Address startPtr = bufferStart(endOfBlock); + Word min = Word.max(); + Word max = Word.zero(); + // Find the max. and min addresses in the object buffer + while (endOfBlock.NE(HEAD_INITIAL_VALUE)) { + startPtr = bufferStart(endOfBlock); + while (startPtr.LT(endOfBlock)) { + Address startSlot = startPtr.loadAddress(); + Word startKey = getKey(startSlot); + if (startKey.GT(max)) + max = startKey; + if (startKey.LT(min)) + min = startKey; + startPtr = startPtr.plus(BYTES_IN_ADDRESS); + } + endOfBlock = getPrev(startPtr); + } + + // If max and min are different (not all elements are equal), push the + // start, end and bitmask values on the stack + if (max.GT(min)) { + pushOnStack(getBitMask(max.xor(min)).toAddress()); + pushOnStack(tail); + pushOnStack(bufferStart(tail)); + pushOnStack(startPtr); + pushOnStack(startPtr.minus(BYTES_IN_ADDRESS)); + } + } + + /** + * Push an address on to the stack + * + * @param val The address to be pushed + */ + private void pushOnStack(Address val) { + stackBase.set(stackLoc, val); + stackLoc++; + } + + /** + * Pop an address from the stack + * + * @return The address at the top of the stack, or 0 if stack is empty + */ + private Address popStack() { + if (stackLoc == 0) + return Address.zero(); + stackLoc--; + return stackBase.get(stackLoc); + } + + /** + * Debug routine, used to check if the object buffer is sorted correctly in + * decreasing final reference deletion time + */ + private void checkIfSorted() { + if (VM.VERIFY_ASSERTIONS) { + Address buf, end; + Word prevKey = Word.max(); + end = tail; + buf = bufferStart(end); + while (buf.NE(HEAD_INITIAL_VALUE)) { + // iterate through the block + while (buf.LT(end)) { + Address slot = buf.loadAddress(); + Word key = getKey(slot); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(key.LE(prevKey)); + prevKey = key; + buf = buf.plus(BYTES_IN_ADDRESS); + } + end = getPrev(end); + buf = bufferStart(end); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,91 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This supports unsynchronized pushing and popping of addresses. + * In addition, this can sort the entries currently on the shared stack. + */ + at Uninterruptible public class SortTODAddressStack extends LocalDeque + implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param queue The shared stack to which this stack will append + * its buffers (when full or flushed) and from which it will aquire new + * buffers when it has exhausted its own. + */ + public SortTODAddressStack(SortTODSharedDeque queue) { + super(queue); + } + + /** + * Sort the address on the shared stack. + */ + public final void sort() { + flushLocal(); + ((SortTODSharedDeque) queue).sort(); + } + + /** + * Push an address onto the address stack. + * + * @param addr the address to be pushed onto the address queue + */ + @Inline + public final void push(Address addr) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero()); + checkHeadInsert(1); + uncheckedHeadInsert(addr); + } + + /** + * Pop an address from the address stack, return zero if the stack + * is empty. + * + * @return The next address in the address stack, or zero if the + * stack is empty + */ + @Inline + public final Address pop() { + if (checkDequeue(1)) { + return uncheckedDequeue(); + } else { + return Address.zero(); + } + } + + /** + * Check if the (local and shared) stacks are empty. + * + * @return True if there are no more entries on the local & shared stack, + * false otherwise. + */ + @Inline + public final boolean isEmpty() { + return !checkDequeue(1); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,93 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This supports unsynchronized pushing and popping of object + * references. In addition, this can sort the entries currently on + * the shared stack. + */ + at Uninterruptible public class SortTODObjectReferenceStack extends LocalDeque + implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param queue The shared stack to which this stack will append + * its buffers (when full or flushed) and from which it will aquire new + * buffers when it has exhausted its own. + */ + public SortTODObjectReferenceStack(SortTODSharedDeque queue) { + super(queue); + } + + /** + * Sort the address on the shared stack. + */ + public final void sort() { + flushLocal(); + ((SortTODSharedDeque) queue).sort(); + } + + /** + * Push an address onto the address stack. + * + * @param object the object to be pushed onto the object queue + */ + @Inline + public final void push(ObjectReference object) { + Address addr = object.toAddress(); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero()); + checkHeadInsert(1); + uncheckedHeadInsert(addr); + } + + /** + * Pop an address from the address stack, return zero if the stack + * is empty. + * + * @return The next address in the address stack, or zero if the + * stack is empty + */ + @Inline + public final ObjectReference pop() { + if (checkDequeue(1)) { + return uncheckedDequeue().toObjectReference(); + } else { + return ObjectReference.nullReference(); + } + } + + /** + * Check if the (local and shared) stacks are empty. + * + * @return True if there are no more entries on the local & shared stack, + * false otherwise. + */ + @Inline + public final boolean isEmpty() { + return !checkDequeue(1); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,47 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.policy.RawPageSpace; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class specializes SortSharedQueue to sort objects according to + * their time of death (TOD). + */ + at Uninterruptible +public final class SortTODSharedDeque extends SortSharedDeque { + + /** + * Constructor + * + * @param rps The space from which the instance should obtain buffers. + * @param arity The arity of the data to be enqueued + */ + public SortTODSharedDeque(String name, RawPageSpace rps, int arity) { + super(name, rps, arity); + } + + /** + * Return the sorting key for the object passed as a parameter. + * + * @param obj The address of the object whose key is wanted + * @return The value of the sorting key for this object + */ + protected Word getKey(Address obj) { + return VM.traceInterface.getDeathTime(obj.toObjectReference()); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,235 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Log; +import org.mmtk.utility.TracingConstants; +import org.mmtk.vm.VM; +import org.mmtk.utility.Constants; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This supports unsynchronized enqueuing and dequeuing of tracing data + * and bulk processing of the buffer. + */ + at Uninterruptible public class TraceBuffer extends LocalQueue + implements Constants, TracingConstants { + + /*********************************************************************** + * + * Class based constants + */ + private static final Word TRACE_NEW_RECORD = Word.fromIntSignExtend(3); + private static final Word TRACE_ALLOC_SIZE = Word.fromIntSignExtend(5); +// private static final Word TRACE_ALLOC_NAME = Word.fromIntSignExtend(6); + private static final Word TRACE_ALLOC_FP = Word.fromIntSignExtend(7); + private static final Word TRACE_ALLOC_THREAD = Word.fromIntSignExtend(9); + private static final Word TRACE_TIB_VALUE = Word.fromIntSignExtend(10); + private static final Word TRACE_DEATH_TIME = Word.fromIntSignExtend(11); + private static final Word TRACE_FIELD_TARGET = Word.fromIntSignExtend(12); + private static final Word TRACE_ARRAY_TARGET = Word.fromIntSignExtend(13); + private static final Word TRACE_FIELD_SLOT = Word.fromIntSignExtend(14); + private static final Word TRACE_ARRAY_ELEMENT = Word.fromIntSignExtend(15); + private static final Word TRACE_STATIC_TARGET = Word.fromIntSignExtend(17); + private static final Word TRACE_BOOT_ALLOC_SIZE = Word.fromIntSignExtend(18); + + /* + * Debugging and trace reducing constants + */ + public static final boolean OMIT_ALLOCS=false; + public static final boolean OMIT_UPDATES=false; + public static final boolean OMIT_BOOTALLOCS=false; + public static final boolean OMIT_UNREACHABLES=false; + public static final boolean OMIT_OTHERS=false; + public static final boolean OMIT_OUTPUT=OMIT_ALLOCS && OMIT_UPDATES && + OMIT_OTHERS; + + + /*********************************************************************** + * + * Public methods + */ + + /** + * Constructor + * + * @param pool The shared queue to which this queue will append its + * buffers (when full or flushed) and from which it will aquire new + * buffers when it has exhausted its own. + */ + public TraceBuffer(SharedDeque pool) { + super(pool); + } + + /** + * Push word onto the tracing queue. + * + * @param i The data to be pushed onto the tracing queue + */ + @Inline + public final void push(Word i) { + checkTailInsert(1); + uncheckedTailInsert(i.toAddress()); + } + + /** + * Process the data in the tracing buffer, output information as needed. + */ + public final void process() { + Word traceState = TRACE_NEW_RECORD; + int entriesNotFlushed = 0; + boolean loggedRecord = false; + /* First we must flush any remaining data */ + if (!OMIT_OUTPUT) Log.writeln(); + + /* Process through the entire buffer. */ + while (checkDequeue(1)) { + /* For speed and efficiency, we will actually process the data buffer by + buffer and not by dequeue-ing each entry. */ + while (!bufferOffset(head).isZero()) { + head = head.minus(BYTES_IN_ADDRESS); + Word val = head.loadWord(); + if (traceState.EQ(TRACE_NEW_RECORD)) { + loggedRecord = false; + if (val.EQ(TRACE_GCSTART)) { + if (!OMIT_OTHERS) { + Log.write('G'); + Log.write('C'); + Log.writeln('B', true); + } + } else if (val.EQ(TRACE_GCEND)) { + if (!OMIT_OTHERS) { + Log.write('G'); + Log.write('C'); + Log.writeln('E', true); + } + } else { + traceState = val; + } + } else { + if (traceState.EQ(TRACE_EXACT_ALLOC) || + traceState.EQ(TRACE_ALLOC)) { + if (!OMIT_ALLOCS) { + Log.write((traceState.EQ(TRACE_EXACT_ALLOC)) ? 'A' : 'a'); + Log.write(' '); + Log.write(val); + loggedRecord = true; + } + traceState = TRACE_ALLOC_SIZE; + } else if (traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC) || + traceState.EQ(TRACE_IMMORTAL_ALLOC)) { + if (!OMIT_ALLOCS) { + Log.write((traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC)) ? 'I' : 'i'); + Log.write(' '); + Log.write(val); + loggedRecord = true; + } + traceState = TRACE_ALLOC_SIZE; + } else if (traceState.EQ(TRACE_BOOT_ALLOC)) { + if (!OMIT_BOOTALLOCS) { + Log.write('B'); + Log.write(' '); + Log.write(val); + loggedRecord = true; + } + traceState = TRACE_BOOT_ALLOC_SIZE; + } else if (traceState.EQ(TRACE_DEATH)) { + if (!OMIT_UNREACHABLES) { + Log.write('D'); + Log.write(' '); + Log.write(val); + loggedRecord = true; + } + traceState = TRACE_DEATH_TIME; + } else if (traceState.EQ(TRACE_BOOT_ALLOC_SIZE)) { + if (!OMIT_BOOTALLOCS) + Log.write(val); + traceState = TRACE_NEW_RECORD; + } else if (traceState.EQ(TRACE_ALLOC_SIZE)) { + if (!OMIT_ALLOCS) + Log.write(val); + traceState = TRACE_ALLOC_FP; + } else if (traceState.EQ(TRACE_ALLOC_FP)) { + if (!OMIT_ALLOCS) + Log.write(val); + traceState = TRACE_ALLOC_THREAD; + } else if (traceState.EQ(TRACE_ALLOC_THREAD)) { + if (!OMIT_ALLOCS) + Log.write(val); + traceState = TRACE_NEW_RECORD; + } else if (traceState.EQ(TRACE_TIB_SET)) { + if (!OMIT_UPDATES) { + Log.write('T'); + Log.write(' '); + Log.write(val); + loggedRecord = true; + } + traceState = TRACE_TIB_VALUE; + } else if (traceState.EQ(TRACE_STATIC_SET)) { + if (!OMIT_UPDATES) { + Log.write('S'); + Log.write(' '); + Log.write(val); + loggedRecord = true; + } + traceState = TRACE_STATIC_TARGET; + } else if (traceState.EQ(TRACE_TIB_VALUE) || + traceState.EQ(TRACE_STATIC_TARGET)) { + if (!OMIT_UPDATES) + Log.write(val); + traceState = TRACE_NEW_RECORD; + } else if (traceState.EQ(TRACE_DEATH_TIME)) { + if (!OMIT_UNREACHABLES) + Log.write(val); + traceState = TRACE_NEW_RECORD; + } else if (traceState.EQ(TRACE_FIELD_SET) || + traceState.EQ(TRACE_ARRAY_SET)) { + if (!OMIT_UPDATES) { + Log.write('U'); + Log.write(' '); + Log.write(val); + loggedRecord = true; + } + traceState = TRACE_FIELD_SLOT; + } else if (traceState.EQ(TRACE_FIELD_TARGET) || + traceState.EQ(TRACE_ARRAY_TARGET)) { + if (!OMIT_UPDATES) + Log.write(val); + traceState = TRACE_NEW_RECORD; + } else if (traceState.EQ(TRACE_FIELD_SLOT) || + traceState.EQ(TRACE_ARRAY_ELEMENT)) { + if (!OMIT_UPDATES) + Log.write(val); + traceState = TRACE_FIELD_TARGET; + } else { + VM.assertions.fail("Cannot understand directive!\n"); + } + if (traceState.EQ(TRACE_NEW_RECORD) && loggedRecord) { + entriesNotFlushed++; + Log.writeln(); + } else if (loggedRecord) { + Log.write(' '); + } + } + if (entriesNotFlushed == 10) { + if (!OMIT_OUTPUT) + Log.flush(); + entriesNotFlushed = 0; + } + } + } + resetLocal(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,51 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.deque; + +import org.mmtk.utility.Constants; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This supports unsynchronized insertion of write buffer values. + */ + at Uninterruptible public class WriteBuffer extends LocalSSB + implements Constants { + + /**************************************************************************** + * + * Public instance methods + */ + + /** + * Constructor + * + * @param queue The shared queue to which this local ssb will append + * its buffers (when full or flushed). + */ + public WriteBuffer(SharedDeque queue) { + super(queue); + } + + /** + * Insert a value to be remembered into the write buffer. + * + * @param addr the value to be inserted into the write buffer + */ + @NoInline + public final void insert(Address addr) { + checkTailInsert(1); + uncheckedTailInsert(addr); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,100 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * Color.java + * + * Cut-down implementation of java.awt.Color sufficient to provide + * the server side (Stream) with colours + */ + at Uninterruptible public class Color { + + /** + * Some gcspy standard colours (taken from gcspy_color_db.c). + */ + public static final Color Black = new Color(0, 0, 0); + public static final Color Blue = new Color(0, 0, 255); + public static final Color Cyan = new Color(0, 255, 255); + public static final Color DarkGray = new Color(64, 64, 64); + public static final Color Gray = new Color(128, 128, 128); + public static final Color Green = new Color(0, 255, 0); + public static final Color LightGray = new Color(192, 192, 192); + public static final Color Magenta = new Color(255, 0, 255); + public static final Color MidGray = new Color(160, 160, 160); + public static final Color NavyBlue = new Color(0, 0, 150); + public static final Color OffWhite = new Color(230, 230, 230); + public static final Color Orange = new Color(255, 200, 0); + public static final Color Pink = new Color(255, 175, 175); + public static final Color Red = new Color(255, 0, 0); + public static final Color White = new Color(255, 255, 255); + public static final Color Yellow = new Color(255, 255, 0); + + private short r; // red component + private short g; // green component + private short b; // blue component + + /** + * Constructor for a simple RGB colour model. + * + * @param r red component + * @param g green component + * @param b blue component + */ + public Color(short r, short g, short b) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert((0 <= r) && (r <= 255) && + (0 <= g) && (g <= 255) && + (0 <= b) && (b <= 255)); + this.r = r; + this.g = g; + this.b = b; + } + + /** + * Constructor for a simple RGB colour model. + * + * @param r red component + * @param g green component + * @param b blue component + */ + private Color(int r, int g, int b) { + this((short) r, (short) g, (short) b); + } + + + /** + * Red component + * + * @return the red component + */ + public short getRed() { return r; } + + /** + * Green component + * + * @return the green component + */ + public short getGreen() { return g; } + + /** + * Blue component + * + * @return the blue component + */ + public short getBlue() { return b; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,95 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy; + +import org.mmtk.utility.Log; +import org.mmtk.utility.options.*; +import org.mmtk.vm.VM; +import org.mmtk.vm.gcspy.ServerInterpreter; +import org.mmtk.vm.gcspy.Util; + +import org.vmmagic.pragma.*; + +/** + * This class implements collector-independent GCspy functionality to start + * the GCspy server. It handles command-line parameters for port number, + * whether the VM should wait for a GCspy client to connect, and tile size. + * Most importantly, it calls the Plan's startGCspyServer method which + * creates a new ServerInterpreter, and adds events and space drivers. + */ + at Uninterruptible public class GCspy { + + /**************************************************************************** + * + * Class variables + */ + + public static final Util util = VM.newGCspyUtil(); + public static final ServerInterpreter server = VM.newGCspyServerInterpreter(); + + /**************************************************************************** + * + * Initialization + */ + + @Interruptible + public static void createOptions() { + Options.gcspyPort = new GCspyPort(); + Options.gcspyWait = new GCspyWait(); + Options.gcspyTileSize = new GCspyTileSize(); + } + + /** + * The boot method is called by the runtime immediately after + * command-line arguments are available. Note that allocation must + * be supported prior to this point because the runtime + * infrastructure may require allocation in order to parse the + * command line arguments. + */ + public static void postBoot() { } + + /** + * Get the number of the port that GCspy communicates on + * + * @return the GCspy port number + */ + public static int getGCspyPort() { + return Options.gcspyPort.getValue(); + } + + /** + * Should the VM wait for GCspy to connect? + * + * @return whether the VM should wait for the visualiser to connect + */ + public static boolean getGCspyWait() { + return Options.gcspyWait.getValue(); + } + + /** + * Start the GCspy server. + * WARNING: allocates memory indirectly + */ + @Interruptible + public static void startGCspyServer() { + int port = getGCspyPort(); + Log.write("GCspy.startGCspyServer, port="); Log.write(port); + Log.write(", wait="); + Log.writeln(getGCspyWait()); + if (port > 0) { + VM.activePlan.global().startGCspyServer(port, getGCspyWait()); + //Log.writeln("gcspy thread booted"); + } + } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,42 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy; + +import org.mmtk.utility.gcspy.drivers.AbstractDriver; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class is only necessary because we cannot implement + * org.mmtk.utility.alloc.LinearScan as an interface since the invokeinterface + * bytecode is forbidden in uninterruptible code. + */ + at Uninterruptible public class LinearScan extends org.mmtk.utility.alloc.LinearScan { + + private final AbstractDriver driver; + + /** + * Create a new scanner. + * @param d The GCspy driver that provides the callback. + */ + public LinearScan(AbstractDriver d) { driver = d; } + + /** + * Scan an object. The object reference is passed to the scan method of the + * GCspy driver registered with this scanner. + * @param obj The object to scan. + */ + public void scan(ObjectReference obj) { driver.scan(obj); } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,60 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy; + +/** + * This interface provides constants used by the GCspy framweork. + * These must correspond with values in gcspy_stream.h + * Presentation + * + + + + + + +
PRESENTATION_PLAIN presented as is
PRESENTATION_PLUS as max+ if value exceeds max else as is
PRESENTATION_MAX_VAR ditto but takes max value from a specified stream
PRESENTATION_PERCENT as value (percent)
PRESENTATION_PERCENT_VARditto but takes max value from a specified stream
PRESENTATION_ENUM chooses from an enumeration
+ Paint style + + + +
PAINT_STYLE_PLAIN Paints as is
PAINT_STYLE_ZERO ditto but treats zero values specially
+ Data types + + + + +
BYTE_TYPE stream of bytes
SHORT_TYPE stream of shorts
INT_TYPE stream of ints
+ * StreamConstants + */ + +public interface StreamConstants { + + int NAME_LEN = 40; + int PRESENTATION_PLAIN = 0; + int PRESENTATION_PLUS = 1; + int PRESENTATION_MAX_VAR = 2; + int PRESENTATION_PERCENT = 3; + int PRESENTATION_PERCENT_VAR = 4; + int PRESENTATION_ENUM = 5; + + int PAINT_STYLE_PLAIN = 0; + int PAINT_STYLE_ZERO = 1; + + int BYTE_TYPE = 0; + int SHORT_TYPE = 1; + int INT_TYPE = 2; + + int ENUM_MAX_LEN = 20; + int ENUM_MAX_NUM = 5; +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,236 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy; + +import org.mmtk.utility.Log; +import org.mmtk.vm.gcspy.Util; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + + +/** + * This class is an abstraction of a contiguous region of a Space. For + * example, a semispace collector might choose to model the heap as a + * single Space, but within that Space it could model each semispace by + * a Subspace.

+ * Subspace provides a number of useful facilities to many drivers, and + * is useful even if the Space comprises just a single contiguous region.

+ * + * A subspace keeps track of the start and end address of the region, + * the index of its first block, the size of the blocks in this space, + * and the number of blocks in this subspace. + */ + at Uninterruptible public class Subspace { + + private Address start_; // The Subspace spans the address range [start_, end_) + private Address end_; + private int firstIndex_; // The index of the block in which start_ lies + private int blockSize_; // The block size + private int blockNum_; // The number of blocks in this space + + private static final boolean DEBUG = false; + + /** + * Create a new subspace + * + * @param start The address of the start of the subspace + * @param end The address of the end of the subspace + * @param firstIndex The index of the first block of the subspace + * @param blockSize The size of blocks in this space + * @param blockNum The number of blocks in this subspace + */ + public Subspace(Address start, + Address end, + int firstIndex, + int blockSize, + int blockNum) { + reset(start, end, firstIndex, blockSize, blockNum); + } + + + //------------------Methods to reset a subspace---------------------- + + /** + * Reset a subspace. + * + * @param start The address of the start of the subspace + * @param end The address of the end of the subspace + * @param firstIndex The index of the first block of the subspace + * @param blockSize The size of blocks in this subspace + * @param blockNum The number of blocks in this subspace + */ + private void reset(Address start, + Address end, + int firstIndex, + int blockSize, + int blockNum) { + //TODO sanity check on addresses and block size and number + reset(start, end, firstIndex, blockNum); + blockSize_ = blockSize; + + if (DEBUG) dump(); + } + + /** + * Reset a new subspace + * + * @param start The address of the start of the subspace + * @param end The address of the end of the subspace + * @param firstIndex The index of the first block of the subspace + * @param blockNum The number of blocks in this subspace + */ + public void reset(Address start, + Address end, + int firstIndex, + int blockNum) { + start_ = start; + end_ = end; + firstIndex_ = firstIndex; + blockNum_ = blockNum; + } + + /** + * Reset a new subspace. + * + * @param start The address of the start of the subspace + * @param end The address of the end of the subspace + * @param blockNum The number of blocks in this subspace + */ + public void reset(Address start, Address end, int blockNum) { + start_ = start; + end_ = end; + blockNum_ = blockNum; + } + + /** + * Reset a new subspace. + * + * @param firstIndex The index of the first block of the subspace + * @param blockNum The number of blocks in this subspace + */ + public void reset(int firstIndex, int blockNum) { + firstIndex_ = firstIndex; + blockNum_ = blockNum; + } + + + //----------------Facilities to query a subspace----------------- + + /** + * Is an index in the range of this subspace? + * + * @param index The index of the block + * @return true if this block lies in this subspace + */ + public boolean indexInRange(int index) { + return index >= firstIndex_ && + index < firstIndex_ + blockNum_; + } + + /** + * Is address in the range of this subspace? + * + * @param addr An address + * @return true if this address is in a block in this subspace + */ + public boolean addressInRange(Address addr) { + return addr.GE(start_) && addr.LT(end_); + } + + + /** + * Get the block index from an address + * + * @param addr The address + * @return The index of the block holding this address + */ + public int getIndex(Address addr) { + if (DEBUG) { + Log.write("start_ ", start_); + Log.write(" end_ ", end_); + Log.write(" blockSize_ ", blockSize_); + Log.write(" firstIndex_ ", firstIndex_); + Log.write(" + ", addr.diff(start_).toInt() / blockSize_); + Log.writeln(" addr ", addr); + } + return firstIndex_ + addr.diff(start_).toInt() / blockSize_; + } + + /** + * Get the address of start of block from its index + * + * @param index The index of the block + * @return The address of the start of the block + */ + public Address getAddress(int index) { + return start_.plus(index - firstIndex_ * blockSize_); + } + + //--------------Accessors------------------------- + + /** + * Get the start of the subspace + * @return The start of this subspace + */ + public Address getStart() { return start_; } + + /** + * Get the end of this subspace + * @return The address of the end of this subspace + */ + public Address getEnd() { return end_; } + + /** + * Get the first index of subspace + * @return the firstIndex of this subspace + */ + public int getFirstIndex() { return firstIndex_; } + + /** + * Get the blocksize for this subspace + * @return The size of a tile + */ + public int getBlockSize() { return blockSize_; } + + /** + * Get the number of tiles in this subspace + * @return The number of tiles in this subspace + */ + public int getBlockNum() { return blockNum_; } + + /** + * Calculate the space remaining in a block after this address + * + * @param addr the Address + * @return the remainder + */ + public int spaceRemaining(Address addr) { + int nextIndex = getIndex(addr) + 1; + Address nextTile = start_.plus(blockSize_ * (nextIndex - firstIndex_)); + return nextTile.diff(addr).toInt(); + } + + /** + * Dump a representation of the subspace + */ + private void dump() { + Log.write("GCspy Subspace: "); + Util.dumpRange(start_, end_); + Log.writeln("\n -- firstIndex=", firstIndex_); + Log.writeln(" -- blockNum=", blockNum_); + } +} + + Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,502 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy.drivers; + +import org.mmtk.policy.Space; +import org.mmtk.utility.Log; +import org.mmtk.utility.gcspy.GCspy; +import org.mmtk.utility.gcspy.Subspace; +import org.mmtk.vm.gcspy.ServerSpace; +import org.mmtk.vm.gcspy.ServerInterpreter; +import org.mmtk.vm.gcspy.Stream; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Abstract GCspy driver for MMTk collectors. + * + * This class implements for the MMTk a base driver for a GCspy space. + * All drivers for GCspy spaces should inherit from this class. + */ + at Uninterruptible +public abstract class AbstractDriver { + + /**************************************************************************** + * + * Class variables + */ + + // Controls used for tile presentation + /** The tile is used */ + protected static final byte CONTROL_USED = 1; + /** The tile is a background tile */ + protected static final byte CONTROL_BACKGROUND = 2; + /** The tile is unused */ + protected static final byte CONTROL_UNUSED = 4; + /** The tile is a separator */ + protected static final byte CONTROL_SEPARATOR = 8; + /** The tile is a link */ + protected static final byte CONTROL_LINK = 16; + + + private static final int MAX_STREAMS = 64; // Max number of streams + + private static final boolean DEBUG = false; + protected String myClass; // used in debugging messages + + + /**************************************************************************** + * + * Instance variables + */ + + /** The owning GCspy server */ + protected final ServerInterpreter server; + /** The name of the GCspy space driver */ + protected final String name; + /** The GCspy space abstraction */ + protected final ServerSpace serverSpace; + /** The MMTK space */ + protected final Space mmtkSpace; + /** The GCspy space's block size */ + protected int blockSize; + /** The maximum number of tiles in this GCspy space */ + protected int maxTileNum; + /** This space's streams */ + protected Stream[] streams; + /** control values for tiles in this space */ + protected byte[] control; + /** Has this space changed? */ + protected boolean changed = true; + + + /** + * Create a new driver for this collector. + * + * @param server The ServerInterpreter that owns this GCspy space. + * @param name The name of this driver. + * @param mmtkSpace The MMTk space represented by this driver. + * @param blockSize The tile size. + * @param mainSpace Is this the main space? + */ + public AbstractDriver(ServerInterpreter server, + String name, + Space mmtkSpace, + int blockSize, + boolean mainSpace) { + this.server = server; + this.name = name; + this.mmtkSpace = mmtkSpace; + this.blockSize = blockSize; + myClass = getClass().getName(); + maxTileNum = countTileNum(mmtkSpace.getExtent(), blockSize); + control = (byte[])GCspy.util.createDataArray(new byte[0], maxTileNum); + // to avoid allocation during GC we preallocate the streams array + streams = new Stream[MAX_STREAMS]; + serverSpace = createServerSpace(server, name, maxTileNum, mainSpace); + } + + /** + * Create a subspace for this space. + * Subspace provide useful facilities for contiguous spaces, even if + * a space contains only one. + * @param mmtkSpace The MMTk space + */ + @Interruptible + protected Subspace createSubspace(Space mmtkSpace) { + Address start = mmtkSpace.getStart(); + return new Subspace(start, start, 0, blockSize, 0); + } + + /** + * Create a new GCspy ServerSpace and add it to the ServerInterpreter. + * @param server the GCspy ServerInterpreter. + * @param spaceName The name of this driver. + * @param maxTileNum the maximum number of tiles in this space. + * @param mainSpace Is this the main space? + */ + @Interruptible + protected ServerSpace createServerSpace(ServerInterpreter server, + String spaceName, + int maxTileNum, + boolean mainSpace) { + // Set the block label + String tmp = "Block Size: " + ((blockSize < 1024) ? + blockSize + " bytes\n": + (blockSize / 1024) + " Kbytes\n"); + + // Create a single GCspy Space + return VM.newGCspyServerSpace(server, // the server + spaceName, // space name + getDriverName(), // driver (space) name + "Block ", // space title + tmp, // block info + maxTileNum, // number of tiles + "UNUSED", // the label for unused blocks + mainSpace); // main space + } + + /** + * Get the name of this driver type. + * @return The name of this driver. + */ + protected abstract String getDriverName(); + + /** + * Get the maximum number of tiles in this space. + * @return the maximum number of tiles in the space. + */ + public int getMaxTileNum() { + return maxTileNum; + } + + /** + * The GCspy space managed by this driver. + * @return the GCspy server space. + */ + public ServerSpace getServerSpace() { return serverSpace; } + + /** + * Add a stream to the driver. This also sets the stream's id + * (unique for this space). + * @param stream The stream + * @exception IndexOutOfBoundsException if more than MAX_STREAMS are added + */ + @Interruptible + public void addStream(Stream stream) { + int id = 0; + while (id < MAX_STREAMS) { + if (streams[id] == null) { + streams[id] = stream; + if (DEBUG) { Log.write("Adding stream with id="); Log.writeln(id); } + Address stream_ = serverSpace.addStream(id); + stream.setStream(id, stream_); + return; + } + id++; + } + throw new IndexOutOfBoundsException("Too many streams added to driver "+name); + } + + /** + * Count number of tiles in an address range. + * @param start The start of the range. + * @param end The end of the range. + * @param tileSize The size of each tile. + * @return The number of tiles in this range. + */ + protected int countTileNum(Address start, Address end, int tileSize) { + if (end.LE(start)) return 0; + int diff = end.diff(start).toInt(); + return countTileNum(diff, tileSize); + } + + /** + * Count number of tiles in an address range. + * @param extent The extent of the range. + * @param tileSize The size of each tile. + * @return The number of tiles in this range. + */ + protected int countTileNum(Extent extent, int tileSize) { + int diff = extent.toInt(); + return countTileNum(diff, tileSize); + } + + private int countTileNum(int diff, int tileSize) { + int tiles = diff / tileSize; + if ((diff % tileSize) != 0) + ++tiles; + return tiles; + } + + /** + * Indicate the limits of a space. + * + * @param start the Address of the start of the space. + * @param end the Address of the end of the space. + */ + public void setRange(Address start, Address end) {} + + /** + * Indicate the limits of a space. + * + * @param start the Address of the start of the space. + * @param extent the extent of the space. + */ + public void setRange(Address start, Extent extent) { + setRange(start, start.plus(extent)); + } + + /** + * Setup the tile names in a subspace. Tile names are typically + * address ranges but may be anything (e.g. a size class if the + * space is a segregated free-list manager, or a class name if the + * space represents the class instances loaded). + * + * @param subspace the Subspace + * @param numTiles the number of tiles to name + */ + protected void setTilenames(Subspace subspace, int numTiles) { + Address start = subspace.getStart(); + int first = subspace.getFirstIndex(); + int bs = subspace.getBlockSize(); + + for (int i = 0; i < numTiles; ++i) { + if (subspace.indexInRange(i)) + serverSpace.setTilename(i, start.plus((i - first) * bs), + start.plus((i + 1 - first) * bs)); + } + } + + /** + * The "typical" maximum number of objects in each tile. + * @param blockSize The size of a tile + * @return The maximum number of objects in a tile + */ + public int maxObjectsPerBlock(int blockSize) { + // Maybe a misuse of ServerInterpreter but it's a convenient + // VM-dependent class + return blockSize / GCspy.server.computeHeaderSize(); + } + + /** + * Is the server connected to a GCspy client? + * @param event The current event + */ + public boolean isConnected(int event) { + return server.isConnected(event); + } + + /** + * Reset the statistics for a space. + * In this base driver, we simply note that the data has changed. + */ + protected void resetData() { changed = true; } + + /** + * Scan an object found at a location. + * Collectors typically call this method to update GCspy statistics. + * The driver may or may not accumulate values found, depending on + * the value of total. + * @param obj the reference to the object found + * @param total Whether to total the statistics + */ + public void scan(ObjectReference obj, boolean total) {} + + /** + * Scan an object found at a location. + * Collectors typically call this method to update GCspy statistics + * The driver will accumulate values found. + * @param obj the reference to the object found + */ + public void scan(ObjectReference obj) { scan(obj, true); } + + /** + * Scan an object found at a location. + * Collectors typically call this method to update GCspy statistics. + * The driver may or may not accumulate values found, depending on + * the value of total. + * @param obj the reference to the object found + * @param total Whether to total the statistics + */ + public void scan(Address obj, boolean total) {} + + /** + * Scan an object found at a location. + * Collectors typically call this method to update GCspy statistics + * The driver will accumulate values found. + * @param obj the reference to the object found + */ + public void scan(Address obj) {} + + /** + * Handle a direct reference from the immortal space.

+ * This is an empty implementation. Subclasses may override this method + * to increment their refFromImmortal Stream. + * + * @param addr The Address + * @return true if the given Address is in this subspace. Always false here. + */ + public boolean handleReferenceFromImmortalSpace(Address addr) { + return false; + } + + /** + * Set space info. + * This simply reports the size of the current space. + * Drivers that want to send something more complex than + * "Current Size: size\n" + * must override this method. + * + * @param size the size of the space + */ + protected void setSpaceInfo(Offset size) { + // - sprintf(tmp, "Current Size: %s\n", gcspy_formatSize(size)); + Address tmp = GCspy.util.formatSize("Current Size: %s\n", 128, size.toInt()); + serverSpace.spaceInfo(tmp); + GCspy.util.free(tmp); + } + + + /**************************************************************************** + * + * Control values + */ + + /** + * Is a tile used? + * @param val the control value. + * @return true if the tile is used + */ + protected static boolean controlIsUsed(byte val) { + return (val & CONTROL_USED) != 0; + } + + /** + * Is a tile a background pseudo-tile? + * @param val the control value. + * @return true if the tile is a background tile + */ + protected static boolean controlIsBackground(byte val) { + return (val & CONTROL_BACKGROUND) != 0; + } + + /** + * Is a tile unused? + * @param val the control value. + * @return true if the tile is unused + */ + protected static boolean controlIsUnused(byte val) { + return (val & CONTROL_UNUSED) != 0; + } + + /** + * Is this a separator? + * @param val the control value. + * @return true if this is a separator + */ + protected static boolean controlIsSeparator(byte val) { + return (val & CONTROL_SEPARATOR) != 0; + } + + /** + * Initialise the value of a control. + * @param index The index of the tile. + * @param value The new value of the control + */ + protected void initControl(int index, byte value) { + control[index] = value; + } + + /** + * Add a control to the tile + * @param index The index of the tile. + * @param value The control to add. + */ + protected void addControl(int index, byte value) { + control[index] |= value; + } + + /** Set the control + * @param value The value to set + */ + protected void setControl(int index, byte value) { + control[index] &= value; + } + + /** + * Get the controls for a tile. + * @param index The index of the tile. + * @return The value of the controls + */ + public byte getControl(int index) { + return control[index]; + } + + /** + * Initialise control values in all tiles + */ + protected void initControls() { + for (int index = 0; index < control.length; ++index) { + initControl(index, CONTROL_USED); + } + } + + /** + * Set the control value in each tile in a region. + * @param tag The control tag. + * @param start The start index of the region. + * @param len The number of tiles in the region. + */ + protected void controlValues(byte tag, int start, int len) { + if (DEBUG) { + Log.write("AbstractDriver.controlValues for space "); + Log.write(name); + Log.write(", control length=", control.length); + Log.write(" writing controls from ", start); + Log.writeln(" to ", start + len); + } + changed = true; + for (int i = start; i < (start+len); ++i) { + // Cannot be both USED and UNUSED or BACKGROUND + if (controlIsBackground(tag) || controlIsUnused(tag)) + setControl(i, (byte)~CONTROL_USED); + else if (controlIsUsed(tag)) + setControl(i, (byte)~CONTROL_UNUSED); + addControl(i, tag); + } + } + + /** + * Transmit the streams for this space. A driver will typically + *

    + *
  1. Determine whether a GCspy client is connected and interested in + * this event, e.g. + *
    server.isConnected(event)
    + *
  2. Setup the summaries for each stream, e.g. + *
    stream.setSummary(values...);
    + *
  3. Setup the control information for each tile. e.g. + *
    controlValues(CONTROL_USED, start, numBlocks);
    + *
    controlValues(CONTROL_UNUSED, end, remainingBlocks);
    + *
  4. Set up the space information, e.g. + *
    setSpace(info);
    + *
  5. Send the data for all streams, e.g. + *
    send(event, numTiles);
    + * Note that AbstractDriver.send takes care of sending the information + * for all streams (including control data). + * + * @param event The event + */ + public abstract void transmit(int event); + + /** + * Send all the streams for this space if it has changed. + * Assume that the data has been gathered and that summary info + * and control values have been set before this is called. + * + * @param event the event + * @param numTiles the number of blocks in this space + */ + protected void send(int event, int numTiles) { + if (changed) { + serverSpace.startCommunication(); + for (int i = 0; i < MAX_STREAMS; i++) + if (streams[i] != null) + streams[i].send(event, numTiles); + serverSpace.sendControls(this, numTiles); + serverSpace.endCommunication(); + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,144 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy.drivers; + +import org.mmtk.policy.Space; + +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.vm.VM; +import org.mmtk.vm.gcspy.ShortStream; + +import org.mmtk.utility.Log; +import org.mmtk.vm.gcspy.ServerInterpreter; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * GCspy driver for the MMTk generational immortal space. + * Additional Stream for remset references. + * This class extends ImmortalSpaceDriver, a simple driver for + * the contiguous MMTk ImmortalSpace. + */ + at Uninterruptible public class GenImmortalSpaceDriver extends ImmortalSpaceDriver { + + private static final boolean DEBUG = false; + + // The Stream for newly promoted objects + protected ShortStream remsetStream; + // Statistics for remset references + protected int totalRemset = 0; + + + /** + * Create a new driver for a generational immortal space. + * + * @param server The GCspy ServerInterpreter + * @param spaceName The name of this GCspy space + * @param mmtkSpace The MMTk space + * @param blockSize The tile size + * @param mainSpace Is this the main space? + */ + public GenImmortalSpaceDriver( + ServerInterpreter server, + String spaceName, + Space mmtkSpace, + int blockSize, + boolean mainSpace) { + + super(server, spaceName, mmtkSpace, blockSize, mainSpace); + + // create additional stream + remsetStream = createRemsetStream(); + + if (DEBUG) { + Log.write("GenImmortalSpaceDriver for "); Log.write(spaceName); + Log.write(", blocksize="); Log.write(blockSize); + Log.write(", start="); Log.write(mmtkSpace.getStart()); + Log.write(", extent="); Log.write(mmtkSpace.getExtent()); + Log.write(", maxTileNum="); Log.writeln(maxTileNum); + } + + resetData(); + } + + /** + * Get the name of this driver type. + * @return The name, "MMTk GenImmortalSpaceDriver" for this driver. + */ + protected String getDriverName() { + return "MMTk GenImmortalSpaceDriver"; + } + + /** + * Heelper methods to create the additional streams + */ + @Interruptible + private ShortStream createRemsetStream() { + return VM.newGCspyShortStream( + this, + "Remembered set stream", + (short)0, + // Say, typical size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "Remset references: ", + " references", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Cyan, + true); + } + + /** + * Setup summaries part of the transmit method.

    + * Overrides method in superclass to handle additional Stream. + */ + protected void setupSummaries() { + super.setupSummaries(); + remsetStream.setSummary(totalRemset); + } + + /** + * Handle a remset address + * + * @param addr Remset Address + * @return true if the given Address is in this subspace. + */ + public boolean handleRemsetAddress(Address addr) { + if(subspace.addressInRange(addr)) { + // increment tile + int index = subspace.getIndex(addr); + remsetStream.increment(index, (short)1); + // increment summary + totalRemset++; + return true; + } else { + return false; + } + } + + /** + * Reset the remset Stream + * The remset Stream has to be reset seperately because we do not + * gather data in the usual way using scan(). + */ + public void resetRemsetStream() { + remsetStream.resetData(); + totalRemset = 0; + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,132 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy.drivers; + +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.vm.VM; +import org.mmtk.vm.gcspy.ShortStream; +import org.mmtk.vm.gcspy.ServerInterpreter; + +import org.mmtk.policy.LargeObjectSpace; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + +/** + * This class extends a simple driver for the MMTk LargeObjectSpace + * for Generational Collectors. + */ + at Uninterruptible public class GenLOSDriver extends TreadmillDriver { + + private static final boolean DEBUG = false; + + // The additional remset stream + protected ShortStream remsetStream; + // Additional overall statistic + protected int totalRemset = 0; // total of remset Addresses + + + /** + * Create a new driver for this collector + * + * @param server The name of the GCspy server that owns this space + * @param spaceName The name of this driver + * @param lospace the large object space for this allocator + * @param blockSize The tile size + * @param threshold the size threshold of the LOS + * @param mainSpace Is this the main space? + */ + public GenLOSDriver(ServerInterpreter server, + String spaceName, + LargeObjectSpace lospace, + int blockSize, + int threshold, + boolean mainSpace) { + //TODO blocksize should be a multiple of treadmill granularity + super(server, spaceName, lospace, blockSize, threshold, mainSpace); + // create remset stream + remsetStream = createRemsetStream(); + // Initialise the statistics + resetData(); + } + + /** + * Get the name of this driver type. + * @return The name, "MMTk GenLOSDriver" for this driver. + */ + protected String getDriverName() { + return "MMTk GenLOSDriver"; + } + + // private creator methods for the streams + @Interruptible + private ShortStream createRemsetStream() { + return VM.newGCspyShortStream( + this, + "Remembered set stream", + (short)0, + // Say, typical size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "Remset references: ", + " references", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Cyan, + true); + } + + /** + * Setup summaries part of the transmit method.

    + * Overrides transmitSetupSummaries of superclass to + * handle additional streams. + */ + protected void setupSummaries() { + super.setupSummaries(); + remsetStream.setSummary(totalRemset); + } + + /** + * Handle a remset address. + * + * @param addr Remset Address + * @return true if the given Address is in this subspace. + */ + public boolean handleRemsetAddress(Address addr) { + if(subspace.addressInRange(addr)) { + // increment tile + int index = subspace.getIndex(addr); + remsetStream.increment(index, (short)1); + // increment summary + this.totalRemset++; + return true; + } else { + return false; + } + } + + /** + * Reset the remset Stream.

    + * The remset Stream has to be reset seperately because we do not + * gather data in the usual way using scan(). + */ + public void resetRemsetStream() { + remsetStream.resetData(); + totalRemset = 0; + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,123 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy.drivers; + +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.policy.Space; +import org.mmtk.utility.Log; +import org.mmtk.vm.gcspy.ServerInterpreter; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * GCspy driver for the contiguous MMTk ImmortalSpace. + * Adds features for the Immortal space. + *

    + * + * This class extends LinearSpaceDriver, a simple driver for contiguous MMTk spaces + * such as CopySpace and ImmortalSpace. + */ + at Uninterruptible public class ImmortalSpaceDriver extends LinearSpaceDriver { + + private static final boolean DEBUG = false; + + // Instance variables + private AbstractDriver[] registeredDrivers; + private ImmortalSpaceDriver.Closure closure; + + /** + * Create a new driver for an immortal Contiguous MMTk space. + * + * @param server The GCspy ServerInterpreter + * @param spaceName The name of this GCspy space + * @param mmtkSpace The MMTk space + * @param blockSize The tile size + * @param mainSpace Is this the main space? + */ + public ImmortalSpaceDriver( + ServerInterpreter server, + String spaceName, + Space mmtkSpace, + int blockSize, + boolean mainSpace) { + + super(server, spaceName, mmtkSpace, blockSize, mainSpace); + + if (DEBUG) { + Log.write("ImmortalSpaceDriver for "); Log.write(spaceName); + Log.write(", blocksize="); Log.write(blockSize); + Log.write(", start="); Log.write(mmtkSpace.getStart()); + Log.write(", extent="); Log.write(mmtkSpace.getExtent()); + Log.write(", maxTileNum="); Log.writeln(maxTileNum); + } + + // initially no registered drivers for reference notification + registeredDrivers = new AbstractDriver[0]; + + closure = new ImmortalSpaceDriver.Closure(); + } + + /** + * Get the name of this driver type. + * @return The name, "MMTk ImmortalSpaceDriver" for this driver. + */ + protected String getDriverName() { + return "MMTk ImmortalSpaceDriver"; + } + + /** + * Update the tile statistics.
    + * This method overrides scan iin its superclass to + * add immortal space features. + * + * @param object The current object + * @param total Whether to accumulate the values + */ + public void scan(ObjectReference object, boolean total) { + Address addr = object.toAddress(); + + if (subspace.addressInRange(addr)) { + VM.scanning.scanObject(closure, object); + super.scan(object, total); + } + } + + /** + * Register a set of AbstractDriver instances to be notified about direct references. + * + * @param drivers The array of driver objects. + */ + public void registerDriversForReferenceNotification(AbstractDriver[] drivers) { + this.registeredDrivers = drivers; + } + + /** + * Used to visit the edges in the immortal object. + */ + @Uninterruptible + private class Closure extends TransitiveClosure { + /** + * Process an edge. + */ + public void processEdge(ObjectReference source, Address slot) { + // Address in Range, locate references + Address target = slot.loadAddress(); + // notify registered drivers + for (int j = 0; j < registeredDrivers.length; j++) { + registeredDrivers[j].handleReferenceFromImmortalSpace(target); + } + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,508 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy.drivers; + +import org.mmtk.policy.Space; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.LinearScan; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.utility.gcspy.Subspace; +import org.mmtk.vm.gcspy.IntStream; +import org.mmtk.vm.gcspy.ShortStream; + +import org.mmtk.utility.Log; +import org.mmtk.vm.gcspy.ServerInterpreter; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * GCspy driver for the MMTk ContigousSpace. + * + * This class implements a simple driver for contiguous MMTk spaces + * such as CopySpace and ImmortalSpace. + */ + at Uninterruptible public class LinearSpaceDriver extends AbstractDriver { + + // The GCspy streams + protected IntStream scalarUsedSpaceStream; + protected IntStream arrayUsedSpaceStream; + protected ShortStream scalarObjectsStream; + protected ShortStream arrayObjectsStream; + protected ShortStream arrayPrimitiveStream; + protected ShortStream rootsStream; + protected ShortStream refFromImmortalStream; + + protected Subspace subspace; // A subspace for all of this space + protected int allTileNum; // total number of tiles + + // Overall statistics + protected int totalScalarObjects = 0; // total number of objects allocated + protected int totalArrayObjects = 0; + protected int totalPrimitives = 0; + protected int totalScalarUsedSpace = 0; // total space used + protected int totalArrayUsedSpace = 0; + protected int totalRoots = 0; + protected int totalRefFromImmortal = 0; + + private final LinearScan scanner; // A scanner to trace objects + + // Debugging + protected Address lastAddress = Address.zero(); + protected int lastSize = 0; + private static final boolean DEBUG = false; + + + /** + * Create a new driver for a contiguous MMTk space. + * + * @param server The GCspy ServerInterpreter + * @param spaceName The name of this GCspy space + * @param mmtkSpace The MMTk space + * @param blockSize The tile size + * @param mainSpace Is this the main space? + */ + public LinearSpaceDriver(ServerInterpreter server, + String spaceName, + Space mmtkSpace, + int blockSize, + boolean mainSpace) { + + super(server, spaceName, mmtkSpace, blockSize, mainSpace); + + if (DEBUG) { + Log.write("LinearSpaceDriver for "); Log.write(spaceName); + Log.write(", blocksize="); Log.write(blockSize); + Log.write(", start="); Log.write(mmtkSpace.getStart()); + Log.write(", extent="); Log.write(mmtkSpace.getExtent()); + Log.write(", maxTileNum="); Log.writeln(maxTileNum); + } + + // Initialise a subspace and 4 Streams + subspace = createSubspace(mmtkSpace); + allTileNum = 0; + scalarUsedSpaceStream = createScalarUsedSpaceStream(); + arrayUsedSpaceStream = createArrayUsedSpaceStream(); + scalarObjectsStream = createScalarObjectsStream(); + arrayPrimitiveStream = createArrayPrimitiveStream(); + arrayObjectsStream = createArrayObjectsStream(); + rootsStream = createRootsStream(); + refFromImmortalStream = createRefFromImmortalStream(); + serverSpace.resize(0); // the collector must call resize() before gathering data + + // Initialise the statistics + resetData(); + scanner = new LinearScan(this); + } + + /** + * Get the name of this driver type. + * @return The name of this driver. + */ + protected String getDriverName() { return "MMTk LinearSpaceDriver"; } + + /** + * Private creator methods to create the Streams. + */ + @Interruptible + private IntStream createScalarUsedSpaceStream() { + return VM.newGCspyIntStream( + this, + "Scalar Used Space stream", // stream name + 0, // min. data value + blockSize, // max. data value + 0, // zero value + 0, // default value + "Scalars and primitive arrays: ", // value prefix + " bytes", // value suffix + StreamConstants.PRESENTATION_PERCENT, // presentation style + StreamConstants.PAINT_STYLE_ZERO, // paint style + 0, // index of max stream (only needed if the presentation is *_VAR) + Color.Red, // tile colour + true); // summary enabled + } + + @Interruptible + private IntStream createArrayUsedSpaceStream() { + return VM.newGCspyIntStream( + this, + "Array Used Space stream", + 0, + blockSize, + 0, + 0, + "Reference arrays: ", + " bytes", + StreamConstants.PRESENTATION_PERCENT, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Blue, + true); + } + + @Interruptible + private ShortStream createScalarObjectsStream() { + return VM.newGCspyShortStream( + this, + "Scalar Objects stream", + (short)0, + // Say, max value = 50% of max possible + (short)(maxObjectsPerBlock(blockSize)/2), + (short)0, + (short)0, + "Scalars: ", + " objects", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Green, + true); + } + + @Interruptible + private ShortStream createArrayPrimitiveStream() { + return VM.newGCspyShortStream( + this, + "Array Primitive stream", + (short)0, + // Say, typical primitive array size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "Primitive arrays: ", + " objects", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Yellow, + true); + } + + @Interruptible + private ShortStream createArrayObjectsStream() { + return VM.newGCspyShortStream( + this, + "Array Objects stream", + (short)0, + // Say, typical ref array size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "Reference arrays: ", + " objects", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Cyan, + true); + } + + @Interruptible + private ShortStream createRootsStream() { + return VM.newGCspyShortStream( + this, + "Roots stream", + (short)0, + // Say, typical size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "Roots: ", + " objects", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Blue, + true); + } + + @Interruptible + private ShortStream createRefFromImmortalStream() { + return VM.newGCspyShortStream( + this, + "References from immortal stream", + (short)0, + // Say, typical size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "References from immortal space: ", + " references", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Blue, + true); + } + + /** + * Reset the statistics for all the streams, including totals used for summaries + */ + public void resetData() { + super.resetData(); + + // Reset all the streams + scalarUsedSpaceStream.resetData(); + arrayUsedSpaceStream.resetData(); + scalarObjectsStream.resetData(); + arrayObjectsStream.resetData(); + arrayPrimitiveStream.resetData(); + refFromImmortalStream.resetData(); + + // Reset the summary counts + totalScalarObjects = 0; + totalArrayObjects = 0; + totalPrimitives = 0; + totalScalarUsedSpace = 0; + totalArrayUsedSpace = 0; + totalRefFromImmortal = 0; + } + + /** + * BumpPointer.linearScan needs a LinearScan object, which we provide here. + * @return the scanner for this driver + */ + public LinearScan getScanner() { return scanner; } + + /** + * Set the current address range of a contiguous space + * @param start the start of the contiguous space + * @param end the end of the contiguous space + */ + public void setRange(Address start, Address end) { + int current = subspace.getBlockNum(); + int required = countTileNum(start, end, subspace.getBlockSize()); + + // Reset the subspace + if(required != current) + subspace.reset(start, end, 0, required); + + if (DEBUG) { + Log.write("\nContiguousSpaceDriver.setRange for contiguous space: "); + Log.write(subspace.getFirstIndex()); Log.write("-", subspace.getBlockNum()); + Log.write(" (", start); Log.write("-", end); Log.write(")"); + } + + // Reset the driver + // Note release() only resets a CopySpace's cursor (and optionally zeroes + // or mprotects the pages); it doesn't make the pages available to other + // spaces. If pages were to be released, change the test here to + // if (allTileNum != required) { + if (allTileNum < required) { + if (DEBUG) { Log.write(", resize from ", allTileNum); Log.write(" to ", required); } + allTileNum = required; + serverSpace.resize(allTileNum); + setTilenames(subspace, allTileNum); + } + if (DEBUG) Log.writeln(); + } + + + /** + * Update the tile statistics + * @param obj The current object + */ + public void scan(ObjectReference obj) { + scan(obj, true); + } + + /** + * Update the tile statistics + * @param obj The current object + * @param total Whether to accumulate the values + */ + public void scan(ObjectReference obj, boolean total) { + boolean isArray = VM.objectModel.isArray(obj); + int length = VM.objectModel.getCurrentSize(obj); + Address addr = obj.toAddress(); + + if (VM.VERIFY_ASSERTIONS) { + if(addr.LT(lastAddress.plus(lastSize))) { + Log.write("\nContiguousSpaceDriver finds addresses going backwards: "); + Log.write("last="); Log.write(lastAddress); + Log.write(" last size="); Log.write(lastSize); + Log.writeln(" current=", addr); + } + lastAddress = addr; + lastSize = length; + } + + // Update the stats + if (subspace.addressInRange(addr)) { + int index = subspace.getIndex(addr); + int remainder = subspace.spaceRemaining(addr); + if (isArray) { + arrayObjectsStream.increment(index, (short)1); + arrayUsedSpaceStream.distribute(index, remainder, blockSize, length); + if (total) { + totalArrayObjects++; + totalArrayUsedSpace += length; + } + } else { + if(!this.scanCheckPrimitiveArray(obj, index, total, length)) { + // real object + scalarObjectsStream.increment(index, (short)1); + if (total) { + totalScalarObjects++; + totalScalarUsedSpace += length; + } + } + scalarUsedSpaceStream.distribute(index, remainder, blockSize, length); + } + } + } + + /** + * Check if this Object is an array of primitives.
    + * Part of the public scan() method. + * + * @param obj The Object to check + * @param index Index of the tile + * @param total Increment summary + * @param length Current size of the Object, will be added to array space summary. + * @return True if this Object is an array of primitives. + */ + protected boolean scanCheckPrimitiveArray(ObjectReference obj, int index, boolean total, int length) { + if(VM.objectModel.isPrimitiveArray(obj)) { + arrayPrimitiveStream.increment(index, (short)1); + if (total) { + totalPrimitives++; + totalScalarUsedSpace += length; + } + return true; + } else { + return false; + } + } + + /** + * Transmit the data if this event is of interest to the client.

    + * Implemented using the algorithm pattern, subclasses can override parts of it. + * @param event The event, defined in the Plan + */ + public void transmit(int event) { + if (!server.isConnected(event)) + return; + + if (DEBUG) { + Log.write("CONNECTED\n"); + Log.write(myClass); + Log.write(".send: numTiles=", allTileNum); + //Log.write("LinearSpaceDriver.transmit: numTiles=", allTileNum); + Log.writeln(", control.length=", control.length); + Log.flush(); + } + + // Setup the summaries + setupSummaries(); + + // Setup the control info + setupControlInfo(); + + // Setup the space info + Offset size = subspace.getEnd().diff(subspace.getStart()); + setSpaceInfo(size); + + // Send the all streams + send(event, allTileNum); + + // Debugging + if (VM.VERIFY_ASSERTIONS) { + lastAddress = Address.zero(); + lastSize = 0; + } + } + + /** + * Setup summaries part of the transmit method.

    + * Override this method to setup summaries of additional streams in subclasses. + */ + protected void setupSummaries() { + scalarUsedSpaceStream.setSummary(totalScalarUsedSpace, + subspace.getEnd().diff(subspace.getStart()).toInt()); + arrayUsedSpaceStream.setSummary(totalArrayUsedSpace, + subspace.getEnd().diff(subspace.getStart()).toInt()); + scalarObjectsStream.setSummary(totalScalarObjects); + arrayObjectsStream.setSummary(totalArrayObjects); + arrayPrimitiveStream.setSummary(totalPrimitives); + rootsStream.setSummary(totalRoots); + refFromImmortalStream.setSummary(totalRefFromImmortal); + } + + /** + * Setup control info part of the transmit method.

    + * Override this method to change the controls for your own driver subclass. + */ + protected void setupControlInfo() { + int numBlocks = subspace.getBlockNum(); + controlValues(CONTROL_USED, subspace.getFirstIndex(), numBlocks); + if (DEBUG) { + Log.write("LinearSpaceDriver.transmitSetupControlInfo: allTileNum=", allTileNum); + Log.writeln(", numBlocks=", numBlocks); + } + if (numBlocks < allTileNum) + controlValues(CONTROL_UNUSED, + subspace.getFirstIndex() + numBlocks, + allTileNum - numBlocks); + } + + /** + * Handle a root address + * + * @param addr Root Address + * @return true if the given Address is in this subspace. + */ + public boolean handleRoot(Address addr) { + if(subspace.addressInRange(addr)) { + // increment tile + int index = subspace.getIndex(addr); + rootsStream.increment(index, (short)1); + // increment summary + this.totalRoots++; + return true; + } else { + return false; + } + } + + /** + * Reset the roots Stream + * The roots Stream has to be reset seperately because we do not + * gather data in the usual way using scan(). + */ + public void resetRootsStream() { + rootsStream.resetData(); + totalRoots = 0; + } + + /** + * Handle a direct reference from the immortal space. + * + * @param addr The Address + * @return true if the given Address is in this subspace. + */ + public boolean handleReferenceFromImmortalSpace(Address addr) { + if(subspace.addressInRange(addr)) { + // increment tile + int index = subspace.getIndex(addr); + refFromImmortalStream.increment(index, (short)1); + // increment summary + this.totalRefFromImmortal++; + return true; + } else { + return false; + } + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,326 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.gcspy.drivers; + +import org.mmtk.policy.LargeObjectSpace; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.utility.gcspy.Subspace; +import org.mmtk.vm.gcspy.IntStream; +import org.mmtk.vm.gcspy.ShortStream; +import org.mmtk.vm.gcspy.ServerInterpreter; +import org.mmtk.utility.Conversions; +import org.mmtk.utility.Log; +import org.mmtk.vm.VM; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + +/** + * This class implements a simple driver for the MMTk LargeObjectSpace. + */ + at Uninterruptible public class TreadmillDriver extends AbstractDriver { + + private static final boolean DEBUG = false; + + // The streams + protected IntStream usedSpaceStream; + protected ShortStream objectsStream; + protected ShortStream rootsStream; + protected ShortStream refFromImmortalStream; + + protected Subspace subspace; // A single subspace for this space + protected int allTileNum; // total number of tiles + + // Overall statistics + protected int totalObjects = 0; // total number of objects allocated + protected int totalUsedSpace = 0; // total space used + protected int totalRoots = 0; // total of roots + protected int totalRefFromImmortal = 0; // total direct references from the immortal space + protected Address maxAddr; // the largest address seen + protected int threshold; + + + /** + * Create a new driver for this collector + * + * @param server The name of the GCspy server that owns this space + * @param spaceName The name of this driver + * @param lospace the large object space for this allocator + * @param blockSize The tile size + * @param threshold the size threshold of the LOS + * @param mainSpace Is this the main space? + */ + public TreadmillDriver( + ServerInterpreter server, + String spaceName, + LargeObjectSpace lospace, + int blockSize, + int threshold, + boolean mainSpace) { + //TODO blocksize should be a multiple of treadmill granularity + super(server, spaceName, lospace, blockSize, mainSpace); + + if (DEBUG) { + Log.write("TreadmillDriver for "); Log.write(spaceName); + Log.write(", blocksize="); Log.write(blockSize); + Log.write(", start="); Log.write(lospace.getStart()); + Log.write(", extent="); Log.write(lospace.getExtent()); + Log.write(", maxTileNum="); Log.writeln(maxTileNum); + } + + this.threshold = threshold; + + // Initialise a subspace and 2 Streams + subspace = createSubspace(lospace); + allTileNum = 0; + maxAddr = lospace.getStart(); + usedSpaceStream = createUsedSpaceStream(); + objectsStream = createObjectsStream(); + rootsStream = createRootsStream(); + refFromImmortalStream = createRefFromImmortalStream(); + serverSpace.resize(0); // the collector must call resize() before gathering data + + // Initialise the statistics + resetData(); + } + + /** + * Get the name of this driver type. + * @return The name, "MMTk TreadmillDriver" for this driver. + */ + protected String getDriverName() { + return "MMTk TreadmillDriver"; + } + + // private creator methods for the streams + @Interruptible + private IntStream createUsedSpaceStream() { + return VM.newGCspyIntStream( + this, + "Used Space stream", // stream name + 0, // min. data value + blockSize, // max. data value + 0, // zero value + 0, // default value + "Space used: ", // value prefix + " bytes", // value suffix + StreamConstants.PRESENTATION_PERCENT, // presentation style + StreamConstants.PAINT_STYLE_ZERO, // paint style + 0, // index of the max stream (only needed if presentation is *_VAR) + Color.Red, // tile colour + true); // summary enabled + } + + @Interruptible + private ShortStream createObjectsStream() { + return VM.newGCspyShortStream( + this, + "Objects stream", + (short)0, + (short)(blockSize/threshold), + (short)0, + (short)0, + "No. of objects = ", + " objects", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Green, + true); + } + + @Interruptible + private ShortStream createRootsStream() { + return VM.newGCspyShortStream( + this, + "Roots stream", + (short)0, + // Say, typical size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "Roots: ", + " objects", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Blue, + true); + } + + @Interruptible + private ShortStream createRefFromImmortalStream() { + return VM.newGCspyShortStream( + this, + "References from Immortal stream", + (short)0, + // Say, typical size = 4 * typical scalar size? + (short)(maxObjectsPerBlock(blockSize)/8), + (short)0, + (short)0, + "References from immortal space: ", + " references", + StreamConstants.PRESENTATION_PLUS, + StreamConstants.PAINT_STYLE_ZERO, + 0, + Color.Blue, + true); + } + + /** + * Reset the tile stats for all streams, including values used for summaries + */ + public void resetData() { + super.resetData(); + + // Reset all the streams + usedSpaceStream.resetData(); + objectsStream.resetData(); + refFromImmortalStream.resetData(); + + // Reset the summary counts + totalUsedSpace = 0; + totalObjects = 0; + totalRefFromImmortal = 0; + } + + /** + * Update the tile statistics + * In this case, we are accounting for super-page objects, rather than + * simply for the objects they contain. + * + * @param addr The address of the superpage + */ + public void scan(Address addr) { + + int index = subspace.getIndex(addr); + int length = ((LargeObjectSpace)mmtkSpace).getSize(addr).toInt(); + + if (DEBUG) { + Log.write("TreadmillDriver: super=", addr); + Log.write(", index=", index); + Log.write(", pages=", length); + Log.write(", bytes=", Conversions.pagesToBytes(length).toInt()); + Log.writeln(", max=", usedSpaceStream.getMaxValue()); + } + + totalObjects++; + totalUsedSpace += length; + objectsStream.increment(index, (short)1); + int remainder = subspace.spaceRemaining(addr); + usedSpaceStream.distribute(index, remainder, blockSize, length); + + Address tmp = addr.plus(length); + if (tmp.GT(maxAddr)) maxAddr = tmp; + } + + /** + * Transmit the data if this event is of interest to the client + * @param event The event, either BEFORE_COLLECTION, SEMISPACE_COPIED + * or AFTER_COLLECTION + */ + public void transmit(int event) { + if (!isConnected(event)) + return; + + // At this point, we've filled the tiles with data, + // however, we don't know the size of the space + // Calculate the highest indexed tile used so far, and update the subspace + Address start = subspace.getStart(); + int required = countTileNum(start, maxAddr, blockSize); + int current = subspace.getBlockNum(); + if (required > current || maxAddr != subspace.getEnd()) { + subspace.reset(start, maxAddr, 0, required); + allTileNum = required; + serverSpace.resize(allTileNum); + setTilenames(subspace, allTileNum); + } + + // Set the summaries + setupSummaries(); + + // set the control info: all of space is USED + controlValues(CONTROL_USED, + subspace.getFirstIndex(), subspace.getBlockNum()); + + // send the space info + Offset size = subspace.getEnd().diff(subspace.getStart()); + setSpaceInfo(size); + + // Send the streams + send(event, allTileNum); + } + + /** + * Setup summaries part of the transmit method.

    + * Override this method to setup summaries of additional streams in subclasses. + */ + protected void setupSummaries() { + usedSpaceStream.setSummary(totalUsedSpace, + subspace.getEnd().diff(subspace.getStart()).toInt()); + objectsStream.setSummary(totalObjects); + rootsStream.setSummary(totalRoots); + refFromImmortalStream.setSummary(totalRefFromImmortal); + } + + + /** + * Handle a root address + * + * @param addr Root Address + * @return true if the given Address is in this subspace. + */ + public boolean handleRoot(Address addr) { + if(subspace.addressInRange(addr)) { + // increment tile + int index = subspace.getIndex(addr); + rootsStream.increment(index, (short)1); + // increment summary + this.totalRoots++; + return true; + } else { + return false; + } + } + + /** + * Reset the roots Stream.
    + * The roots Stream has to be reset seperately because we do not + * gather data in the usual way using scan(). + */ + public void resetRootsStream() { + rootsStream.resetData(); + totalRoots = 0; + } + + /** + * Handle a direct reference from the immortal space. + * + * @param addr The Address + * @return true if the given Address is in this subspace. + */ + public boolean handleReferenceFromImmortalSpace(Address addr) { + if(subspace.addressInRange(addr)) { + // increment tile + int index = subspace.getIndex(addr); + refFromImmortalStream.increment(index, (short)1); + // increment summary + this.totalRefFromImmortal++; + return true; + } else { + return false; + } + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,382 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.heap; + +import org.mmtk.plan.Plan; +import org.mmtk.policy.Space; +import static org.mmtk.policy.Space.PAGES_IN_CHUNK; +import org.mmtk.utility.alloc.EmbeddedMetaData; +import org.mmtk.utility.Conversions; +import org.mmtk.utility.GenericFreeList; +import org.mmtk.vm.VM; +import org.mmtk.utility.Constants; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * This class manages the allocation of pages for a space. When a + * page is requested by the space both a page budget and the use of + * virtual address space are checked. If the request for space can't + * be satisfied (for either reason) a GC may be triggered.

    + */ + at Uninterruptible +public final class FreeListPageResource extends PageResource implements Constants { + + private final GenericFreeList freeList; + private int highWaterMark = 0; + private final int metaDataPagesPerRegion; + private int pagesCurrentlyOnFreeList = 0; + + /** + * Constructor + * + * Contiguous free list resource. The address range is pre-defined at + * initialization time and is immutable. + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + * @param start The start of the address range allocated to this resource + * @param bytes The size of the address rage allocated to this resource + */ + public FreeListPageResource(int pageBudget, Space space, Address start, + Extent bytes) { + super(pageBudget, space, start); + int pages = Conversions.bytesToPages(bytes); + freeList = new GenericFreeList(pages); + pagesCurrentlyOnFreeList = pages; + this.metaDataPagesPerRegion = 0; + } + + /** + * Constructor + * + * Contiguous free list resource. The address range is pre-defined at + * initialization time and is immutable. + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + * @param start The start of the address range allocated to this resource + * @param bytes The size of the address rage allocated to this resource + * @param metaDataPagesPerRegion The number of pages of meta data + * that are embedded in each region. + */ + public FreeListPageResource(int pageBudget, Space space, Address start, + Extent bytes, int metaDataPagesPerRegion) { + super(pageBudget, space, start); + this.metaDataPagesPerRegion = metaDataPagesPerRegion; + int pages = Conversions.bytesToPages(bytes); + freeList = new GenericFreeList(pages, EmbeddedMetaData.PAGES_IN_REGION); + pagesCurrentlyOnFreeList = pages; + reserveMetaData(space.getExtent()); + } + + /** + * Constructor + * + * Discontiguous monotone resource. The address range is not + * pre-defined at initialization time and is dynamically defined to + * be some set of pages, according to demand and availability. + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + */ + public FreeListPageResource(int pageBudget, Space space, int metaDataPagesPerRegion) { + super(pageBudget, space); + this.metaDataPagesPerRegion = metaDataPagesPerRegion; + this.start = Space.AVAILABLE_START; + freeList = new GenericFreeList(Map.globalPageMap, Map.getDiscontigFreeListPROrdinal(this)); + pagesCurrentlyOnFreeList = 0; + } + + /** + * Return the number of available physical pages for this resource. + * This includes all pages currently free on the resource's free list. + * If the resource is using discontiguous space it also includes + * currently unassigned discontiguous space.

    + * + * Note: This just considers physical pages (ie virtual memory pages + * allocated for use by this resource). This calculation is orthogonal + * to and does not consider any restrictions on the number of pages + * this resource may actually use at any time (ie the number of + * committed and reserved pages).

    + * + * Note: The calculation is made on the assumption that all space that + * could be assigned to this resource would be assigned to this resource + * (ie the unused discontiguous space could just as likely be assigned + * to another competing resource). + * + * @return The number of available physical pages for this resource. + */ + @Override + public int getAvailablePhysicalPages() { + int rtn = pagesCurrentlyOnFreeList; + if (!contiguous) { + int chunks = Map.getAvailableDiscontiguousChunks()-Map.getChunkConsumerCount(); + if (chunks < 0) chunks = 0; + rtn += chunks*(Space.PAGES_IN_CHUNK-metaDataPagesPerRegion); + } + return rtn; + } + + /** + * Allocate pages pages from this resource.

    + * + * If the request can be satisfied, then ensure the pages are + * mmpapped and zeroed before returning the address of the start of + * the region. If the request cannot be satisfied, return zero. + * + * @param pages The number of pages to be allocated. + * @return The start of the first page if successful, zero on + * failure. + */ + @Inline + protected Address allocPages(int pages) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(metaDataPagesPerRegion == 0 || pages <= PAGES_IN_CHUNK - metaDataPagesPerRegion); + lock(); + boolean newChunk = false; + int pageOffset = freeList.alloc(pages); + if (pageOffset == GenericFreeList.FAILURE && !contiguous) { + pageOffset = allocateContiguousChunks(pages); + newChunk = true; + } + if (pageOffset == -1) { + unlock(); + return Address.zero(); + } else { + pagesCurrentlyOnFreeList -= pages; + if (pageOffset > highWaterMark) { + if ((pageOffset ^ highWaterMark) > EmbeddedMetaData.PAGES_IN_REGION) { + int regions = 1 + ((pageOffset - highWaterMark) >> EmbeddedMetaData.LOG_PAGES_IN_REGION); + int metapages = regions * metaDataPagesPerRegion; + reserved += metapages; + committed += metapages; + newChunk = true; + } + highWaterMark = pageOffset; + } + Address rtn = start.plus(Conversions.pagesToBytes(pageOffset)); + Extent bytes = Conversions.pagesToBytes(pages); + commitPages(pages, pages); + space.growSpace(rtn, bytes, newChunk); + unlock(); + Mmapper.ensureMapped(rtn, pages); + VM.memory.zero(rtn, bytes); + VM.events.tracePageAcquired(space, rtn, pages); + return rtn; + } + } + + /** + * Release a group of pages, associated with this page resource, + * that were allocated together, optionally zeroing on release and + * optionally memory protecting on release. + * + * @param first The first page in the group of pages that were + * allocated together. + */ + @Inline + public void releasePages(Address first) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(Conversions.isPageAligned(first)); + + int pageOffset = Conversions.bytesToPages(first.diff(start)); + + int pages = freeList.size(pageOffset); + if (ZERO_ON_RELEASE) + VM.memory.zero(first, Conversions.pagesToBytes(pages)); + /* Can't use protect here because of the chunk sizes involved! + if (protectOnRelease.getValue()) + LazyMmapper.protect(first, pages); + */ + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pages <= committed); + + lock(); + reserved -= pages; + committed -= pages; + int freed = freeList.free(pageOffset, true); + pagesCurrentlyOnFreeList += pages; + + if (!contiguous) // only discontiguous spaces use chunks + releaseFreeChunks(first, freed); + + unlock(); + + VM.events.tracePageReleased(space, first, pages); + } + + /** + * The release of a page may have freed up an entire chunk or + * set of chunks. We need to check whether any chunks can be + * freed, and if so, free them. + * + * @param freedPage The address of the page that was just freed. + * @param pagesFreed The number of pages made available when the page was freed. + */ + private void releaseFreeChunks(Address freedPage, int pagesFreed) { + int pageOffset = Conversions.bytesToPages(freedPage.diff(start)); + + if (metaDataPagesPerRegion > 0) { // can only be a single chunk + if (pagesFreed == (PAGES_IN_CHUNK - metaDataPagesPerRegion)) { + freeContiguousChunk(Space.chunkAlign(freedPage, true)); + } + } else { // may be multiple chunks + if (pagesFreed % PAGES_IN_CHUNK == 0) { // necessary, but not sufficient condition + /* grow a region of chunks, starting with the chunk containing the freed page */ + int regionStart = pageOffset & ~(PAGES_IN_CHUNK - 1); + int nextRegionStart = regionStart + PAGES_IN_CHUNK; + /* now try to grow (end point pages are marked as non-coalescing) */ + while (regionStart >= 0 && freeList.isCoalescable(regionStart)) + regionStart -= PAGES_IN_CHUNK; + while (nextRegionStart < GenericFreeList.MAX_UNITS && freeList.isCoalescable(nextRegionStart)) + nextRegionStart += PAGES_IN_CHUNK; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(regionStart >= 0 && nextRegionStart < GenericFreeList.MAX_UNITS); + if (pagesFreed == nextRegionStart - regionStart) { + freeContiguousChunk(start.plus(Conversions.pagesToBytes(regionStart))); + } + } + } + } + + /** + * Allocate sufficient contiguous chunks within a discontiguous region to + * satisfy the pending request. Note that this is purely about address space + * allocation within a discontiguous region. This method does not reserve + * individual pages, it merely assigns a suitably large region of virtual + * memory from within the discontiguous region for use by a particular space. + * + * @param pages The number of pages currently being requested + * @return A chunk number or GenericFreelist.FAILURE + */ + private int allocateContiguousChunks(int pages) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(metaDataPagesPerRegion == 0 || pages <= PAGES_IN_CHUNK - metaDataPagesPerRegion); + int rtn = GenericFreeList.FAILURE; + int requiredChunks = Space.requiredChunks(pages); + Address region = space.growDiscontiguousSpace(requiredChunks); + if (!region.isZero()) { + int regionStart = Conversions.bytesToPages(region.diff(start)); + int regionEnd = regionStart + (requiredChunks*Space.PAGES_IN_CHUNK) - 1; + freeList.setUncoalescable(regionStart); + freeList.setUncoalescable(regionEnd + 1); + for (int p = regionStart; p < regionEnd; p += Space.PAGES_IN_CHUNK) { + int liberated; + if (p != regionStart) + freeList.clearUncoalescable(p); + liberated = freeList.free(p, true); // add chunk to our free list + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liberated == Space.PAGES_IN_CHUNK + (p - regionStart)); + if (metaDataPagesPerRegion > 1) + freeList.alloc(metaDataPagesPerRegion, p); // carve out space for metadata + pagesCurrentlyOnFreeList += Space.PAGES_IN_CHUNK - metaDataPagesPerRegion; + } + rtn = freeList.alloc(pages); // re-do the request which triggered this call + } + return rtn; + } + + /** + * Release a single chunk from a discontiguous region. All this does is + * release a chunk from the virtual address space associated with this + * discontiguous space. + * + * @param chunk The chunk to be freed + */ + private void freeContiguousChunk(Address chunk) { + int numChunks = Map.getContiguousRegionChunks(chunk); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(numChunks == 1 || metaDataPagesPerRegion == 0); + + /* nail down all pages associated with the chunk, so it is no longer on our free list */ + int chunkStart = Conversions.bytesToPages(chunk.diff(start)); + int chunkEnd = chunkStart + (numChunks*Space.PAGES_IN_CHUNK); + while (chunkStart < chunkEnd) { + freeList.setUncoalescable(chunkStart); + if (metaDataPagesPerRegion > 0) + freeList.free(chunkStart); // first free any metadata pages + int tmp = freeList.alloc(Space.PAGES_IN_CHUNK, chunkStart); // then alloc the entire chunk + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tmp == chunkStart); + chunkStart += Space.PAGES_IN_CHUNK; + pagesCurrentlyOnFreeList -= (Space.PAGES_IN_CHUNK - metaDataPagesPerRegion); + } + /* now return the address space associated with the chunk for global reuse */ + space.releaseDiscontiguousChunks(chunk); + } + + /** + * Reserve virtual address space for meta-data. + * + * @param extent The size of this space + */ + private void reserveMetaData(Extent extent) { + highWaterMark = 0; + if (metaDataPagesPerRegion > 0) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(start.toWord().rshl(EmbeddedMetaData.LOG_BYTES_IN_REGION).lsh(EmbeddedMetaData.LOG_BYTES_IN_REGION).toAddress().EQ(start)); + Extent size = extent.toWord().rshl(EmbeddedMetaData.LOG_BYTES_IN_REGION).lsh(EmbeddedMetaData.LOG_BYTES_IN_REGION).toExtent(); + Address cursor = start.plus(size); + while (cursor.GT(start)) { + cursor = cursor.minus(EmbeddedMetaData.BYTES_IN_REGION); + int unit = cursor.diff(start).toWord().rshl(LOG_BYTES_IN_PAGE).toInt(); + int tmp = freeList.alloc(metaDataPagesPerRegion, unit); + pagesCurrentlyOnFreeList -= metaDataPagesPerRegion; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tmp == unit); + } + } + } + + /** + * Adjust a page request to include metadata requirements, if any. In the + * case of a free-list allocator, meta-data is pre-allocated, so simply + * return the un-adjusted request size. + * + * @param pages The size of the pending allocation in pages + * @return The (unadjusted) request size, since metadata is pre-allocated + */ + public int adjustForMetaData(int pages) { return pages; } + + public Address getHighWater() { + return start.plus(Extent.fromIntSignExtend(highWaterMark< + *

  6. function[0][0] is ignored. + *
  7. All numbers in the first row must monotonically increase and + * must be in the range from 0 to 1 inclusive.
  8. + *
  9. All numbers in the first column must monotonically increase + * and must be in the range from 0 to 1 inclusive.
  10. + *
  11. There must be 0 and 1 values specified in both dimensions. + *
  12. For all interior points in the matrix, the value must be + * greater than the liveRatio for that column.
  13. + * + */ + private static final double[][] function = + VM.activePlan.constraints().generational() ? generationalFunction : nongenerationalFunction; + + private static long endLastMajorGC; + private static double accumulatedGCTime; + + /** + * Initialize heap size parameters and the mechanisms + * used to adaptively change heap size. + */ + public static void boot(Extent initial, Extent max) { + initialHeapSize = initial; + maxHeapSize = max; + if (initialHeapSize.GT(maxHeapSize)) + maxHeapSize = initialHeapSize; + currentHeapSize = initialHeapSize; + VM.events.heapSizeChanged(currentHeapSize); + if (VM.VERIFY_ASSERTIONS) sanityCheck(); + endLastMajorGC = VM.statistics.nanoTime(); + } + + /** + * @return the current heap size in bytes + */ + public static Extent getCurrentHeapSize() { + return currentHeapSize; + } + + /** + * Return the max heap size in bytes (as set by -Xmx). + * + * @return The max heap size in bytes (as set by -Xmx). + */ + public static Extent getMaxHeapSize() { + return maxHeapSize; + } + + /** + * Return the initial heap size in bytes (as set by -Xms). + * + * @return The initial heap size in bytes (as set by -Xms). + */ + public static Extent getInitialHeapSize() { + return initialHeapSize; + } + + /** + * Forcibly grow the heap by the given number of bytes. + * Used to provide headroom when handling an OutOfMemory + * situation. + * @param size number of bytes to grow the heap + */ + public static void overrideGrowHeapSize(Extent size) { + currentHeapSize = currentHeapSize.plus(size); + VM.events.heapSizeChanged(currentHeapSize); + } + + /** + * Record the time taken by the current GC; + * used to compute gc load, one of the inputs + * into the heap size management function + */ + public static void recordGCTime(double time) { + accumulatedGCTime += time; + } + + /** + * Reset timers used to compute gc load + */ + public static void reset() { + endLastMajorGC = VM.statistics.nanoTime(); + accumulatedGCTime = 0; + } + + /** + * Decide how to grow/shrink the heap to respond + * to application's memory usage. + * @return true if heap size was changed, false otherwise + */ + public static boolean considerHeapSize() { + Extent oldSize = currentHeapSize; + Extent reserved = Plan.reservedMemory(); + double liveRatio = reserved.toLong() / ((double) currentHeapSize.toLong()); + double ratio = computeHeapChangeRatio(liveRatio); + Extent newSize = Word.fromIntSignExtend((int)(ratio * (double) (oldSize.toLong()>>LOG_BYTES_IN_MBYTE))).lsh(LOG_BYTES_IN_MBYTE).toExtent(); // do arith in MB to avoid overflow + if (newSize.LT(reserved)) newSize = reserved; + newSize = newSize.plus(BYTES_IN_MBYTE - 1).toWord().rshl(LOG_BYTES_IN_MBYTE).lsh(LOG_BYTES_IN_MBYTE).toExtent(); // round to next megabyte + if (newSize.GT(maxHeapSize)) newSize = maxHeapSize; + if (newSize.NE(oldSize) && newSize.GT(Extent.zero())) { + // Heap size is going to change + currentHeapSize = newSize; + if (Options.verbose.getValue() >= 2) { + Log.write("GC Message: Heap changed from "); Log.writeDec(oldSize.toWord().rshl(LOG_BYTES_IN_KBYTE)); + Log.write("KB to "); Log.writeDec(newSize.toWord().rshl(LOG_BYTES_IN_KBYTE)); + Log.writeln("KB"); + } + VM.events.heapSizeChanged(currentHeapSize); + return true; + } else { + return false; + } + } + + private static double computeHeapChangeRatio(double liveRatio) { + // (1) compute GC load. + long totalNanos = VM.statistics.nanoTime() - endLastMajorGC; + double totalTime = VM.statistics.nanosToMillis(totalNanos); + double gcLoad = accumulatedGCTime / totalTime; + + if (liveRatio > 1) { + // Perhaps indicates bad bookkeeping in MMTk? + Log.write("GCWarning: Live ratio greater than 1: "); + Log.writeln(liveRatio); + liveRatio = 1; + } + if (gcLoad > 1) { + if (gcLoad > 1.0001) { + Log.write("GC Error: GC load was greater than 1!! "); + Log.writeln(gcLoad); + Log.write("GC Error:\ttotal time (ms) "); Log.writeln(totalTime); + Log.write("GC Error:\tgc time (ms) "); Log.writeln(accumulatedGCTime); + } + gcLoad = 1; + } + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio >= 0); + if (VM.VERIFY_ASSERTIONS && gcLoad < -0.0) { + Log.write("gcLoad computed to be "); Log.writeln(gcLoad); + Log.write("\taccumulateGCTime was (ms) "); Log.writeln(accumulatedGCTime); + Log.write("\ttotalTime was (ms) "); Log.writeln(totalTime); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + } + + if (Options.verbose.getValue() > 2) { + Log.write("Live ratio "); Log.writeln(liveRatio); + Log.write("GCLoad "); Log.writeln(gcLoad); + } + + // (2) Find the 4 points surrounding gcLoad and liveRatio + int liveRatioUnder = 1; + int liveRatioAbove = function[0].length - 1; + int gcLoadUnder = 1; + int gcLoadAbove = function.length - 1; + while (true) { + if (function[0][liveRatioUnder+1] >= liveRatio) break; + liveRatioUnder++; + } + while (true) { + if (function[0][liveRatioAbove-1] <= liveRatio) break; + liveRatioAbove--; + } + while (true) { + if (function[gcLoadUnder+1][0] >= gcLoad) break; + gcLoadUnder++; + } + while (true) { + if (function[gcLoadAbove-1][0] <= gcLoad) break; + gcLoadAbove--; + } + + // (3) Compute the heap change ratio + double factor = function[gcLoadUnder][liveRatioUnder]; + double liveRatioFraction = + (liveRatio - function[0][liveRatioUnder]) / + (function[0][liveRatioAbove] - function[0][liveRatioUnder]); + double liveRatioDelta = + function[gcLoadUnder][liveRatioAbove] - function[gcLoadUnder][liveRatioUnder]; + factor += (liveRatioFraction * liveRatioDelta); + double gcLoadFraction = + (gcLoad - function[gcLoadUnder][0]) / + (function[gcLoadAbove][0] - function[gcLoadUnder][0]); + double gcLoadDelta = + function[gcLoadAbove][liveRatioUnder] - function[gcLoadUnder][liveRatioUnder]; + factor += (gcLoadFraction * gcLoadDelta); + + if (Options.verbose.getValue() > 2) { + Log.write("Heap adjustment factor is "); + Log.writeln(factor); + } + return factor; + } + + /** + * Check that function satisfies the invariants + */ + private static void sanityCheck() { + // Check live ratio + double[] liveRatio = function[0]; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio[1] == 0); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio[liveRatio.length-1] == 1); + for (int i = 2; i < liveRatio.length; i++) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio[i-1] < liveRatio[i]); + for (int j = 1; j < function.length; j++) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[j][i] >= 1 || function[j][i] > liveRatio[i]); + } + } + + // Check GC load + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[1][0] == 0); + int len = function.length; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[len-1][0] == 1); + for (int i = 2; i < len; i++) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[i-1][0] < function[i][0]); + } + + // Check that we have a rectangular matrix + for (int i = 1; i < function.length; i++) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[i-1].length == function[i].length); + } + } + + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,339 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.heap; + +import org.mmtk.policy.Space; +import org.mmtk.utility.GenericFreeList; +import org.mmtk.utility.Log; +import org.mmtk.vm.Lock; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.Inline; +import org.vmmagic.pragma.Interruptible; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Extent; +import org.vmmagic.unboxed.Word; + +/** + * This class manages the mapping of spaces to virtual memory ranges.

    + * + */ + at Uninterruptible +public class Map { + + /* set the map base address so that we have an unused (null) chunk at the bottome of the space for 64 bit */ + private static final Address MAP_BASE_ADDRESS = Space.BITS_IN_ADDRESS == 32 ? Address.zero() : Space.HEAP_START.minus(Space.BYTES_IN_CHUNK); + + /**************************************************************************** + * + * Class variables + */ + private static final int[] descriptorMap; + private static final int[] linkageMap; + private static final Space[] spaceMap; + private static final GenericFreeList regionMap; + public static final GenericFreeList globalPageMap; + private static int sharedDiscontigFLCount = 0; + private static final FreeListPageResource[] sharedFLMap; + private static int totalAvailableDiscontiguousChunks = 0; + + private static final Lock lock = VM.newLock("Map lock"); + + /**************************************************************************** + * + * Initialization + */ + + /** + * Class initializer. Create our two maps + */ + static { + descriptorMap = new int[Space.MAX_CHUNKS]; + linkageMap = new int[Space.MAX_CHUNKS]; + spaceMap = new Space[Space.MAX_CHUNKS]; + regionMap = new GenericFreeList(Space.MAX_CHUNKS); + globalPageMap = new GenericFreeList(1, 1, Space.MAX_SPACES); + sharedFLMap = new FreeListPageResource[Space.MAX_SPACES]; + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(Space.BITS_IN_ADDRESS == Space.LOG_ADDRESS_SPACE || + Space.HEAP_END.diff(MAP_BASE_ADDRESS).toWord().rshl(Space.LOG_ADDRESS_SPACE).isZero()); + } + + /**************************************************************************** + * + * Map accesses and insertion + */ + + /** + * Insert a space and its descriptor into the map, associating it + * with a particular address range. + * + * @param start The start address of the region to be associated + * with this space. + * @param extent The size of the region, in bytes + * @param descriptor The descriptor for this space + * @param space The space to be associated with this region + */ + public static void insert(Address start, Extent extent, int descriptor, + Space space) { + Extent e = Extent.zero(); + while (e.LT(extent)) { + int index = getChunkIndex(start.plus(e)); + if (descriptorMap[index] != 0) { + Log.write("Conflicting virtual address request for space \""); + Log.write(space.getName()); Log.write("\" at "); + Log.writeln(start.plus(e)); + Space.printVMMap(); + VM.assertions.fail("exiting"); + } + descriptorMap[index] = descriptor; + VM.barriers.setArrayNoBarrier(spaceMap, index, space); + e = e.plus(Space.BYTES_IN_CHUNK); + } + } + + /** + * Allocate some number of contiguous chunks within a discontiguous region + * + * @param descriptor The descriptor for the space to which these chunks will be assigned + * @param space The space to which these chunks will be assigned + * @param chunks The number of chunks required + * @param previous The previous contgiuous set of chunks for this space (to create a linked list of contiguous regions for each space) + * @return The address of the assigned memory. This always succeeds. If the request fails we fail right here. + */ + public static Address allocateContiguousChunks(int descriptor, Space space, int chunks, Address previous) { + lock.acquire(); + int chunk = regionMap.alloc(chunks); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(chunk != 0); + if (chunk == -1) { + Log.write("Unable to allocate virtual address space for space \""); + Log.write(space.getName()); Log.write("\" for "); + Log.write(chunks); Log.write(" chunks ("); + Log.write(chunks<prior to bootstrap + * (i.e. at "build" time). + */ + static { + mapped = new byte[MMAP_NUM_CHUNKS]; + for (int c = 0; c < MMAP_NUM_CHUNKS; c++) { + mapped[c] = UNMAPPED; + } + } + + /**************************************************************************** + * Generic mmap and protection functionality + */ + + /** + * Given an address array describing the regions of virtual memory to be used + * by MMTk, demand zero map all of them if they are not already mapped. + * + * @param spaceMap An address array containing a pairs of start and end + * addresses for each of the regions to be mappe3d + */ + public static void eagerlyMmapAllSpaces(AddressArray spaceMap) { + + /*for (int i = 0; i < spaceMap.length() / 2; i++) { + Address regionStart = spaceMap.get(i * 2); + Address regionEnd = spaceMap.get(i * 2 + 1); + Log.write(regionStart); Log.write(" "); Log.writeln(regionEnd); + if (regionEnd.EQ(Address.zero()) || regionStart.EQ(Address.fromIntSignExtend(-1)) ||regionEnd.EQ(Address.fromIntSignExtend(-1))) + break; + if (VM.VERIFY_ASSERTIONS) { + VM.assertions._assert(regionStart.EQ(chunkAlignDown(regionStart))); + VM.assertions._assert(regionEnd.EQ(chunkAlignDown(regionEnd))); + } + int pages = Conversions.bytesToPages(regionEnd.diff(regionStart)); + ensureMapped(regionStart, pages); + }*/ + } + + /** + * Mark a range of pages as having (already) been mapped. This is useful + * where the VM has performed the mapping of the pages itself. + * + * @param start The start of the range to be marked as mapped + * @param bytes The size of the range, in bytes. + */ + public static void markAsMapped(Address start, int bytes) { + int startChunk = Conversions.addressToMmapChunksDown(start); + int endChunk = Conversions.addressToMmapChunksUp(start.plus(bytes)); + for (int i = startChunk; i <= endChunk; i++) + mapped[i] = MAPPED; + } + + /** + * Ensure that a range of pages is mmapped (or equivalent). If the + * pages are not yet mapped, demand-zero map them. Note that mapping + * occurs at chunk granularity, not page granularity.

    + * + * NOTE: There is a monotonicity assumption so that only updates require lock + * acquisition. + * TODO: Fix the above to support unmapping. + * + * @param start The start of the range to be mapped. + * @param pages The size of the range to be mapped, in pages + */ + public static void ensureMapped(Address start, int pages) { + int startChunk = Conversions.addressToMmapChunksDown(start); + int endChunk = Conversions.addressToMmapChunksUp(start.plus(Conversions.pagesToBytes(pages))); + for (int chunk = startChunk; chunk < endChunk; chunk++) { + if (mapped[chunk] == MAPPED) continue; + Address mmapStart = Conversions.mmapChunksToAddress(chunk); + lock.acquire(); +// Log.writeln(mmapStart); + // might have become MAPPED here + if (mapped[chunk] == UNMAPPED) { + int errno = VM.memory.dzmmap(mmapStart, MMAP_CHUNK_BYTES); + if (errno != 0) { + lock.release(); + Log.write("ensureMapped failed with errno "); Log.write(errno); + Log.write(" on address "); Log.writeln(mmapStart); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + } else { + if (verbose) { + Log.write("mmap succeeded at chunk "); Log.write(chunk); Log.write(" "); Log.write(mmapStart); + Log.write(" with len = "); Log.writeln(MMAP_CHUNK_BYTES); + } + } + } + if (mapped[chunk] == PROTECTED) { + if (!VM.memory.munprotect(mmapStart, MMAP_CHUNK_BYTES)) { + lock.release(); + VM.assertions.fail("Mmapper.ensureMapped (unprotect) failed"); + } else { + if (verbose) { + Log.write("munprotect succeeded at chunk "); Log.write(chunk); Log.write(" "); Log.write(mmapStart); + Log.write(" with len = "); Log.writeln(MMAP_CHUNK_BYTES); + } + } + } + mapped[chunk] = MAPPED; + lock.release(); + } + + } + + /** + * Memory protect a range of pages (using mprotect or equivalent). Note + * that protection occurs at chunk granularity, not page granularity. + * + * @param start The start of the range to be protected. + * @param pages The size of the range to be protected, in pages + */ + public static void protect(Address start, int pages) { + int startChunk = Conversions.addressToMmapChunksDown(start); + int chunks = Conversions.pagesToMmapChunksUp(pages); + int endChunk = startChunk + chunks; + lock.acquire(); + for (int chunk = startChunk; chunk < endChunk; chunk++) { + if (mapped[chunk] == MAPPED) { + Address mmapStart = Conversions.mmapChunksToAddress(chunk); + if (!VM.memory.mprotect(mmapStart, MMAP_CHUNK_BYTES)) { + lock.release(); + VM.assertions.fail("Mmapper.mprotect failed"); + } else { + if (verbose) { + Log.write("mprotect succeeded at chunk "); Log.write(chunk); Log.write(" "); Log.write(mmapStart); + Log.write(" with len = "); Log.writeln(MMAP_CHUNK_BYTES); + } + } + mapped[chunk] = PROTECTED; + } else { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(mapped[chunk] == PROTECTED); + } + } + lock.release(); + } + + /**************************************************************************** + * Utility functions + */ + + /** + * Return true if the given address has been mmapped + * + * @param addr The address in question. + * @return true if the given address has been mmapped + */ + @Uninterruptible + public static boolean addressIsMapped(Address addr) { + int chunk = Conversions.addressToMmapChunksDown(addr); + return mapped[chunk] == MAPPED; + } + + /** + * Return true if the given object has been mmapped + * + * @param object The object in question. + * @return true if the given object has been mmapped + */ + @Uninterruptible + public static boolean objectIsMapped(ObjectReference object) { + return addressIsMapped(VM.objectModel.refToAddress(object)); + } + + /** + * Return a given address rounded up to an mmap chunk size + * + * @param addr The address to be aligned + * @return The given address rounded up to an mmap chunk size + */ + @SuppressWarnings("unused") // but might be useful someday + private static Address chunkAlignUp(Address addr) { + return chunkAlignDown(addr.plus(MMAP_CHUNK_MASK)); + } + + /** + * Return a given address rounded down to an mmap chunk size + * + * @param addr The address to be aligned + * @return The given address rounded down to an mmap chunk size + */ + private static Address chunkAlignDown(Address addr) { + return addr.toWord().and(Word.fromIntSignExtend(MMAP_CHUNK_MASK).not()).toAddress(); + } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,307 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.heap; + +import org.mmtk.utility.alloc.EmbeddedMetaData; +import org.mmtk.utility.options.Options; +import org.mmtk.policy.Space; +import org.mmtk.utility.Conversions; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class manages the allocation of pages for a space. When a + * page is requested by the space both a page budget and the use of + * virtual address space are checked. If the request for space can't + * be satisfied (for either reason) a GC may be triggered.

    + */ + at Uninterruptible +public final class MonotonePageResource extends PageResource + implements Constants { + + /**************************************************************************** + * + * Instance variables + */ + private Address cursor; + private Address sentinel; + private final int metaDataPagesPerRegion; + private Address currentChunk = Address.zero(); + + /** + * Constructor + * + * Contiguous monotone resource. The address range is pre-defined at + * initialization time and is immutable. + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + * @param start The start of the address range allocated to this resource + * @param bytes The size of the address rage allocated to this resource + * @param metaDataPagesPerRegion The number of pages of meta data + * that are embedded in each region. + */ + public MonotonePageResource(int pageBudget, Space space, Address start, + Extent bytes, int metaDataPagesPerRegion) { + super(pageBudget, space, start); + this.cursor = start; + this.sentinel = start.plus(bytes); + this.metaDataPagesPerRegion = metaDataPagesPerRegion; + } + + /** + * Constructor + * + * Discontiguous monotone resource. The address range is not + * pre-defined at initialization time and is dynamically defined to + * be some set of pages, according to demand and availability. + * + * CURRENTLY UNIMPLEMENTED + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + * @param metaDataPagesPerRegion The number of pages of meta data + * that are embedded in each region. + */ + public MonotonePageResource(int pageBudget, Space space, int metaDataPagesPerRegion) { + super(pageBudget, space); + /* unimplemented */ + this.start = Address.zero(); + this.cursor = Address.zero(); + this.sentinel = Address.zero(); + this.metaDataPagesPerRegion = metaDataPagesPerRegion; + } + + /** + * Return the number of available physical pages for this resource. + * This includes all pages currently unused by this resource's page + * cursor. If the resource is using discontiguous space it also includes + * currently unassigned discontiguous space.

    + * + * Note: This just considers physical pages (ie virtual memory pages + * allocated for use by this resource). This calculation is orthogonal + * to and does not consider any restrictions on the number of pages + * this resource may actually use at any time (ie the number of + * committed and reserved pages).

    + * + * Note: The calculation is made on the assumption that all space that + * could be assigned to this resource would be assigned to this resource + * (ie the unused discontiguous space could just as likely be assigned + * to another competing resource). + * + * @return The number of available physical pages for this resource. + */ + @Override + public int getAvailablePhysicalPages() { + int rtn = Conversions.bytesToPages(sentinel.diff(cursor)); + if (!contiguous) + rtn += Map.getAvailableDiscontiguousChunks()*Space.PAGES_IN_CHUNK; + return rtn; + } + + /** + * Allocate pages pages from this resource. Simply + * bump the cursor, and fail if we hit the sentinel.

    + * + * If the request can be satisfied, then ensure the pages are + * mmpapped and zeroed before returning the address of the start of + * the region. If the request cannot be satisfied, return zero. + * + * @param requestPages The number of pages to be allocated. + * @return The start of the first page if successful, zero on + * failure. + */ + @Inline + protected Address allocPages(int requestPages) { + int pages = requestPages; + boolean newChunk = false; + lock(); + Address rtn = cursor; + if (Space.chunkAlign(rtn, true).NE(currentChunk)) { + newChunk = true; + currentChunk = Space.chunkAlign(rtn, true); + } + + if (metaDataPagesPerRegion != 0) { + /* adjust allocation for metadata */ + Address regionStart = getRegionStart(cursor.plus(Conversions.pagesToBytes(pages))); + Offset regionDelta = regionStart.diff(cursor); + if (regionDelta.sGE(Offset.zero())) { + /* start new region, so adjust pages and return address accordingly */ + pages += Conversions.bytesToPages(regionDelta) + metaDataPagesPerRegion; + rtn = regionStart.plus(Conversions.pagesToBytes(metaDataPagesPerRegion)); + } + } + Extent bytes = Conversions.pagesToBytes(pages); + Address tmp = cursor.plus(bytes); + + if (!contiguous && tmp.GT(sentinel)) { + /* we're out of virtual memory within our discontiguous region, so ask for more */ + int requiredChunks = Space.requiredChunks(pages); + start = space.growDiscontiguousSpace(requiredChunks); + cursor = start; + sentinel = cursor.plus(start.isZero() ? 0 : requiredChunks< + * + * In this case we simply report the expected page cost. We can't use + * worst case here because we would exhaust our budget every time. + * + * @param pages The size of the pending allocation in pages + * @return The number of required pages, inclusive of any metadata + */ + public int adjustForMetaData(int pages) { + return (metaDataPagesPerRegion * pages) / EmbeddedMetaData.PAGES_IN_REGION; + } + + /** + * Adjust a page request to include metadata requirements, if any.

    + * + * Note that there could be a race here, with multiple threads each + * adjusting their request on account of the same single metadata + * region. This should not be harmful, as the failing requests will + * just retry, and if multiple requests succeed, only one of them + * will actually have the metadata accounted against it, the others + * will simply have more space than they originally requested. + * + * @param pages The size of the pending allocation in pages + * @param begin The start address of the region assigned to this pending + * request + * @return The number of required pages, inclusive of any metadata + */ + public int adjustForMetaData(int pages, Address begin) { + if (getRegionStart(begin).plus(metaDataPagesPerRegion< + * + * This class is abstract, and is subclassed with monotone and + * freelist variants, which reflect monotonic and ad hoc space usage + * respectively. Monotonic use is easier to manage, but is obviously + * more restrictive (useful for copying collectors which allocate + * monotonically before freeing the entire space and starting over). + */ + at Uninterruptible +public abstract class PageResource implements Constants { + + /**************************************************************************** + * + * Class variables + */ + protected static final boolean ZERO_ON_RELEASE = false; // debugging + + private static final Lock classLock; + private static long cumulativeCommitted = 0; + + + /**************************************************************************** + * + * Instance variables + */ + + // page budgeting + protected int reserved; + protected int committed; + protected int required; + private final int pageBudget; + + protected final boolean contiguous; + protected final Space space; + protected Address start; // only for contiguous + + // locking + private final Lock gcLock; // used during GC + private final Lock mutatorLock; // used by mutators + + /**************************************************************************** + * + * Initialization + */ + static { + classLock = VM.newLock("PageResource"); + Options.protectOnRelease = new ProtectOnRelease(); + } + + /** + * Constructor + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + */ + private PageResource(int pageBudget, Space space, boolean contiguous) { + this.pageBudget = pageBudget; + this.contiguous = contiguous; + this.space = space; + gcLock = VM.newLock(space.getName() + ".gcLock"); + mutatorLock = VM.newLock(space.getName() + ".mutatorLock"); + } + + /** + * Constructor for discontiguous spaces + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + */ + PageResource(int pageBudget, Space space) { + this(pageBudget, space, false); + } + + /** + * Constructor for contiguous spaces + * + * @param pageBudget The budget of pages available to this memory + * manager before it must poll the collector. + * @param space The space to which this resource is attached + */ + PageResource(int pageBudget, Space space, Address start) { + this(pageBudget, space, true); + this.start = start; + } + + /** + * Return the number of available physical pages for this resource. + * + * Note: This just considers physical pages (ie virtual memory pages + * allocated for use by this resource). This calculation is orthogonal + * to and does not consider any restrictions on the number of pages + * this resource may actually use at any time (ie the number of + * committed and reserved pages).

    + * + * Note: The calculation is made on the assumption that all space that + * could be assigned to this resource would be assigned to this resource + * (ie the unused discontiguous space could just as likely be assigned + * to another competing resource). + * + * @return The number of available physical pages for this resource. + */ + public abstract int getAvailablePhysicalPages(); + + /** + * Reserve pages.

    + * + * The role of reserving pages is that it allows the request to be + * noted as pending (the difference between committed and reserved + * indicates pending requests). If the request would exceed the + * page budget then the caller must poll in case a GC is necessary. + * + * @param pages The number of pages requested + * @return True if the page budget could satisfy the request. + */ + @Inline + public final boolean reservePages(int pages) { + lock(); + required += adjustForMetaData(pages); + reserved = committed + required; + boolean satisfied = reserved <= pageBudget; + unlock(); + return satisfied; + } + + /** + * Remove a request to the space. + * + * @param pages The number of pages in the request. + */ + @Inline + public final void clearRequest(int pages) { + lock(); + required -= adjustForMetaData(pages); + unlock(); + } + + /** + * Reserve pages unconditionally.

    + * + * An example of where this is useful is in cases where it is + * desirable to put some space aside as head-room. By + * unconditionally reserving the pages, the pages are counted + * against the collectors budget. When the space is actually + * needed, the pages can be unconditionally released, freeing + * the pages for other purposes. + * + * @param pages The number of pages to be unconditionally + * reserved. + */ + public final void unconditionallyReservePages(int pages) { + lock(); + committed += pages; + reserved += pages; + unlock(); + } + + /** + * Release pages unconditionally.

    + * + * This call allows pages to be unconditionally removed from + * the collectors page budget. + * + * @see #unconditionallyReservePages + * @param pages The number of pages to be unconditionally + * released. + */ + public final void unconditionallyReleasePages(int pages) { + lock(); + committed -= pages; + reserved -= pages; + unlock(); + } + + abstract Address allocPages(int pages); + + /** + * Adjust a page request to include metadata requirements for a request + * of the given size. This must be a pure function, that is it does not + * depend on the state of the PageResource. + * + * @param pages The size of the pending allocation in pages + * @return The number of required pages, inclusive of any metadata + */ + public abstract int adjustForMetaData(int pages); + + /** + * Allocate pages in virtual memory, returning zero on failure.

    + * + * If the request cannot be satisfied, zero is returned and it + * falls to the caller to trigger the GC. + * + * Call allocPages (subclass) to find the pages in + * virtual memory. If successful then commit the pending page + * request and return the address of the first page. + * + * @param pages The number of pages requested + * @return The address of the first of pages pages, or + * zero on failure. + */ + @Inline + public final Address getNewPages(int pages) { + return allocPages(pages); + } + + /** + * Commit pages to the page budget. This is called after + * successfully determining that the request can be satisfied by + * both the page budget and virtual memory. This simply accounts + * for the descrepency between committed and + * reserved while the request was pending. + * + * This *MUST* be called by each PageResource during the + * allocPages, and the caller must hold the lock. + * + * @param requestedPages The number of pages from this request + * @param totalPages The number of pages + */ + protected void commitPages(int requestedPages, int totalPages) { + int predictedPages = adjustForMetaData(requestedPages); + int delta = totalPages - predictedPages; + required -= predictedPages; + reserved += delta; + committed += totalPages; + if (!Plan.gcInProgress()) + addToCommitted(totalPages); // only count mutator pages + } + + /** + * Return the number of reserved pages + * + * @return The number of reserved pages. + */ + public final int reservedPages() { return reserved; } + + /** + * Return the number of committed pages + * + * @return The number of committed pages. + */ + public final int committedPages() { return committed; } + + /** + * Return the number of required pages + * + * @return The number of required pages. + */ + public final int requiredPages() { return required; } + + /** + * Return the cumulative number of committed pages + * + * @return The cumulative number of committed pages. + */ + public static long cumulativeCommittedPages() { return cumulativeCommitted; } + + /** + * Add to the total cumulative committed page count. + * + * @param pages The number of pages to be added. + */ + private static void addToCommitted(int pages) { + classLock.acquire(); + cumulativeCommitted += pages; + classLock.release(); + } + + /** + * Acquire the appropriate lock depending on whether the context is + * GC or mutator. + */ + protected final void lock() { + if (Plan.gcInProgress()) + gcLock.acquire(); + else + mutatorLock.acquire(); + } + + /** + * Release the appropriate lock depending on whether the context is + * GC or mutator. + */ + protected final void unlock() { + if (Plan.gcInProgress()) + gcLock.release(); + else + mutatorLock.release(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,166 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.heap; + +import org.mmtk.policy.Space; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class manages the encoding and decoding of space descriptors.

    + * + * Space descriptors are integers that encode a space's mapping into + * virtual memory. For discontiguous spaces, they indicate + * discontiguity and mapping must be done by consulting the space map. + * For contiguous spaces, the space's address range is encoded into + * the integer (using a fixed point notation).

    + * + * The purpose of this class is to allow static final int + * space descriptors to exist for each space, which can then be used + * in tests to determine whether an object is in a space. A good + * compiler can perform this decoding at compile time and produce + * optimal code for the test. + */ + at Uninterruptible public class SpaceDescriptor implements Constants { + + /**************************************************************************** + * + * Class variables + */ + + private static final int TYPE_BITS = 2; + private static final int TYPE_SHARED = 0; + private static final int TYPE_CONTIGUOUS = 1; + private static final int TYPE_CONTIGUOUS_HI = 3; + private static final int TYPE_MASK = (1 << TYPE_BITS) - 1; + private static final int SIZE_SHIFT = TYPE_BITS; + private static final int SIZE_BITS = 10; + private static final int SIZE_MASK = ((1 << SIZE_BITS) - 1) << SIZE_SHIFT; + private static final int EXPONENT_SHIFT = SIZE_SHIFT + SIZE_BITS; + private static final int EXPONENT_BITS = 5; + private static final int EXPONENT_MASK = ((1 << EXPONENT_BITS) - 1) << EXPONENT_SHIFT; + private static final int MANTISSA_SHIFT = EXPONENT_SHIFT + EXPONENT_BITS; + private static final int MANTISSA_BITS = 14; + private static final int BASE_EXPONENT = BITS_IN_INT - MANTISSA_BITS; + + private static int discontiguousSpaceIndex = 0; + private static final int DISCONTIG_INDEX_INCREMENT = 1<contiguous space + * + * @param start The start address of the space + * @param end The end address of the space + * @return An integer descriptor encoding the region of virtual + * memory occupied by the space + */ + public static int createDescriptor(Address start, Address end) { + int chunks = end.diff(start).toWord().rshl(Space.LOG_BYTES_IN_CHUNK).toInt(); + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(!start.isZero() && chunks > 0 && chunks < (1 << SIZE_BITS)); + boolean top = end.EQ(Space.HEAP_END); + Word tmp = start.toWord(); + tmp = tmp.rshl(BASE_EXPONENT); + int exponent = 0; + while (!tmp.isZero() && tmp.and(Word.one()).isZero()) { + tmp = tmp.rshl(1); + exponent++; + } + int mantissa = tmp.toInt(); + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(tmp.lsh(BASE_EXPONENT + exponent).EQ(start.toWord())); + return (mantissa<dis-contiguous (shared) space + * + * @return An integer descriptor reflecting the fact that this space + * is shared (and thus discontiguous and so must be established via + * maps). + */ + public static int createDescriptor() { + discontiguousSpaceIndex += DISCONTIG_INDEX_INCREMENT; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((discontiguousSpaceIndex & TYPE_CONTIGUOUS) != TYPE_CONTIGUOUS); + return discontiguousSpaceIndex; + } + + /**************************************************************************** + * + * Descriptor interrogation + */ + + /** + * Return true if this descriptor describes a contiguous space + * + * @param descriptor + * @return True if this descriptor describes a contiguous space + */ + @Inline + public static boolean isContiguous(int descriptor) { + return ((descriptor & TYPE_CONTIGUOUS) == TYPE_CONTIGUOUS); + } + + /** + * Return true if this descriptor describes a contiguous space that + * is at the top of the virtual address space + * + * @param descriptor + * @return True if this descriptor describes a contiguous space that + * is at the top of the virtual address space + */ + @Inline + public static boolean isContiguousHi(int descriptor) { + return ((descriptor & TYPE_MASK) == TYPE_CONTIGUOUS_HI); + } + + /** + * Return the start of this region of memory encoded in this descriptor + * + * @param descriptor + * @return The start of this region of memory encoded in this descriptor + */ + @Inline + public static Address getStart(int descriptor) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isContiguous(descriptor)); + Word mantissa = Word.fromIntSignExtend(descriptor >>> MANTISSA_SHIFT); + int exponent = (descriptor & EXPONENT_MASK) >>> EXPONENT_SHIFT; + return mantissa.lsh(BASE_EXPONENT + exponent).toAddress(); + } + + /** + * Return the size of the region of memory encoded in this + * descriptor, in chunks + * + * @param descriptor + * @return The size of the region of memory encoded in this + * descriptor, in chunks + */ + @Inline + public static int getChunks(int descriptor) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isContiguous(descriptor)); + return (descriptor & SIZE_MASK) >>> SIZE_SHIFT; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,126 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.heap; + +import org.mmtk.utility.Constants; + +import org.vmmagic.unboxed.*; + +/** + * This class manages the encoding and decoding of virtual memory requests. + * + * By encapsulating this aspect of the construction of a space, we greatly + * reduce the number of constructors required. + */ +public final class VMRequest implements Constants { + + public static final int REQUEST_DISCONTIGUOUS = 0; + public static final int REQUEST_FIXED = 1; + public static final int REQUEST_EXTENT = 3; + public static final int REQUEST_FRACTION = 4; + + public final int type; + public final Address start; + public final Extent extent; + public final float frac; + public final boolean top; + + private VMRequest(int type, Address start, Extent bytes, float frac, boolean top) { + this.type = type; + this.start = start; + this.extent = bytes; + this.frac = frac; + this.top = top; + } + + /** + * Is this a discontiguous space request? + * @return true if this is a discontiguous space request, false otherwise + */ + public boolean isDiscontiguous() { + return type == REQUEST_DISCONTIGUOUS; + } + + /** + * A request for a discontiguous region of memory + * + * @return The request object + */ + public static VMRequest create() { + return new VMRequest(REQUEST_DISCONTIGUOUS, Address.zero(), Extent.zero(), 0f, false); + } + + /** + * A request for an explicit region of memory + * + * @param start The start of the region + * @param extent The size of the region + * @return The request object + */ + public static VMRequest create(Address start, Extent extent) { + return new VMRequest(REQUEST_FIXED, start, extent, 0f, false); + } + + /** + * A request for a number of megabytes of memory + * + * @param mb The number of megabytes + * @return The request object + */ + public static VMRequest create(int mb) { + return create(mb, false); + } + + /** + * A request for a fraction of available memory + * + * @param frac The fraction + * @return The request object + */ + public static VMRequest create(float frac) { + return create(frac, false); + } + + /** + * A request for a number of megabytes of memory, optionally requesting the highest available. + * + * @param mb The number of megabytes + * @param top True to request high memory + * @return The request object + */ + public static VMRequest create(int mb, boolean top) { + return new VMRequest(REQUEST_EXTENT, Address.zero(), Word.fromIntSignExtend(mb).lsh(LOG_BYTES_IN_MBYTE).toExtent(), 0f, top); + } + + /** + * A request for a fraction of available memory, optionally requesting the highest available. + * + * @param frac The fraction + * @param top True to request high memory + * @return The request object + */ + public static VMRequest create(float frac, boolean top) { + return new VMRequest(REQUEST_FRACTION, Address.zero(), Extent.zero(), frac, top); + } + + /** + * A request for a number of bytes of memory, optionally requesting the highest available. + * + * @param extent The number of bytes + * @param top True to request high memory + * @return The request object + */ + public static VMRequest create(Extent extent, boolean top) { + return new VMRequest(REQUEST_EXTENT, Address.zero(), extent, 0f, top); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,37 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.mmtk.plan.Plan; + +/** + * Provide an upper bound on nursery size. This option is not intended to + * be created directly, but via NurserySize. + */ +public final class BoundedNursery extends org.vmutil.options.PagesOption { + /** + * Create the option. + */ + public BoundedNursery() { + super(Options.set, "Bounded Nursery", + "Bound the maximum size of the nursery to this value", + Plan.DEFAULT_MAX_NURSERY); + } + + /** + * Nursery can not be empty. + */ + protected void validate() { + failIf(value <= 0, "Can not have an empty nursery"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,35 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Concurrent trigger percentage + */ +public class ConcurrentTrigger extends org.vmutil.options.IntOption { + /** + * Create the option. + */ + public ConcurrentTrigger() { + super(Options.set, "Concurrent Trigger", + "Concurrent trigger percentage", + 50); + } + + /** + * Only accept values between 1 and 100 (inclusive) + */ + protected void validate() { + failIf(this.value <= 0, "Trigger must be between 1 and 100"); + failIf(this.value > 100, "Trigger must be between 1 and 100"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Trigger cycle buffer filtering if the space available falls below this threshold. + */ +public final class CycleFilterThreshold extends org.vmutil.options.PagesOption { + /** + * Create the option. + */ + public CycleFilterThreshold() { + super(Options.set, "Cycle Filter Threshold", + "Trigger cycle buffer filtering if the space available falls below this threshold", + 512); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Trigger cycle detection if the meta data volume grows to this limit. + */ +public final class CycleMetaDataLimit extends org.vmutil.options.PagesOption { + /** + * Create the option. + */ + public CycleMetaDataLimit() { + super(Options.set, "Cycle Meta Data Limit", + "Trigger cycle detection if the meta data volume grows to this limit", + 4096); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Trigger cycle detection if the space available falls below this threshold. + */ +public final class CycleTriggerThreshold extends org.vmutil.options.PagesOption { + /** + * Create the option. + */ + public CycleTriggerThreshold() { + super(Options.set, "Cycle Trigger Threshold", + "Trigger cycle detection if the space available falls below this threshold", + 512); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,29 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.vmmagic.unboxed.Address; + +/** + * Allow an address to be specified on the command line for use in debugging. + */ +public final class DebugAddress extends org.vmutil.options.AddressOption { + /** + * Create the option + */ + public DebugAddress() { + super(Options.set, "Debug Address", + "Specify an address at runtime for use in debugging", + Address.zero()); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,26 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_FREE_HEADROOM; + +public class DefragFreeHeadroom extends org.vmutil.options.PagesOption { + /** + * Create the option. + */ + public DefragFreeHeadroom() { + super(Options.set, "Defrag Free Headroom", + "Allow the defragmenter this amount of free headroom during defrag. For analysis purposes only!", + DEFAULT_DEFRAG_FREE_HEADROOM); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,33 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_FREE_HEADROOM_FRACTION; + +public class DefragFreeHeadroomFraction extends org.vmutil.options.FloatOption { + /** + * Create the option. + */ + public DefragFreeHeadroomFraction() { + super(Options.set, "Defrag Free Headroom Fraction", + "Allow the defragmenter this fraction of the heap size as free headroom during defrag. For analysis purposes only!", + DEFAULT_DEFRAG_FREE_HEADROOM_FRACTION); + } + + /** + * Ensure the value is valid. + */ + protected void validate() { + failIf((this.value < 0 || this.value > 1.0), "Ratio must be a float between 0 and 1"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_HEADROOM; + +/** + */ +public class DefragHeadroom extends org.vmutil.options.PagesOption { + /** + * Create the option. + */ + public DefragHeadroom() { + super(Options.set, "Defrag Headroom", + "Allow the defragmenter this amount of headroom during defrag.", + DEFAULT_DEFRAG_HEADROOM); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,33 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_HEADROOM_FRACTION; + +public class DefragHeadroomFraction extends org.vmutil.options.FloatOption { + /** + * Create the option. + */ + public DefragHeadroomFraction() { + super(Options.set, "Defrag Headroom Fraction", + "Allow the defrag this fraction of the heap as headroom during defrag.", + DEFAULT_DEFRAG_HEADROOM_FRACTION); + } + + /** + * Ensure the value is valid. + */ + protected void validate() { + failIf((this.value < 0 || this.value > 1.0), "Ratio must be a float between 0 and 1"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,33 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_LINE_REUSE_RATIO; + +public class DefragLineReuseRatio extends org.vmutil.options.FloatOption { + /** + * Create the option. + */ + public DefragLineReuseRatio() { + super(Options.set, "Defrag Line Reuse Ratio", + "Blocks with this fraction marked may be reused for defrag allocation", + DEFAULT_DEFRAG_LINE_REUSE_RATIO); + } + + /** + * Ensure the value is valid. + */ + protected void validate() { + failIf((this.value <= 0 || this.value > 1.0), "Ratio must be a float between 0 and 1"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,33 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_SIMPLE_SPILL_THRESHOLD; + +public class DefragSimpleSpillThreshold extends org.vmutil.options.FloatOption { + /** + * Create the option. + */ + public DefragSimpleSpillThreshold() { + super(Options.set, "Defrag Simple Spill Threshold", + "Blocks with this fraction spilled will be defrag sources", + DEFAULT_SIMPLE_SPILL_THRESHOLD); + } + + /** + * Ensure the value is valid. + */ + protected void validate() { + failIf((this.value <= 0 || this.value > 1.0), "Ratio must be a float between 0 and 1"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we force degfrag every time the immix space is collected? + */ +public final class DefragStress extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public DefragStress() { + super(Options.set, "Defrag Stress", + "Should we force degfrag every time the immix space is collected?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,33 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * A sample enumeration for testing. + */ +public final class DummyEnum extends org.vmutil.options.EnumOption { + + // enumeration values. + public final int FOO = 0; + public final int BAR = 1; + + /** + * Create the option. + */ + public DummyEnum() { + super(Options.set, "Dummy Enum", + "This is a sample enumeration to test the options system", + new String[] {"foo", "bar"}, + "foo"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we eagerly finish sweeping at the start of a collection + */ +public final class EagerCompleteSweep extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public EagerCompleteSweep() { + super(Options.set, "Eager Complete Sweep", + "Should we eagerly finish sweeping at the start of a collection", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should spaces be eagerly demand zero mmapped? + */ +public final class EagerMmapSpaces extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public EagerMmapSpaces() { + super(Options.set, "Eager Mmap Spaces", + "If true, all spaces are eagerly demand zero mmapped at boot time", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Echo when options are set? + */ +public final class EchoOptions extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public EchoOptions() { + super(Options.set, "Echo Options", + "Echo when options are set?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,44 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.mmtk.plan.Plan; + +/** + * Provide an lower and upper bound on nursery size. + * + * This option is not intended to be created directly, but via NurserySize. + */ +public final class FixedNursery extends org.vmutil.options.PagesOption { + // values + BoundedNursery boundedNursery; + + /** + * Create the option + */ + public FixedNursery(BoundedNursery boundedNursery) { + super(Options.set, "Fixed Nursery", + "Fix the minimum and maximum size of the nursery to this value", + Plan.DEFAULT_MIN_NURSERY); + this.boundedNursery = boundedNursery; + } + + /** + * Nursery can not be empty. + */ + protected void validate() { + failIf(value <= 0, "Can not have an empty nursery"); + // Update upper bound. + boundedNursery.setBytes(this.getBytes()); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Option to print fragmentation information for the free list. + */ +public final class FragmentationStats extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public FragmentationStats() { + super(Options.set, "Fragmentation Stats", + "Should we print fragmentation statistics for the free list allocator?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should a major GC be performed when a system GC is triggered? + */ +public final class FullHeapSystemGC extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public FullHeapSystemGC() { + super(Options.set, "Full Heap System GC", + "Should a major GC be performed when a system GC is triggered?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Try to limit reference counting collections to this time cap. + */ +public final class GCTimeCap extends org.vmutil.options.MicrosecondsOption { + /** + * Create the option. + */ + public GCTimeCap() { + super(Options.set, "GC Time Cap", + "Try to limit reference counting collections to this time cap", + 1000000); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,34 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Port number for GCSpy server to connect with visualiser. + */ +public final class GCspyPort extends org.vmutil.options.IntOption { + /** + * Create the option. + */ + public GCspyPort() { + super(Options.set, "GCSpy Port", + "Port number for GCSpy server to connect with visualiser", + 0); + } + + /** + * Ensure the port is valid. + */ + protected void validate() { + failIf(this.value <= 0, "Unreasonable GCSpy port value"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,34 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * GCspy Tile Size. + */ +public final class GCspyTileSize extends org.vmutil.options.IntOption { + /** + * Create the option. + */ + public GCspyTileSize() { + super(Options.set, "GCspy Tile Size", + "GCspy Tile Size", + 131072); + } + + /** + * Ensure the tile size is positive + */ + protected void validate() { + failIf(this.value <= 0, "Unreasonable gcspy tilesize"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should the VM wait for the visualiser to connect? + */ +public final class GCspyWait extends org.vmutil.options.BooleanOption { + /** + * Create the option + */ + public GCspyWait() { + super(Options.set, "GCSpy Wait", + "Should the VM wait for the visualiser to connect?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we use a generational approach to cycle detection? + */ +public final class GenCycleDetection extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public GenCycleDetection() { + super(Options.set, "Gen Cycle Detection", + "Should we use a generational approach to cycle detection?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we wrap the entire execution with a harnessBegin/harnessEnd? + */ +public final class HarnessAll extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public HarnessAll() { + super(Options.set, "Harness All", + "Should we wrap the entire execution inside calls to harnessBegin and harnessEnd?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we ignore calls to java.lang.System.gc? + */ +public final class IgnoreSystemGC extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public IgnoreSystemGC() { + super(Options.set, "Ignore System GC", + "Should we ignore calls to java.lang.System.gc?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,35 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_LINE_REUSE_RATIO; + +/** + */ +public class LineReuseRatio extends org.vmutil.options.FloatOption { + /** + * Create the option. + */ + public LineReuseRatio() { + super(Options.set, "Line Reuse Ratio", + "Blocks with this fraction marked may be reused for allocation", + DEFAULT_LINE_REUSE_RATIO); + } + + /** + * Ensure the value is valid. + */ + protected void validate() { + failIf((this.value <= 0 || this.value > 1.0), "Ratio must be a float between 0 and 1"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,37 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.mmtk.policy.MarkSweepSpace; + +/** + * Number of bits to use for the header cycle of mark sweep spaces. + */ +public final class MarkSweepMarkBits extends org.vmutil.options.IntOption { + /** + * Create the option. + */ + public MarkSweepMarkBits() { + super(Options.set, "Mark Sweep Mark Bits", + "Number of bits to use for the header cycle of mark sweep spaces", + MarkSweepSpace.DEFAULT_MARKCOUNT_BITS); + } + + /** + * Ensure the value is valid. + */ + protected void validate() { + failIf(this.value <= 0, "Must provide at least one bit"); + failIf(this.value > MarkSweepSpace.MAX_MARKCOUNT_BITS , "Only "+MarkSweepSpace.MAX_MARKCOUNT_BITS+" bits are reserved in MarkSweepSpace"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Provide a bound on how much metadata is allowed before a GC is triggered. + */ +public final class MetaDataLimit extends org.vmutil.options.PagesOption { + /** + * Create the option. + */ + public MetaDataLimit() { + super(Options.set, "Meta Data Limit", + "Trigger a GC if the meta data volume grows to this limit", + 4096); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should finalization be disabled? + */ +public final class NoFinalizer extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public NoFinalizer() { + super(Options.set, "No Finalizer", + "Should finalization be disabled?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should reference type processing be disabled? + */ +public final class NoReferenceTypes extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public NoReferenceTypes() { + super(Options.set, "No Reference Types", + "Should reference type processing be disabled?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,53 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.vmmagic.pragma.*; + +/** + * A composite option that provides a min/max interface to MMTk, + * and a fixed/bounded option interface to the VM/user. + */ +public final class NurserySize { + // values + private FixedNursery fixedNursery; + private BoundedNursery boundedNursery; + + /** + * Create the options. + */ + public NurserySize() { + boundedNursery = new BoundedNursery(); + fixedNursery = new FixedNursery(boundedNursery); + } + + /** + * Read the upper bound of the nursery size. + * + * @return maximum number of pages in the nursery. + */ + @Uninterruptible + public int getMaxNursery() { + return boundedNursery.getPages(); + } + + /** + * Read the lower bound of the nursery size. + * + * @return minimum number of pages in the nursery. + */ + @Uninterruptible + public int getMinNursery() { + return fixedNursery.getPages(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,67 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.vmutil.options.OptionSet; + +/** + * Repository for all option instances. + */ +public final class Options { + public static OptionSet set; + + /* Other options */ + public static BoundedNursery boundedNursery; + public static ConcurrentTrigger concurrentTrigger; + public static CycleFilterThreshold cycleFilterThreshold; + public static CycleMetaDataLimit cycleMetaDataLimit; + public static CycleTriggerThreshold cycleTriggerThreshold; + public static DebugAddress debugAddress; + public static DummyEnum dummyEnum; + public static DefragHeadroom defragHeadroom; + public static DefragHeadroomFraction defragHeadroomFraction; + public static DefragFreeHeadroom defragFreeHeadroom; + public static DefragFreeHeadroomFraction defragFreeHeadroomFraction; + public static DefragLineReuseRatio defragLineReuseRatio; + public static DefragSimpleSpillThreshold defragSimpleSpillThreshold; + public static DefragStress defragStress; + public static EagerCompleteSweep eagerCompleteSweep; + public static EagerMmapSpaces eagerMmapSpaces; + public static FixedNursery fixedNursery; + public static FragmentationStats fragmentationStats; + public static FullHeapSystemGC fullHeapSystemGC; + public static GCspyPort gcspyPort; + public static GCspyTileSize gcspyTileSize; + public static GCspyWait gcspyWait; + public static GCTimeCap gcTimeCap; + public static GenCycleDetection genCycleDetection; + public static HarnessAll harnessAll; + public static IgnoreSystemGC ignoreSystemGC; + public static LineReuseRatio lineReuseRatio; + public static MarkSweepMarkBits markSweepMarkBits; + public static MetaDataLimit metaDataLimit; + public static NoFinalizer noFinalizer; + public static NoReferenceTypes noReferenceTypes; + public static NurserySize nurserySize; + public static PerfMetric perfMetric; + public static PrintPhaseStats printPhaseStats; + public static ProtectOnRelease protectOnRelease; + public static SanityCheck sanityCheck; + public static StressFactor stressFactor; + public static TraceRate traceRate; + public static VariableSizeHeap variableSizeHeap; + public static VerboseFragmentationStats verboseFragmentationStats; + public static Verbose verbose; + public static VerboseTiming verboseTiming; + public static XmlStats xmlStats; +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Performance counter options. + */ +public class PerfMetric extends org.vmutil.options.EnumOption { + /** + * Create the option. + */ + public PerfMetric() { + super(Options.set, "Perf Metric", + "Use this to select a performance metric to measure", + new String[] {"RI", "L1D_MISS", "L2_MISS", "DTLB_MISS", "ITLB_MISS", "ITLB_HIT", "BPU_TC", "TC_FLUSH", "L1I_MISS", "BRANCHES", "BRANCH_MISS"}, + "RI"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * When printing statistics, should statistics for each + * gc-mutator phase be printed? + */ +public final class PrintPhaseStats extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public PrintPhaseStats() { + super(Options.set, "Print Phase Stats", + "When printing statistics, should statistics for each gc-mutator phase be printed?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should memory be protected on release? + */ +public final class ProtectOnRelease extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public ProtectOnRelease() { + super(Options.set, "Protect On Release", + "Should memory be protected on release?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + + +/** + * Should a major GC be performed when a system GC is triggered? + */ +public final class SanityCheck extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public SanityCheck() { + super(Options.set, "Sanity Check", + "Perform sanity checks before and after each collection?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,38 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.mmtk.plan.Plan; +import org.mmtk.utility.Constants; + +/** + * Force frequent collections after amounts of allocation. + */ +public final class StressFactor extends org.vmutil.options.PagesOption { + /** + * Create the option, defaulting to the maximum possible value. + */ + public StressFactor() { + super(Options.set, "Stress Factor", + "Force a collection after this much allocation", + Integer.MAX_VALUE >>> Constants.LOG_BYTES_IN_PAGE); + } + + /** + * Ensure that the value is sensible. + */ + public void validate() { + failIf(this.value < Plan.DEFAULT_POLL_FREQUENCY, + "Stress Factor must be at least equal to plan's poll frequency"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,47 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +import org.vmmagic.pragma.*; + +/** + * The granularity of the trace being produced. + */ +public final class TraceRate extends org.vmutil.options.IntOption + implements org.mmtk.utility.Constants { + /** + * Create the option. + */ + public TraceRate() { + super(Options.set, "Trace Rate", + "The granularity of the trace being produced. By default, the trace has the maximum possible granularity.", + Integer.MAX_VALUE); + } + + /** + * Return the appropriate value. + * + * @return the trace rate. + */ + @Uninterruptible + public int getValue() { + return (this.value < BYTES_IN_ADDRESS) ? 1 : (this.value >> LOG_BYTES_IN_ADDRESS); + } + + /** + * Trace rate must be positive. + */ + protected void validate() { + failIf(value <= 0, "Can not have a negative trace rate"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we shrink/grow the heap to adjust to application working set? + */ +public final class VariableSizeHeap extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public VariableSizeHeap() { + super(Options.set, "Variable Size Heap", + "Should we shrink/grow the heap to adjust to application working set?", + true); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,34 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * GC verbosity level. + */ +public final class Verbose extends org.vmutil.options.IntOption { + /** + * Create the option. + */ + public Verbose() { + super(Options.set, "Verbose", + "GC verbosity level", + 0); + } + + /** + * Only accept non-negative values. + */ + protected void validate() { + failIf(this.value < 0, "Unreasonable verbosity level"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we print verbose fragmentation statistics for the free list allocator? + */ +public final class VerboseFragmentationStats extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public VerboseFragmentationStats() { + super(Options.set, "Verbose Fragmentation Stats", + "Should we print verbose fragmentation statistics for the free list allocator?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Should we display detailed breakdown of where GC time is spent? + */ +public final class VerboseTiming extends org.vmutil.options.BooleanOption { + /** + * Create the option. + */ + public VerboseTiming() { + super(Options.set, "Verbose Timing", + "Should we display detailed breakdown of where GC time is spent?", + false); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.options; + +/** + * Display statistics and options in XML rather than himan-readable + * format. + */ +public final class XmlStats extends org.vmutil.options.BooleanOption { + + /** + * Create the option. + */ + public XmlStats() { + super(Options.set, "Xml Stats", "Print end-of-run statistics in XML format", false); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,253 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.sanitychecker; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.Trace; +import org.mmtk.plan.Simple; +import org.mmtk.plan.TraceLocal; +import org.mmtk.policy.Space; +import org.mmtk.utility.Constants; +import org.mmtk.utility.Log; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class performs sanity checks for Simple collectors. + */ + at Uninterruptible +public final class SanityChecker implements Constants { + + /* Counters */ + public static long referenceCount; + public static long rootReferenceCount; + public static long danglingReferenceCount; + public static long nullReferenceCount; + public static long liveObjectCount; + + public static final int DEAD = -2; + public static final int ALIVE = -1; + public static final int UNSURE = 0; + + public static final int LOG_SANITY_DATA_SIZE = 24; + + /* Tracing */ + public Trace rootTrace; + public Trace checkTrace; + private final SanityDataTable sanityTable; + private boolean preGCSanity; + + /* Local, but we only run the check trace single-threaded. */ + final SanityTraceLocal checkTraceLocal; + + /* Linear scanning */ + private final SanityLinearScan scanner = new SanityLinearScan(this); + + /**************************************************************************** + * Constants + */ + public SanityChecker() { + sanityTable = new SanityDataTable(Plan.sanitySpace, LOG_SANITY_DATA_SIZE); + checkTrace = new Trace(Plan.sanitySpace); + rootTrace = new Trace(Plan.sanitySpace); + checkTraceLocal = new SanityTraceLocal(checkTrace, this); + } + + /** + * Perform any sanity checking collection phases. + * + * @param phaseId The id to proces + * @return True if the phase was handled. + */ + @NoInline + public boolean collectionPhase(int phaseId) { + if (phaseId == Simple.SANITY_SET_PREGC) { + preGCSanity = true; + return true; + } + + if (phaseId == Simple.SANITY_SET_POSTGC) { + preGCSanity = false; + return true; + } + + if (phaseId == Simple.SANITY_PREPARE) { + Log.writeln(""); + Log.write("============================== GC Sanity Checking "); + Log.writeln("=============================="); + Log.writeln(preGCSanity ? "Performing Pre-GC Sanity Checks..." : "Performing Post-GC Sanity Checks..."); + + // Reset counters + referenceCount = 0; + nullReferenceCount = 0; + liveObjectCount = 0; + danglingReferenceCount = 0; + rootReferenceCount = 0; + + // Clear data space + sanityTable.acquireTable(); + + // Root trace + rootTrace.prepareNonBlocking(); + + // Checking trace + checkTrace.prepareNonBlocking(); + checkTraceLocal.prepare(); + return true; + } + + if (phaseId == Simple.SANITY_ROOTS) { + VM.scanning.resetThreadCounter(); + return true; + } + + if (phaseId == Simple.SANITY_BUILD_TABLE) { + // Trace, checking for dangling pointers + checkTraceLocal.completeTrace(); + return true; + } + + if (phaseId == Simple.SANITY_CHECK_TABLE) { + // Iterate over the reachable objects. + Address curr = sanityTable.getFirst(); + while (!curr.isZero()) { + ObjectReference ref = SanityDataTable.getObjectReference(curr); + int normalRC = SanityDataTable.getNormalRC(curr); + int rootRC = SanityDataTable.getRootRC(curr); + if (!preGCSanity) { + int expectedRC = VM.activePlan.global().sanityExpectedRC(ref, rootRC); + switch (expectedRC) { + case SanityChecker.ALIVE: + case SanityChecker.UNSURE: + // Always ok. + break; + case SanityChecker.DEAD: + // Never ok. + Log.write("ERROR: SanityRC = "); + Log.write(normalRC); + Log.write(", SpaceRC = 0 "); + SanityChecker.dumpObjectInformation(ref); + break; + default: + // A mismatch in an RC space + if (normalRC != expectedRC && VM.activePlan.global().lastCollectionFullHeap()) { + Log.write("WARNING: SanityRC = "); + Log.write(normalRC); + Log.write(", SpaceRC = "); + Log.write(expectedRC); + Log.write(" "); + SanityChecker.dumpObjectInformation(ref); + break; + } + } + } + curr = sanityTable.getNext(curr); + } + + if (!preGCSanity && VM.activePlan.global().lastCollectionFullHeap()) { + VM.activePlan.global().sanityLinearScan(scanner); + } + return true; + } + + if (phaseId == Simple.SANITY_RELEASE) { + checkTrace.release(); + sanityTable.releaseTable(); + checkTraceLocal.release(); + + Log.writeln("roots\tobjects\trefs\tnull"); + Log.write(rootReferenceCount);Log.write("\t"); + Log.write(liveObjectCount);Log.write("\t"); + Log.write(referenceCount);Log.write("\t"); + Log.writeln(nullReferenceCount); + + Log.write("========================================"); + Log.writeln("========================================"); + + return true; + } + + return false; + } + + /** + * Process an object during a linear scan of the heap. We have already checked + * all objects in the table. So we are only interested in objects that are not in + * the sanity table here. We are therefore only looking for leaks here. + * + * @param object The object being scanned. + */ + public void scanProcessObject(ObjectReference object) { + if (sanityTable.getEntry(object, false).isZero()) { + // Is this a leak? + int expectedRC = VM.activePlan.global().sanityExpectedRC(object, 0); + + if (expectedRC == SanityChecker.UNSURE) { + // Probably not. + return; + } + + // Possibly + Log.write("WARNING: Possible leak, SpaceRC = "); + Log.write(expectedRC); + Log.write(" "); + SanityChecker.dumpObjectInformation(object); + } + } + + /** + * Process an object during sanity checking, validating data, + * incrementing counters and enqueuing if this is the first + * visit to the object. + * + * @param object The object to mark. + * @param root True If the object is a root. + */ + public void processObject(TraceLocal trace, ObjectReference object, boolean root) { + SanityChecker.referenceCount++; + if (root) SanityChecker.rootReferenceCount++; + + if (object.isNull()) { + SanityChecker.nullReferenceCount++; + return; + } + + if (Plan.SCAN_BOOT_IMAGE && Space.isInSpace(Plan.VM_SPACE, object)) { + return; + } + + // Get the table entry. + Address tableEntry = sanityTable.getEntry(object, true); + + if (SanityDataTable.incRC(tableEntry, root)) { + SanityChecker.liveObjectCount++; + trace.processNode(object); + } + } + + /** + * Print out object information (used for warning and error messages) + * + * @param object The object to dump info for. + */ + public static void dumpObjectInformation(ObjectReference object) { + Log.write(object); + Log.write(" ["); + Log.write(Space.getSpaceForObject(object).getName()); + Log.write("] "); + Log.writeln(VM.objectModel.getTypeDescriptor(object)); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,78 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.sanitychecker; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.Simple; +import org.mmtk.utility.Constants; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class performs sanity checks for Simple collectors. + */ + at Uninterruptible +public final class SanityCheckerLocal implements Constants { + + /* Trace */ + final SanityRootTraceLocal rootTraceLocal; + + /**************************************************************************** + * Constants + */ + public SanityCheckerLocal() { + rootTraceLocal = new SanityRootTraceLocal(Plan.sanityChecker.rootTrace); + } + + /** + * Perform any sanity checking collection phases. + * + * @param phaseId The id to proces + * @param primary Perform local single threaded actions on this thread + * @return True if the phase was handled. + */ + @NoInline + public boolean collectionPhase(int phaseId, boolean primary) { + if (phaseId == Simple.SANITY_PREPARE) { + rootTraceLocal.prepare(); + return true; + } + + if (phaseId == Simple.SANITY_ROOTS) { + VM.scanning.computeGlobalRoots(rootTraceLocal); + VM.scanning.computeThreadRoots(rootTraceLocal); + VM.scanning.computeStaticRoots(rootTraceLocal); + if (Plan.SCAN_BOOT_IMAGE) { + VM.scanning.computeBootImageRoots(rootTraceLocal); + } + rootTraceLocal.flush(); + return true; + } + + if (phaseId == Simple.SANITY_COPY_ROOTS) { + if (primary) { + rootTraceLocal.copyRootValuesTo(Plan.sanityChecker.checkTraceLocal); + } + return true; + } + + if (phaseId == Simple.SANITY_RELEASE) { + rootTraceLocal.release(); + return true; + } + + return false; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,161 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.sanitychecker; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.policy.RawPageSpace; +import org.mmtk.utility.Constants; +import org.mmtk.utility.deque.*; +import org.mmtk.utility.SimpleHashtable; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements a simple hashtable to store and retrieve per + * object information for sanity checking.

    + * + * This class is not thread safe. + */ + at Uninterruptible +public final class SanityDataTable extends SimpleHashtable implements Constants { + + /** The number of bits for the normal reference count */ + private static final int NORMAL_RC_BITS = 25; + + /** The mask for the normal reference count */ + private static final int NORMAL_RC_MASK = (1 << 25) - 1; + + /** The shift for the root reference count */ + private static final int ROOT_RC_SHIFT = NORMAL_RC_BITS; + + /** The increment to use for normal increments */ + private static final int NORMAL_RC_INC = 1; + + /** The increment to use for root increments */ + private static final int ROOT_RC_INC = 1 << ROOT_RC_SHIFT; + + /** + * Create a new data table of a specified size. + * + * @param rps The space to acquire the data structure from. + * @param logSize The log of the number of table entries. + */ + public SanityDataTable(RawPageSpace rps, int logSize) { + super(rps, logSize, Extent.fromIntSignExtend(BYTES_IN_WORD)); + } + + /** + * Increment the data word for an object. + * + * @param entry The table entry. + * @param root True if this is a root reference. + * @return True if this is the first ref to that object. + */ + @Inline + public static boolean incRC(Address entry, boolean root) { + Address data = SimpleHashtable.getPayloadAddress(entry); + int old = data.loadInt(); + data.store(old + (root ? ROOT_RC_INC : NORMAL_RC_INC)); + return (old == 0); + } + + /** + * Push any entries that are only in this table, and not the + * passed table. This does not compare values. + * + * @param other The table to use for comparison. + * @param deque The buffer to push results onto. + */ + public void pushNotInOther(SanityDataTable other, + ObjectReferenceDeque deque) { + Address entry = getFirst(); + while (!entry.isZero()) { + Word key = SimpleHashtable.getKey(entry); + if (!other.contains(key)) { + deque.push(key.toAddress().toObjectReference()); + } + entry = getNext(entry); + } + } + + + /** + * Given an address of an entry, read the reference count, + * excluding root references. + * + * @param entry The entry + * @return The reference count. + */ + public static int getNormalRC(Address entry) { + return SimpleHashtable.getPayloadAddress(entry).loadInt() & NORMAL_RC_MASK; + } + + /** + * Given an address of an entry, read the root reference count. + * + * @param entry The entry + * @return The root reference count. + */ + public static int getRootRC(Address entry) { + return SimpleHashtable.getPayloadAddress(entry).loadInt() >>> ROOT_RC_SHIFT; + } + + /** + * Given an address of an entry, read the total reference count. + * + * @param entry The entry + * @return The total reference count. + */ + public static int getRC(Address entry) { + int val = SimpleHashtable.getPayloadAddress(entry).loadInt(); + return (val & NORMAL_RC_MASK) + val >>> ROOT_RC_SHIFT; + } + + /** + * Given an address of an entry, read the reference component. + * + * @param entry The entry + * @return The object reference. + */ + public static ObjectReference getObjectReference(Address entry) { + return SimpleHashtable.getKey(entry).toAddress().toObjectReference(); + } + + /** + * Forward data table using the supplied trace. Note that the data is + * not hashed correctly, so only enumeration can be used without + * rehashing. + * + * @param trace The trace to use. + */ + public void forwardTable(TraceLocal trace) { + Address entry = getFirst(); + while (!entry.isZero()) { + ObjectReference obj = getObjectReference(entry); + SimpleHashtable.replaceKey(entry, trace.getForwardedReference(obj).toAddress().toWord()); + entry = getNext(entry); + } + } + + /** + * Get an entry for an object. + * + * @param object The object to find an entry for. + * @param create Create an entry if none exists? + * @return The entry address. + */ + public Address getEntry(ObjectReference object, boolean create) { + return super.getEntry(object.toAddress().toWord(), create); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,34 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.sanitychecker; + +import org.mmtk.utility.alloc.LinearScan; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.ObjectReference; + +/** + * This class performs sanity checks for Simple collectors. + */ + at Uninterruptible +final class SanityLinearScan extends LinearScan { + + private final SanityChecker sanityChecker; + public SanityLinearScan(SanityChecker sanityChecker) { + this.sanityChecker = sanityChecker; + } + + public void scan(ObjectReference object) { + sanityChecker.scanProcessObject(object); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,101 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.sanitychecker; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the parallel root-gathering part of a sanity check. + */ + at Uninterruptible +public final class SanityRootTraceLocal extends TraceLocal { + + /** + * Constructor + */ + public SanityRootTraceLocal(Trace trace) { + super(trace); + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * Copy root values across to the 'real' single-threaded trace that will do + * the sanity checking. + */ + @Inline + public void copyRootValuesTo(TraceLocal trace) { + while (!rootLocations.isEmpty()) { + ObjectReference object = rootLocations.pop().loadObjectReference(); + if (!object.isNull()) { + trace.traceObject(object, true); + } + } + while (!values.isEmpty()) { + trace.traceObject(values.pop(), true); + } + } + + /** + * Process delayed roots. This does not make sense for SanityRootTraceLocal. + * are empty. + */ + @Inline + public void processRoots() { + VM.assertions.fail("SanityRootTraceLocal.processRoots called."); + } + + /** + * Finishing processing all GC work. This does not make sense for SanityRootTraceLocal. + */ + @Inline + public void completeTrace() { + VM.assertions.fail("SanityRootTraceLocal.completeTrace called."); + } + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * @param object The object to be traced. + * @param root Is this object a root? + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object, boolean root) { + if (!root) VM.assertions.fail("SanityRootTraceLocal.traceObject called for non-root object."); + if (!object.isNull()) { + values.push(object); + } + return object; + } + + /** + * Will this object move from this point on, during the current trace ? + * + * @param object The object to query. + * @return True if the object will not move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + // We never move objects! + return true; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,66 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.sanitychecker; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.Trace; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.*; + +/** + * This class implements the simply sanity closure. + */ + at Uninterruptible +public final class SanityTraceLocal extends TraceLocal { + + private final SanityChecker sanityChecker; + + /** + * Constructor + */ + public SanityTraceLocal(Trace trace, SanityChecker sanityChecker) { + super(trace); + this.sanityChecker = sanityChecker; + } + + /**************************************************************************** + * + * Object processing and tracing + */ + + /** + * This method is the core method during the trace of the object graph. + * The role of this method is to: + * + * @param object The object to be traced. + * @param root Is this object a root? + * @return The new reference to the same object instance. + */ + @Inline + public ObjectReference traceObject(ObjectReference object, boolean root) { + sanityChecker.processObject(this, object, root); + return object; + } + + /** + * Will this object move from this point on, during the current trace ? + * + * @param object The object to query. + * @return True if the object will not move. + */ + public boolean willNotMoveInCurrentCollection(ObjectReference object) { + // We never move objects! + return true; + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,200 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.mmtk.utility.Log; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements a simple boolean counter (counting number of + * phases where some boolean event is true). + */ + at Uninterruptible public class BooleanCounter extends Counter { + + /**************************************************************************** + * + * Instance variables + */ + + private final boolean[] state; + + protected int total = 0; + private boolean running = false; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name to be associated with this counter + */ + public BooleanCounter(String name) { + this(name, true, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + */ + public BooleanCounter(String name, boolean start) { + this(name, start, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + * @param mergephases True if this counter does not separately + * report GC and Mutator phases. + */ + public BooleanCounter(String name, boolean start, boolean mergephases) { + super(name, start, mergephases); + state = new boolean[Stats.MAX_PHASES]; + for (int i = 0; i < Stats.MAX_PHASES; i++) + state[i] = false; + } + + /**************************************************************************** + * + * Counter-specific methods + */ + + /** + * Set the boolean to true for this phase, increment the total. + */ + public void set() { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Stats.phase == Stats.MAX_PHASES -1 || !state[Stats.phase]); + state[Stats.phase] = true; + total++; + } + + /**************************************************************************** + * + * Generic counter control methods: start, stop, print etc + */ + + /** + * Start this counter + */ + protected void start() { + if (!Stats.gatheringStats) return; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running); + running = true; + } + + /** + * Stop this counter + */ + protected void stop() { + if (!Stats.gatheringStats) return; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running); + running = false; + } + + /** + * The phase has changed (from GC to mutator or mutator to GC). + * Take action with respect to the last phase if necessary. + * Do nothing in this case. + * + * @param oldPhase The last phase + */ + void phaseChange(int oldPhase) {} + + /** + * Print the value of this counter for the given phase. Print '0' + * for false, '1' for true. + * + * @param phase The phase to be printed + */ + protected final void printCount(int phase) { + if (VM.VERIFY_ASSERTIONS && mergePhases()) + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1)); + if (mergePhases()) + printValue((state[phase] || state[phase + 1]) ? 1 : 0); + else + printValue((state[phase]) ? 1 : 0); + } + + /** + * Print the current total number of 'true' phases for this counter + */ + protected final void printTotal() { + int total = 0; + for (int p = 0; p <= Stats.phase; p++) { + total += (state[p]) ? 1 : 0; + } + printValue(total); + } + + /** + * Print the current total number of 'true' phases for either the + * mutator or GC phase + * + * @param mutator True if the total for the mutator phases is to be + * printed (otherwise the total for the GC phases will be printed). + */ + protected final void printTotal(boolean mutator) { + int total = 0; + for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) { + total += (state[p]) ? 1 : 0; + } + printValue(total); + } + + /** + * Print the current minimum value for either the mutator or GC + * phase. Do nothing in this case. + * + * @param mutator True if the minimum for the mutator phase is to be + * printed (otherwise the minimum for the GC phase will be printed). + */ + protected final void printMin(boolean mutator) {} + + /** + * Print the current maximum value for either the mutator or GC + * phase. Do nothing in this case. + * + * @param mutator True if the maximum for the mutator phase is to be + * printed (otherwise the maximum for the GC phase will be printed). + */ + protected final void printMax(boolean mutator) {} + + /** + * Print the given value + * + * @param value The value to be printed + */ + void printValue(int value) { + Log.write(value); + } + + /** + * Print statistics for the most recent phase + */ + public void printLast() { + if (Stats.phase > 0) printCount(Stats.phase - 1); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,173 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.vmmagic.pragma.*; + +/** + * + * This abstract class describes the interface of a generic counter. + */ + at Uninterruptible public abstract class Counter { + + /**************************************************************************** + * + * Instance variables + */ + + private final String name; + private final boolean start; + private final boolean mergephases; + + /** + * Allow for counters whose values are too complex to be simply printed out. + */ + protected boolean complex = false; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name to be associated with this counter + */ + Counter(String name) { + this(name, true, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + */ + Counter(String name, boolean start) { + this(name, start, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + * @param mergephases True if this counter does not separately + * report GC and Mutator phases. + */ + Counter(String name, boolean start, boolean mergephases) { + this.name = name; + this.start = start; + this.mergephases = mergephases; + Stats.newCounter(this); + } + + /**************************************************************************** + * + * Counter control methods: start, stop, print etc + */ + + /** + * Start this counter + */ + abstract void start(); + + /** + * Stop this counter + */ + abstract void stop(); + + /** + * The phase has changed (from GC to mutator or mutator to GC). + * Take action with respect to the last phase if necessary. + * + * @param oldPhase The last phase + */ + abstract void phaseChange(int oldPhase); + + /** + * Print the value of this counter for the given phase + * + * @param phase The phase to be printed + */ + abstract void printCount(int phase); + + /** + * Print the current total for this counter + */ + abstract void printTotal(); + + /** + * Print the current total for either the mutator or GC phase + * + * @param mutator True if the total for the mutator phases is to be + * printed (otherwise the total for the GC phases will be printed). + */ + abstract void printTotal(boolean mutator); + + /** + * Print the current minimum value for either the mutator or GC phase + * + * @param mutator True if the minimum for the mutator phase is to be + * printed (otherwise the minimum for the GC phase will be printed). + */ + abstract void printMin(boolean mutator); + + /** + * Print the current maximum value for either the mutator or GC phase + * + * @param mutator True if the maximum for the mutator phase is to be + * printed (otherwise the maximum for the GC phase will be printed). + */ + abstract void printMax(boolean mutator); + + /** + * Print statistics for the most recent phase + */ + public void printLast() { + if (Stats.phase > 0) printCount(Stats.phase - 1); + } + + + /**************************************************************************** + * + * Accessor methods + */ + + /** + * Return the name of this counter + * @return The name of this counter + */ + String getName() { return name; } + + /** + * Return true if this counter is implicitly started when + * startAll() is called. + * @return True if this counter is implicitly started when + * startAll() is called. + */ + boolean getStart() { return start; } + + /** + * Return true if this counter will merge stats for GC and mutator phases. + * @return True if this counter will merge stats for GC and mutator phases. + */ + boolean mergePhases() { return mergephases; } + + boolean isComplex() { return complex; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,230 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.mmtk.utility.Log; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements a simple event counter (counting number + * events that occur for each phase). + */ + at Uninterruptible public class EventCounter extends Counter { + + /**************************************************************************** + * + * Instance variables + */ + + private final long[] count; + + protected long totalCount = 0; + private boolean running = false; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name to be associated with this counter + */ + public EventCounter(String name) { + this(name, true, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + */ + public EventCounter(String name, boolean start) { + this(name, start, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + * @param mergephases True if this counter does not separately + * report GC and Mutator phases. + */ + public EventCounter(String name, boolean start, boolean mergephases) { + super(name, start, mergephases); + count = new long[Stats.MAX_PHASES]; + } + + /**************************************************************************** + * + * Counter-specific methods + */ + + /** + * Increment the event counter + */ + public void inc() { + if (running) inc(1); + } + + /** + * Increment the event counter by value + * + * @param value The amount by which the counter should be incremented. + */ + public void inc(int value) { + if (running) totalCount += value; + } + + /**************************************************************************** + * + * Generic counter control methods: start, stop, print etc + */ + + /** + * Start this counter + */ + protected void start() { + if (!Stats.gatheringStats) return; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running); + running = true; + } + + /** + * Stop this counter + */ + protected void stop() { + if (!Stats.gatheringStats) return; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running); + running = false; + } + + /** + * The phase has changed (from GC to mutator or mutator to GC). + * Take action with respect to the last phase if necessary. + * Do nothing in this case. + * + * @param oldPhase The last phase + */ + void phaseChange(int oldPhase) { + if (running) { + count[oldPhase] = totalCount; + totalCount = 0; + } + } + + /** + * Print the value of this counter for the given phase. Print '0' + * for false, '1' for true. + * + * @param phase The phase to be printed + */ + protected final void printCount(int phase) { + if (VM.VERIFY_ASSERTIONS && mergePhases()) + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1)); + if (mergePhases()) + printValue(count[phase] + count[phase + 1]); + else + printValue(count[phase]); + } + + /** + * Print the current value for this counter (mid-phase) + */ + public final void printCurrent() { + printValue(totalCount); + } + + /** + * Print the current total for this counter + */ + public final void printTotal() { + long total = 0; + for (int p = 0; p <= Stats.phase; p++) { + total += count[p]; + } + printValue(total); + } + + /** + * Print the current total for either the mutator or GC phase + * + * @param mutator True if the total for the mutator phases is to be + * printed (otherwise the total for the GC phases will be printed). + */ + protected final void printTotal(boolean mutator) { + long total = 0; + for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) { + total += count[p]; + } + printValue(total); + } + + /** + * Print the current minimum value for either the mutator or GC + * phase. + * + * @param mutator True if the minimum for the mutator phase is to be + * printed (otherwise the minimum for the GC phase will be printed). + */ + protected final void printMin(boolean mutator) { + int p = (mutator) ? 0 : 1; + long min = count[p]; + for (; p < Stats.phase; p += 2) { + if (count[p] < min) min = count[p]; + } + printValue(min); + } + + /** + * Print the current maximum value for either the mutator or GC + * phase. + * + * @param mutator True if the maximum for the mutator phase is to be + * printed (otherwise the maximum for the GC phase will be printed). + */ + protected final void printMax(boolean mutator) { + int p = (mutator) ? 0 : 1; + long max = count[p]; + for (; p < Stats.phase; p += 2) { + if (count[p] > max) max = count[p]; + } + printValue(max); + } + + /** + * Print the given value + * + * @param value The value to be printed + */ + void printValue(long value) { + Log.write(value); + } + + /** + * Print statistics for the most recent phase + */ + public void printLast() { + if (Stats.phase > 0) printCount(Stats.phase - 1); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,215 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.mmtk.utility.Log; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This abstract class implements a simple counter (counting some + * integer (long) value for each phase). + */ + at Uninterruptible public abstract class LongCounter extends Counter { + + /**************************************************************************** + * + * Instance variables + */ + + private final long[] count; + + private long startValue = 0; + protected long totalCount = 0; + private boolean running = false; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name to be associated with this counter + */ + LongCounter(String name) { + this(name, true, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + */ + LongCounter(String name, boolean start) { + this(name, start, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + * @param mergephases True if this counter does not separately + * report GC and Mutator phases. + */ + LongCounter(String name, boolean start, boolean mergephases) { + super(name, start, mergephases); + count = new long[Stats.MAX_PHASES]; + } + + /**************************************************************************** + * + * Counter-specific methods + */ + protected abstract long getCurrentValue(); + + /**************************************************************************** + * + * Generic counter control methods: start, stop, print etc + */ + + /** + * Start this counter + */ + public void start() { + if (!Stats.gatheringStats) return; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running); + running = true; + startValue = getCurrentValue(); + } + + /** + * Stop this counter + */ + public void stop() { + if (!Stats.gatheringStats) return; + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running); + running = false; + long delta = getCurrentValue() - startValue; + count[Stats.phase] += delta; + totalCount += delta; + } + + /** + * The phase has changed (from GC to mutator or mutator to GC). + * Take action with respect to the last phase if necessary. + * Do nothing in this case. + * + * @param oldPhase The last phase + */ + protected void phaseChange(int oldPhase) { + if (running) { + long now = getCurrentValue(); + long delta = now - startValue; + count[oldPhase] += delta; + totalCount += delta; + startValue = now; + } + } + + /** + * Print the value of this counter for the given phase. Print '0' + * for false, '1' for true. + * + * @param phase The phase to be printed + */ + protected final void printCount(int phase) { + if (VM.VERIFY_ASSERTIONS && mergePhases()) + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1)); + if (mergePhases()) + printValue(count[phase] + count[phase + 1]); + else + printValue(count[phase]); + } + + /** + * Print the current total for this counter + */ + public final void printTotal() { + printValue(totalCount); + } + + + /** + * Get the total as at the lasts phase + * + * @return The total as at the last phase + */ + long getLastTotal() { + return totalCount; + } + + /** + * Print the current total for either the mutator or GC phase + * + * @param mutator True if the total for the mutator phases is to be + * printed (otherwise the total for the GC phases will be printed). + */ + protected final void printTotal(boolean mutator) { + long total = 0; + for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) { + total += count[p]; + } + printValue(total); + } + + /** + * Print the current minimum value for either the mutator or GC + * phase. + * + * @param mutator True if the minimum for the mutator phase is to be + * printed (otherwise the minimum for the GC phase will be printed). + */ + protected final void printMin(boolean mutator) { + int p = (mutator) ? 0 : 1; + long min = count[p]; + for (; p < Stats.phase; p += 2) { + if (count[p] < min) min = count[p]; + } + printValue(min); + } + + /** + * Print the current maximum value for either the mutator or GC + * phase. + * + * @param mutator True if the maximum for the mutator phase is to be + * printed (otherwise the maximum for the GC phase will be printed). + */ + protected final void printMax(boolean mutator) { + int p = (mutator) ? 0 : 1; + long max = count[p]; + for (; p < Stats.phase; p += 2) { + if (count[p] > max) max = count[p]; + } + printValue(max); + } + + /** + * Print the given value + * + * @param value The value to be printed + */ + void printValue(long value) { + Log.write(value); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,78 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements a simple performance counter, used to gather + * data from hardware performance counters. + */ + at Uninterruptible +public class PerfCounter extends LongCounter { + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name to be associated with this counter + */ + public PerfCounter(String name) { + this(name, true, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started at + * boot time (otherwise the counter must be explicitly started). + */ + public PerfCounter(String name, boolean start) { + this(name, start, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started at + * boot time (otherwise the counter must be explicitly started). + * @param gconly True if this counter only pertains to (and + * therefore functions during) GC phases. + */ + public PerfCounter(String name, boolean start, boolean gconly) { + super(name, start, gconly); + } + + /**************************************************************************** + * + * Counter-specific methods + */ + + /** + * Get the current value for this counter + * + * @return The current value for this counter + */ + @Inline + protected final long getCurrentValue() { + return VM.statistics.perfCtrReadMetric(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,138 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.vmmagic.pragma.*; + +/** + * This class implements a simple counter of events of different sizes + * (eg object allocations, where total number of objects and total + * volume of objects would be counted). + * + * The counter is trivially composed from two event counters (one for + * counting the number of events, the other for counting the volume). + */ + at Uninterruptible public class SizeCounter { + + /**************************************************************************** + * + * Instance variables + */ + private EventCounter units; + private EventCounter volume; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name to be associated with this counter + */ + public SizeCounter(String name) { + this(name, true, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + */ + public SizeCounter(String name, boolean start) { + this(name, start, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + * @param mergephases True if this counter does not separately + * report GC and Mutator phases. + */ + public SizeCounter(String name, boolean start, boolean mergephases) { + units = new EventCounter(name, start, mergephases); + volume = new EventCounter(name + "Volume", start, mergephases); + } + + /**************************************************************************** + * + * Counter-specific methods + */ + + /** + * Increment the event counter by value + * + * @param value The amount by which the counter should be incremented. + */ + public void inc(int value) { + units.inc(); + volume.inc(value); + } + + /**************************************************************************** + * + * Generic counter control methods: start, stop, print etc + */ + + /** + * Start this counter + */ + public void start() { + units.start(); + volume.start(); + } + + /** + * Stop this counter + */ + public void stop() { + units.stop(); + volume.stop(); + } + + /** + * Print current (mid-phase) units + */ + public void printCurrentUnits() { + units.printCurrent(); + } + + /** + * Print (mid-phase) volume + */ + public void printCurrentVolume() { + volume.printCurrent(); + } + + /** + * Print units + */ + public void printUnits() { + units.printTotal(); + } + + /** + * Print volume + */ + public void printVolume() { + volume.printTotal(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,378 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.mmtk.plan.Plan; +import org.mmtk.utility.Log; +import org.mmtk.utility.options.Options; +import org.mmtk.utility.options.PrintPhaseStats; +import org.mmtk.utility.options.XmlStats; + +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements basic statistics functionality + */ + at Uninterruptible public class Stats { + + /**************************************************************************** + * + * Class variables + */ + + public static final boolean GATHER_MARK_CONS_STATS = false; + + /** Maximum number of gc/mutator phases that can be counted */ + static final int MAX_PHASES = 1 << 12; + /** Maximum number of counters that can be in operation */ + static final int MAX_COUNTERS = 100; + + private static int counters = 0; + private static Counter[] counter; + static int phase = 0; + private static int gcCount = 0; + static boolean gatheringStats = false; + static boolean exceededPhaseLimit = false; + + /**************************************************************************** + * + * Initialization + */ + + /** + * Class initializer. This is executed prior to bootstrap + * (i.e. at "build" time). This is where key global + * instances are allocated. These instances will be incorporated + * into the boot image by the build process. + */ + static { + counter = new Counter[MAX_COUNTERS]; + Options.printPhaseStats = new PrintPhaseStats(); + Options.xmlStats = new XmlStats(); + } + + /** + * Add a new counter to the set of managed counters. + * + * @param ctr The counter to be added. + */ + @Interruptible + static void newCounter(Counter ctr) { + if (counters < (MAX_COUNTERS - 1)) { + counter[counters++] = ctr; + } else { + Log.writeln("Warning: number of stats counters exceeds maximum"); + } + } + + /** + * Start a new GC phase. This means notifying each counter of the + * phase change. + */ + public static void startGC() { + gcCount++; + if (!gatheringStats) return; + if (phase < MAX_PHASES - 1) { + for (int c = 0; c < counters; c++) { + counter[c].phaseChange(phase); + } + phase++; + } else if (!exceededPhaseLimit) { + Log.writeln("Warning: number of GC phases exceeds MAX_PHASES"); + exceededPhaseLimit = true; + } + } + + /** + * End a GC phase. This means notifying each counter of the phase + * change. + */ + public static void endGC() { + if (!gatheringStats) return; + if (phase < MAX_PHASES - 1) { + for (int c = 0; c < counters; c++) { + counter[c].phaseChange(phase); + } + phase++; + } else if (!exceededPhaseLimit) { + Log.writeln("Warning: number of GC phases exceeds MAX_PHASES"); + exceededPhaseLimit = true; + } + } + + /** + * Start all implicitly started counters (i.e. those for whom + * start == true). + */ + public static void startAll() { + if (gatheringStats) { + Log.writeln("Error: calling Stats.startAll() while stats running"); + Log.writeln(" verbosity > 0 and the harness mechanism may be conflicitng"); + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); + } + gatheringStats = true; + for (int c = 0; c < counters; c++) { + if (counter[c].getStart()) + counter[c].start(); + } + if (Options.xmlStats.getValue()) { + Xml.begin(); + Xml.openTag("mmtk-stats"); + Xml.end(); + } + } + + /** + * Stop all counters + */ + @Interruptible + public static void stopAll() { + stopAllCounters(); + Stats.printStats(); + if (Options.xmlStats.getValue()) { + Xml.begin(); + Xml.closeTag("mmtk-stats"); + Xml.end(); + } + } + + /** + * Stop all counters + */ + private static void stopAllCounters() { + for (int c = 0; c < counters; c++) { + if (counter[c].getStart()) + counter[c].stop(); + } + gatheringStats = false; + } + + @Interruptible + public static void printStats() { + if (exceededPhaseLimit) { + Log.writeln("Warning: number of GC phases exceeds MAX_PHASES. Statistics are truncated."); + } + if (Options.xmlStats.getValue()) + printStatsXml(); + else + printStatsPlain(); + } + + /** + * Print out statistics + */ + @Interruptible + public static void printStatsPlain() { + if (Options.printPhaseStats.getValue()) + printPhases(); + printTotals(); + } + + /** + * Print out statistics totals + */ + @Interruptible + public static void printTotals() { + Log.writeln("============================ MMTk Statistics Totals ============================"); + printColumnNames(); + Log.write(phase/2); Log.write("\t"); + for (int c = 0; c < counters; c++) { + if (counter[c].mergePhases()) { + counter[c].printTotal(); Log.write("\t"); + } else { + counter[c].printTotal(true); Log.write("\t"); + counter[c].printTotal(false); Log.write("\t"); + } + } + Log.writeln(); + Log.write("Total time: "); + Plan.totalTime.printTotal(); Log.writeln(" ms"); + Log.writeln("------------------------------ End MMTk Statistics -----------------------------"); + } + + /** + * Print out statistics for each mutator/gc phase + */ + @Interruptible + public static void printPhases() { + Log.writeln("--------------------- MMTk Statistics Per GC/Mutator Phase ---------------------"); + printColumnNames(); + for (int p = 0; p <= phase; p += 2) { + Log.write((p/2)+1); Log.write("\t"); + for (int c = 0; c < counters; c++) { + if (counter[c].mergePhases()) { + counter[c].printCount(p); Log.write("\t"); + } else { + counter[c].printCount(p); Log.write("\t"); + counter[c].printCount(p+1); Log.write("\t"); + } + } + Log.writeln(); + } + } + + /** + * Print out statistics column names + */ + @Interruptible + private static void printColumnNames() { + Log.write("GC\t"); + for (int c = 0; c < counters; c++) { + if (counter[c].mergePhases()) { + Log.write(counter[c].getName()); + Log.write("\t"); + } else { + Log.write(counter[c].getName()); + Log.write(".mu\t"); + Log.write(counter[c].getName()); + Log.write(".gc\t"); + } + } + Log.writeln(); + } + + /* **************************************************************** + * + * Statistics output in xml format + */ + + /** + * Print command-line options and statistics in XML format + */ + @Interruptible + public static void printStatsXml() { + Xml.begin(); + Options.set.logXml(); + VM.config.printConfigXml(); + if (Options.printPhaseStats.getValue()) + printPhasesXml(); + printTotalsXml(); + Xml.end(); + } + + private static void openStatXml(String name) { + Xml.openMinorTag("stat"); + Xml.attribute("name", name); + } + + private static void closeStatXml() { + Xml.closeMinorTag(); + } + + enum Phase { + MUTATOR("mu"), GC("gc"), COMBINED("all"); + + private final String name; + Phase(String name) { + this.name = name; + } + public String toString() { return name; } + } + + /** + * Print out statistics totals in Xml format + */ + @Interruptible + public static void printTotalsXml() { + Xml.openTag("mmtk-stats-totals"); + Xml.singleValue("gc", phase/2); + for (int c = 0; c < counters; c++) { + if (!counter[c].isComplex()) + if (counter[c].mergePhases()) { + printTotalXml(counter[c],Phase.COMBINED); + } else { + printTotalXml(counter[c],Phase.MUTATOR); + printTotalXml(counter[c],Phase.GC); + } + } + Xml.singleValue("total-time",Plan.totalTime.getTotalMillis(),"ms"); + Xml.closeTag("mmtk-stats-totals"); + } + + /** + * Print a single total in an xml tag + * + * @param c The counter + * @param phase The phase + */ + @Interruptible + private static void printTotalXml(Counter c, Phase phase) { + openStatXml(c.getName()); + Xml.openAttribute("value"); + if (phase == Phase.COMBINED) { + c.printTotal(); + } else { + c.printTotal(phase == Phase.MUTATOR); + Xml.closeAttribute(); + Xml.openAttribute("phase"); + Log.write(phase.toString()); + } + Xml.closeAttribute(); + closeStatXml(); + } + + /** + * Print a single phase counter in an xml tag + * + * @param c The counter + * @param p The phase number + * @param phase The phase (null, "mu" or "gc") + */ + @Interruptible + private static void printPhaseStatXml(Counter c, int p, Phase phase) { + openStatXml(c.getName()); + Xml.openAttribute("value"); + if (phase == Phase.COMBINED) { + c.printCount(p); + } else { + c.printCount(p); + Xml.closeAttribute(); + Xml.openAttribute("phase"); + Log.write(phase.name); + } + Xml.closeAttribute(); + closeStatXml(); + } + + /** + * Print out statistics for each mutator/gc phase in Xml format + */ + @Interruptible + public static void printPhasesXml() { + Xml.openTag("mmtk-stats-per-gc"); + for (int p = 0; p <= phase; p += 2) { + Xml.openTag("phase",false); + Xml.attribute("gc",(p/2)+1); + Xml.closeMinorTag(); + for (int c = 0; c < counters; c++) { + if (!counter[c].isComplex()) + if (counter[c].mergePhases()) { + printPhaseStatXml(counter[c],p,Phase.COMBINED); + } else { + printPhaseStatXml(counter[c],p,Phase.MUTATOR); + printPhaseStatXml(counter[c],p,Phase.GC); + } + } + Xml.closeTag("phase"); + } + Xml.closeTag("mmtk-stats-per-gc"); + } + + /** @return The GC count (inclusive of any in-progress GC) */ + public static int gcCount() { return gcCount; } + + /** @return True if currently gathering stats */ + public static boolean gatheringStats() { return gatheringStats; } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,145 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.mmtk.utility.Log; +import org.mmtk.vm.VM; + +import org.vmmagic.pragma.*; + +/** + * This class implements a simple timer. + */ + at Uninterruptible public class Timer extends LongCounter { + + /**************************************************************************** + * + * Initialization + */ + + /** + * Constructor + * + * @param name The name to be associated with this counter + */ + public Timer(String name) { + this(name, true, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + */ + public Timer(String name, boolean start) { + this(name, start, false); + } + + /** + * Constructor + * + * @param name The name to be associated with this counter + * @param start True if this counter is to be implicitly started + * when startAll() is called (otherwise the counter + * must be explicitly started). + * @param mergephases True if this counter does not separately + * report GC and Mutator phases. + */ + public Timer(String name, boolean start, boolean mergephases) { + super(name, start, mergephases); + } + + /**************************************************************************** + * + * Counter-specific methods + */ + + /** + * Get the current value for this timer + * + * @return The current value for this timer + */ + @Inline + protected final long getCurrentValue() { + return VM.statistics.nanoTime(); + } + + /** + * Print the total in microseconds + */ + final void printTotalMicro() { + printMicro(totalCount); + } + + /** + * Print the total in milliseconds + */ + public final void printTotalMillis() { + printMillis(totalCount); + } + + /** + * Print the total in seconds + */ + public final void printTotalSecs() { + printSecs(totalCount); + } + + /** + * Print a value (in milliseconds) + * + * @param value The value to be printed + */ + final void printValue(long value) { + printMillis(value); + } + + /** + * Print a value in microseconds + * + * @param value The value to be printed + */ + final void printMicro(long value) { + Log.write(1000 * VM.statistics.nanosToMillis(value)); + } + + /** + * Print a value in milliseconds + * + * @param value The value to be printed + */ + final void printMillis(long value) { + Log.write(VM.statistics.nanosToMillis(value)); + } + + /** + * Print a value in seconds + * + * @param value The value to be printed + */ + final void printSecs(long value) { + Log.write(VM.statistics.nanosToSecs(value)); + } + + /** + * Get the current value of the timer in milliseconds + */ + final double getTotalMillis() { + return VM.statistics.nanosToMillis(totalCount); + } + +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,300 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.utility.statistics; + +import org.mmtk.utility.Log; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Word; + +/** + * Utility class for writing statistics out in XML format. + */ + at Uninterruptible +public class Xml { + /** + * Mark the start of XML output + */ + public static void begin() { + Log.writeln(" "); + } + + /** + * Mark the end of XML output + */ + public static void end() { + Log.writeln(" "); + } + + /** + * Close the innermost XML tag and pop it from the stack. + */ + public static void closeTag(String name) { + Log.write(""); + } + + /** + * Open an XML tag. + * + * @param name Tag name + * @param endTag Should the tag be closed, or left open for + * adding additional attributes + */ + static void openTag(String name, boolean endTag) { + openMinorTag(name); + if (endTag) + closeTag(false); + } + + /** + * Open a simple XML entity. + * + * @param name Name of the entity + */ + static void openTag(String name) { openTag(name,true); } + + /** + * Output a "stat" entity, with a given name, doublevalue and optionally, units. + * + * @param name Name of the entity + * @param value The value of the entity + * @param units The units, or null for no units. + */ + public static void singleValue(String name, double value, String units) { + openMinorTag("stat"); + attribute("name",name); + attribute("value",value); + if (units != null) attribute("units",units); + closeMinorTag(); + } + + /** + * Convenience version of singleValue where units are not specified. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void singleValue(String name, double value) { + singleValue(name,value,null); + } + + /** + * Output a "config" entity, with a given name and booleanvalue. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void configItem(String name, boolean value) { + openMinorTag("conf"); + attribute("name",name); + attribute("value",value); + closeMinorTag(); + } + + /** + * Output a "config" entity, with a given name and Stringvalue. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void configItem(String name, String value) { + openMinorTag("conf"); + attribute("name",name); + attribute("value",value); + closeMinorTag(); + } + + /** + * Output a "stat" entity, with a given name, long value and + * optionally, units. + * + * @param name Name of the entity + * @param value The value of the entity + * @param units The units, or null for no units. + */ + public static void singleValue(String name, long value, String units) { + openMinorTag("stat"); + attribute("name",name); + attribute("value",value); + if (units != null) attribute("units",units); + closeMinorTag(); + } + + /** + * Convenience version of singleValue where units are not specified. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void singleValue(String name, long value) { + singleValue(name,value,null); + } + + /** + * Add a word-valued attribute to an open XML tag. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void attribute(String name, Word value) { + openAttribute(name); Log.write(value); closeAttribute(); + } + + /** + * Add a byte[]-valued attribute to an open XML tag. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void attribute(String name, byte[] value) { + openAttribute(name); Log.write(value); closeAttribute(); + } + + /** + * Add a String-valued attribute to an open XML tag. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void attribute(String name, String value) { + openAttribute(name); Log.write(value); closeAttribute(); + } + + /** + * Add a boolean-valued attribute to an open XML tag. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void attribute(String name, boolean value) { + openAttribute(name); Log.write(value); closeAttribute(); + } + + /** + * Add a double-valued attribute to an open XML tag. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void attribute(String name, double value) { + openAttribute(name); Log.write(value); closeAttribute(); + } + + /** + * Add a long-valued attribute to an open XML tag. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void attribute(String name, long value) { + openAttribute(name); Log.write(value); closeAttribute(); + } + + /** + * Add an int-valued attribute to an open XML tag. + * + * @param name Name of the entity + * @param value The value of the entity + */ + public static void attribute(String name, int value) { + openAttribute(name); Log.write(value); closeAttribute(); + } + + /** + * Close an attribute (actually a simple close-quote) + */ + public static void closeAttribute() { + Log.write("\""); + } + + /** + * Open an attribute (write "{name}=\") + * + * @param name Name of the entity + */ + public static void openAttribute(String name) { + Log.write(" "); Log.write(name); Log.write("=\""); + } + + /** + * Start a tag + */ + public static void startTag() { + Log.write("<"); + } + + /** + * End a tag, optionally closing it (if it is a simple entity) + * + * @param close If true, close the tag with "/>" rather than ">" + */ + public static void closeTag(boolean close) { + closeTag(close,true); + } + + /** + * End a tag, optionally closing it (if it is a simple entity), + * and optionally printing end-of-line + * + * @param close If true, close the tag with "/>" rather than ">" + * @param endLine If true end the current line. + */ + public static void closeTag(boolean close, boolean endLine) { + if (close) Log.write("/"); + Log.write(">"); + if (endLine) Log.writeln(); + } + + /** + * Close a tag with a "/>" + */ + public static void closeMinorTag() { + closeTag(true,true); + } + + /** + * Open a tag without pushing it on the tag stack - must end this + * with a call to closeMinorTag() + * + * @param name Name of the entity + */ + public static void openMinorTag(String name) { + Log.write("<"); Log.write(name); + } + + /** + * Open an XML comment + */ + public static void openComment() { + Log.write(""); + } + + /** + * Add a comment, bracketing it with open- and close-comment tags. + * + * @param comment The comment. + */ + public static void comment(String comment) { + openComment(); + Log.write(comment); + closeComment(); + Log.writeln(); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,59 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.plan.Plan; +import org.mmtk.plan.CollectorContext; +import org.mmtk.plan.MutatorContext; +import org.mmtk.plan.PlanConstraints; + +import org.mmtk.utility.Log; + +import org.vmmagic.pragma.*; + +/** + * Stub to give access to plan local, constraint and global instances + */ + at Uninterruptible public abstract class ActivePlan { + + /** @return The active Plan instance. */ + public abstract Plan global(); + + /** @return The active PlanConstraints instance. */ + public abstract PlanConstraints constraints(); + + /** @return The active CollectorContext instance. */ + public abstract CollectorContext collector(); + + /** @return The active MutatorContext instance. */ + public abstract MutatorContext mutator(); + + /** @return The log for the active thread */ + public abstract Log log(); + + /** @return The maximum number of collector threads that may participate in parallel GC. */ + public abstract int collectorCount(); + + /** Reset the mutator iterator */ + public abstract void resetMutatorIterator(); + + /** + * Return the next MutatorContext in a + * synchronized iteration of all mutators. + * + * @return The next MutatorContext in a + * synchronized iteration of all mutators, or + * null when all mutators have been done. + */ + public abstract MutatorContext getNextMutator(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,77 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; + + at Uninterruptible public abstract class Assert { + /** + * Logs a message and traceback, then exits. + * + * @param message the string to log + */ + public abstract void fail(String message); + + /** + * Checks that the given condition is true. If it is not, this + * method does a traceback and exits. All calls to this method + * must be guarded by VM.VERIFY_ASSERTIONS. + * + * @param cond the condition to be checked + */ + public abstract void _assert(boolean cond); + + /** + * Checks that the given condition is true. If it is not, this + * method prints a message, does a traceback and exits. All calls + * to this method must be guarded by VM.VERIFY_ASSERTIONS. + * + * @param cond the condition to be checked + * @param message the message to print + */ + public abstract void _assert(boolean cond, String message); + + /** + * Print a stack trace + */ + public abstract void dumpStack(); + + /** + * Checks if the virtual machine is running. This value changes, so + * the call-through to the VM must be a method. In Jikes RVM, just + * returns VM.runningVM. + * + * @return true if the virtual machine is running + */ + public abstract boolean runningVM(); + + /* + * NOTE: The following methods must be implemented by subclasses of this + * class, but are internal to the VM<->MM interface glue, so are never + * called by MMTk users. + */ + /** @return true if assertions should be verified */ + protected abstract boolean getVerifyAssertionsConstant(); + + /* + * NOTE: This method should not be called by anything other than the + * reflective mechanisms in org.mmtk.vm.VM, and is not implemented by + * subclasses. + * + * This hack exists only to allow us to declare getVerifyAssertions() as + * a protected method. + */ + static boolean verifyAssertionsTrapdoor(Assert a) { + return a.getVerifyAssertionsConstant(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,149 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.*; + + at Uninterruptible +public abstract class Barriers { + /** + * Sets an element of an object array without invoking any write + * barrier. This method is called by the Map class to ensure + * potentially-allocation-triggering write barriers do not occur in + * allocation slow path code. + * + * @param dst the destination array + * @param index the index of the element to set + * @param value the new value for the element + */ + public abstract void setArrayNoBarrier(Object [] dst, int index, Object value); + + /** + * Perform the actual write of the write barrier. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param target The value that the slot will be updated to + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + */ + public abstract void performWriteInBarrier(ObjectReference ref, Address slot, + ObjectReference target, Word metaDataA, + Word metaDataB, int mode); + + /** + * Perform the actual write of the write barrier, writing the value as a raw Word. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param rawTarget The value that the slot will be updated to + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + */ + public abstract void performRawWriteInBarrier(ObjectReference ref, Address slot, + Word rawTarget, Word metaDataA, + Word metaDataB, int mode); + + /** + * Perform the actual read of the read barrier. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + * @return the read value + */ + public abstract ObjectReference performReadInBarrier(ObjectReference ref, Address slot, + Word metaDataA, Word metaDataB, int mode); + + /** + * Perform the actual read of the read barrier, returning the value as a raw Word. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + * @return the read value + */ + public abstract Word performRawReadInBarrier(ObjectReference ref, Address slot, + Word metaDataA, Word metaDataB, int mode); + + /** + * Atomically write a reference field of an object or array and return + * the old value of the reference field. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param target The value that the slot will be updated to + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + * @return The value that was replaced by the write. + */ + public abstract ObjectReference performWriteInBarrierAtomic(ObjectReference ref, Address slot, + ObjectReference target, Word metaDataA, + Word metaDataB, int mode); + + /** + * Atomically write a reference field of an object or array and return + * the old value of the reference field. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param rawTarget The raw value that the slot will be updated to + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + * @return The raw value that was replaced by the write. + */ + public abstract Word performRawWriteInBarrierAtomic(ObjectReference ref, Address slot, + Word rawTarget, Word metaDataA, + Word metaDataB, int mode); + + /** + * Attempt an atomic compare and exchange in a write barrier sequence. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param old The old reference to be swapped out + * @param target The value that the slot will be updated to + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + * @return True if the compare and swap was successful + */ + public abstract boolean tryCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot, + ObjectReference old, ObjectReference target, + Word metaDataA, Word metaDataB, int mode); + + /** + * Attempt an atomic compare and exchange in a write barrier sequence. + * + * @param ref The object that has the reference field + * @param slot The slot that holds the reference + * @param rawOld The old reference to be swapped out + * @param rawTarget The value that the slot will be updated to + * @param metaDataA VM specific meta data + * @param metaDataB VM specific meta data + * @param mode The context in which the write is occuring + * @return True if the compare and swap was successful + */ + public abstract boolean tryRawCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot, + Word rawOld, Word rawTarget, + Word metaDataA, Word metaDataB, int mode); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,69 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +/** + * Build-time configuration constants for MMTk. + */ +public abstract class BuildTimeConfig { + + /** + * @return The name of the current MMTk plan + */ + public abstract String getPlanName(); + + /** + * Return a property of type String + * @param name The name of the property + * @return The value of the property + */ + public abstract String getStringProperty(String name); + + /** + * Return a property of type String, with default. + * @param name The name of the property + * @param dflt Default value + * @return The value of the property + */ + public abstract String getStringProperty(String name, String dflt); + + /** + * Return a property of type int + * @param name The name of the property + * @return The value of the property + */ + public abstract int getIntProperty(String name); + + /** + * Return a property of type String, with default. + * @param name The name of the property + * @param dflt Default value + * @return The value of the property + */ + public abstract int getIntProperty(String name, int dflt); + + /** + * Return a property of type boolean + * @param name The name of the property + * @return The value of the property + */ + public abstract boolean getBooleanProperty(String name); + + /** + * Return a property of type boolean, with default. + * @param name The name of the property + * @param dflt Default value + * @return The value of the property + */ + public abstract boolean getBooleanProperty(String name, boolean dflt); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,160 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.plan.CollectorContext; +import org.mmtk.plan.MutatorContext; + +import org.vmmagic.pragma.*; + + at Uninterruptible public abstract class Collection { + + /**************************************************************************** + * + * Class variables + */ + + /** + * An unknown GC trigger reason. Signals a logic bug. + */ + public static final int UNKNOWN_GC_TRIGGER = 0; + + /** + * Concurrent collection phase trigger. + */ + public static final int INTERNAL_PHASE_GC_TRIGGER = 1; + + /** + * Externally triggered garbage collection (eg call to System.gc()) + */ + public static final int EXTERNAL_GC_TRIGGER = 2; + + /** + * Resource triggered garbage collection. For example, an + * allocation request would take the number of pages in use beyond + * the number available. + */ + public static final int RESOURCE_GC_TRIGGER = 3; + + /** + * Internally triggered garbage collection. For example, the memory + * manager attempting another collection after the first failed to + * free space. + */ + public static final int INTERNAL_GC_TRIGGER = 4; + + /** + * The number of garbage collection trigger reasons. + */ + public static final int TRIGGER_REASONS = 5; + + /** Short descriptions of the garbage collection trigger reasons. */ + protected static final String[] triggerReasons = { + "unknown", + "concurrent phase", + "external request", + "resource exhaustion", + "internal request" + }; + + /** + * Triggers a collection. + * + * @param why the reason why a collection was triggered. 0 to + * TRIGGER_REASONS - 1. + */ + @Unpreemptible + public abstract void triggerCollection(int why); + + /** + * Joins an already requested collection. + */ + @Unpreemptible + public abstract void joinCollection(); + + /** + * Trigger an asynchronous collection, checking for memory + * exhaustion first. + * + * @param why the reason why a collection was triggered. 0 to + * TRIGGER_REASONS - 1. + */ + public abstract void triggerAsyncCollection(int why); + + /** + * The maximum number collection attempts across threads. + */ + public abstract int maximumCollectionAttempt(); + + /** + * Report that the allocation has succeeded. + */ + public abstract void reportAllocationSuccess(); + + /** + * Report that a physical allocation has failed. + */ + public abstract void reportPhysicalAllocationFailed(); + + /** + * Does the VM consider this an emergency alloction, where the normal + * heap size rules can be ignored. + */ + public abstract boolean isEmergencyAllocation(); + + /** + * Determine whether a collection cycle has fully completed (this is + * used to ensure a GC is not in the process of completing, to + * avoid, for example, an async GC being triggered on the switch + * from GC to mutator thread before all GC threads have switched. + * + * @return True if GC is not in progress. + */ + public abstract boolean noThreadsInGC(); + + /** + * Prepare a mutator for collection. + * + * @param m the mutator to prepare + */ + public abstract void prepareMutator(MutatorContext m); + + /** + * Prepare a collector for a collection. + * + * @param c the collector to prepare + */ + public abstract void prepareCollector(CollectorContext c); + + /** + * Rendezvous with all other processors, returning the rank + * (that is, the order this processor arrived at the barrier). + */ + public abstract int rendezvous(int where); + + /** @return The number of active collector threads */ + public abstract int activeGCThreads(); + + /** + * @return The ordinal ID of the running collector thread w.r.t. + * the set of active collector threads (zero based) + */ + public abstract int activeGCThreadOrdinal(); + + /** + * Request each mutator flush remembered sets. This method + * will trigger the flush and then yield until all processors have + * flushed. + */ + public abstract void requestMutatorFlush(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,43 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.utility.Log; +import org.mmtk.utility.statistics.Xml; + +public class Config { + /* The name of the active plan */ + private final String ACTIVE_PLAN; + + /** Mark bit in the header or on the side ? */ + public final boolean HEADER_MARK_BITS; + + Config(BuildTimeConfig config) { + ACTIVE_PLAN = config.getPlanName(); + HEADER_MARK_BITS = config.getBooleanProperty("mmtk.headerMarkBit",true); + } + + public void printConfig() { + Log.writeln("================ MMTk Configuration ================"); + Log.write("plan = "); Log.writeln(ACTIVE_PLAN); + Log.write("HEADER_MARK_BITS = "); Log.writeln(HEADER_MARK_BITS); + Log.writeln("===================================================="); + } + + public void printConfigXml() { + Log.writeln(""); + Xml.configItem("plan",ACTIVE_PLAN); + Xml.configItem("header-mark-bit",HEADER_MARK_BITS); + Log.writeln(""); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,89 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.ObjectReference; + +/** + * + */ + at Uninterruptible +public abstract class Debug { + /** + * Global switch for debugging - if false the other methods of this + * class are never called. + * @return Whether debugging is enabled + */ + public abstract boolean isEnabled(); + + /** + * A modbuf (object remembering barrier) entry has been + * traced during collection. + * @param object + */ + public void modbufEntry(ObjectReference object) { } + + /** + * A remset (slot remembering barrier) entry has been + * traced during collection. + * @param slot + */ + public void remsetEntry(Address slot) { } + + /** + * An array remset entry has been traced during collection. Implicitly + * the slots from start (inclusive) through to guard (non-inclusive) + * are traced as remset entries + * @param start + * @param guard + */ + public void arrayRemsetEntry(Address start, Address guard) { } + + /** + * A global GC collection phase + * @param phaseId The phase ID + * @param before true at the start of the phase, false at the end + */ + public void globalPhase(short phaseId, boolean before) { } + + /** + * A per-collector GC collection phase + * @param phaseId The phase ID + * @param ordinal The collector ID (within this collection) + * @param before true at the start of the phase, false at the end + */ + public void collectorPhase(short phaseId, int ordinal, boolean before) { } + + /** + * A per-mutator GC collection phase + * @param phaseId The phase ID + * @param ordinal The mutator ID + * @param before true at the start of the phase, false at the end + */ + public void mutatorPhase(short phaseId, int ordinal, boolean before) { } + + /* + * NOTE: These methods should not be called by anything other than the + * reflective mechanisms in org.mmtk.vm.VM, and are not implemented by + * subclasses. + * + * This hack exists only to allow us to declare the respective + * methods as protected. + */ + static final boolean isEnabledTrapdoor(Debug d) { + return d.isEnabled(); + } + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,347 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmutil.options.OptionSet; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.vm.gcspy.ByteStream; +import org.mmtk.vm.gcspy.IntStream; +import org.mmtk.vm.gcspy.ServerInterpreter; +import org.mmtk.vm.gcspy.ServerSpace; +import org.mmtk.vm.gcspy.ShortStream; +import org.mmtk.vm.gcspy.Util; + +/** + * This class defines factory methods for VM-specific types which must + * be instantiated within MMTk. Since the concrete type is defined at + * build time, we leave it to a concrete vm-specific instance of this class + * to perform the object instantiation. + */ +public abstract class Factory { + + /** + * Create or retrieve the OptionSet used for MMTk options. + * + * @return A concrete VM-specific OptionSet instance + */ + public abstract OptionSet getOptionSet(); + + /** + * Create a new ActivePlan instance using the appropriate VM-specific + * concrete ActivePlan sub-class. + * + * @see ActivePlan + * @return A concrete VM-specific ActivePlan instance. + */ + public abstract ActivePlan newActivePlan(); + + /** + * Create a new Assert instance using the appropriate VM-specific + * concrete Assert sub-class. + * + * @see Assert + * @return A concrete VM-specific Assert instance. + */ + public abstract Assert newAssert(); + + /** + * Create a new Barriers instance using the appropriate VM-specific + * concrete Barriers sub-class. + * + * @see Barriers + * @return A concrete VM-specific Barriers instance. + */ + public abstract Barriers newBarriers(); + + /** + * Create a new Collection instance using the appropriate VM-specific + * concrete Collection sub-class. + * + * @see Collection + * @return A concrete VM-specific Collection instance. + */ + public abstract Collection newCollection(); + + /** + * Create a new Config instance using the appropriate VM-specific + * concrete Config sub-class. + * + * @see Collection + * @return A concrete VM-specific Collection instance. + */ + public abstract BuildTimeConfig newBuildTimeConfig(); + + /** + * Create a new Lock instance using the appropriate VM-specific + * concrete Lock sub-class. + * + * @see Lock + * @param name The string to be associated with this lock instance + * @return A concrete VM-specific Lock instance. + */ + public abstract Lock newLock(String name); + + /** + * Create a new Memory instance using the appropriate VM-specific + * concrete Memory sub-class. + * + * @see Memory + * @return A concrete VM-specific Memory instance. + */ + public abstract Memory newMemory(); + + /** + * Create a new ObjectModel instance using the appropriate VM-specific + * concrete ObjectModel sub-class. + * + * @see ObjectModel + * @return A concrete VM-specific ObjectModel instance. + */ + public abstract ObjectModel newObjectModel(); + + /** + * Create a new ReferenceProcessor instance using the appropriate VM-specific + * concrete ReferenceProcessor sub-class. + * + * @see ReferenceProcessor + * @return A concrete VM-specific ReferenceProcessor instance. + */ + public abstract ReferenceProcessor newReferenceProcessor(ReferenceProcessor.Semantics semantics); + + + /** + * Create a new FinalizbleProcessor instance using the appropriate VM-specific + * concrete FinalizableProcessor sub-class. + * + * @see FinalizableProcessor + * @return A concrete VM-specific FinalizableProcessor instance. + */ + public abstract FinalizableProcessor newFinalizableProcessor(); + + /** + * Create a new Scanning instance using the appropriate VM-specific + * concrete Scanning sub-class. + * + * @see Scanning + * @return A concrete VM-specific Scanning instance. + */ + public abstract Scanning newScanning(); + + /** + * Create a new Statistics instance using the appropriate VM-specific + * concrete Statistics sub-class. + * + * @see Statistics + * @return A concrete VM-specific Statistics instance. + */ + public abstract Statistics newStatistics(); + + /** + * Create a new Strings instance using the appropriate VM-specific + * concrete Strings sub-class. + * + * @see Strings + * @return A concrete VM-specific Strings instance. + */ + public abstract Strings newStrings(); + + /** + * Create a new SynchronizedCounter instance using the appropriate + * VM-specific concrete SynchronizedCounter sub-class. + * + * @see SynchronizedCounter + * + * @return A concrete VM-specific SynchronizedCounter instance. + */ + public abstract SynchronizedCounter newSynchronizedCounter(); + + /** + * Create a new TraceInterface instance using the appropriate VM-specific + * concrete TraceInterface sub-class. + * + * @see TraceInterface + * @return A concrete VM-specific TraceInterface instance. + */ + public abstract TraceInterface newTraceInterface(); + + /** + * Create a new MMTk_Events instance using the appropriate VM-specific + * concrete MMTk_Events sub-class. + */ + public abstract MMTk_Events newEvents(); + + /** + * Create a new debug object + */ + public abstract Debug newDebug(); + + /********************************************************************** + * GCspy methods + */ + + /** + * Create a new Util instance using the appropriate VM-specific + * concrete Util sub-class. + * + * @see Util + * @return A concrete VM-specific Util instance. + */ + public abstract Util newGCspyUtil(); + + /** + * Create a new ServerInterpreter instance using the appropriate VM-specific + * concrete ServerInterpreter sub-class. + * + * @see ServerInterpreter + * @return A concrete VM-specific ServerInterpreter instance. + */ + public abstract ServerInterpreter newGCspyServerInterpreter(); + + /** + * Create a new ServerSpace instance using the appropriate VM-specific + * concrete ServerSpace sub-class. + * + * @param serverInterpreter The server that owns this space + * @param serverName The server's name + * @param driverName The space driver's name + * @param title Title for the space + * @param blockInfo A label for each block + * @param tileNum Max number of tiles in this space + * @param unused A label for unused blocks + * @param mainSpace Whether this space is the main space + * + * @see ServerSpace + * @return A concrete VM-specific ServerSpace instance. + */ + public abstract ServerSpace newGCspyServerSpace( + ServerInterpreter serverInterpreter, + String serverName, + String driverName, + String title, + String blockInfo, + int tileNum, + String unused, + boolean mainSpace); + + /** + * Create a new IntStream instance using the appropriate + * VM-specific concrete IntStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see IntStream + * + * @return A concrete VM-specific IntStream instance. + */ + public abstract IntStream newGCspyIntStream( + AbstractDriver driver, + String name, + int minValue, + int maxValue, + int zeroValue, + int defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary); + + /** + * Create a new ByteStream instance using the appropriate + * VM-specific concrete ByteStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see IntStream + * + * @return A concrete VM-specific ByteStream instance. + */ + public abstract ByteStream newGCspyByteStream( + AbstractDriver driver, + String name, + byte minValue, + byte maxValue, + byte zeroValue, + byte defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary); + + /** + * Create a new ShortStream instance using the appropriate + * VM-specific concrete ShortStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see IntStream + * + * @return A concrete VM-specific ShortStream instance. + */ + public abstract ShortStream newGCspyShortStream( + AbstractDriver driver, + String name, + short minValue, + short maxValue, + short zeroValue, + short defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,42 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.plan.TraceLocal; +import org.vmmagic.pragma.Uninterruptible; + +/** + * This class manages finalizable objects. + */ + at Uninterruptible +public abstract class FinalizableProcessor { + + /** + * Clear the contents of the table. This is called when finalization is + * disabled to make it easier for VMs to change this setting at runtime. + */ + public abstract void clear(); + + /** + * Scan through the list of references. + * + * @param trace the thread local trace element. + * @param nursery true if it is safe to only scan new references. + */ + public abstract void scan(TraceLocal trace, boolean nursery); + + /** + * Iterate over and forward entries in the table. + */ + public abstract void forward(TraceLocal trace, boolean nursery); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,47 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; + +/** + * Simple, fair locks with deadlock detection. + */ + at Uninterruptible public abstract class Lock { + + /** + * Set the name of this lock instance + * + * @param str The name of the lock (for error output). + */ + public abstract void setName(String str); + + + /** + * Try to acquire a lock and spin-wait until acquired. + */ + public abstract void acquire(); + + /** + * Perform sanity checks on the lock. For debugging. + * + * @param w Identifies the code location in the debugging output. + */ + public abstract void check(int w); + + /** + * Release the lock by incrementing serving counter. + */ + public abstract void release(); + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ + +package org.mmtk.vm; + +import org.mmtk.policy.Space; +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Extent; + +/** + * Event generation interface for MMTk. + */ + at Uninterruptible +public abstract class MMTk_Events { + public abstract void tracePageAcquired(Space space, Address startAddress, int numPages); + + public abstract void tracePageReleased(Space space, Address startAddress, int numPages); + + public abstract void heapSizeChanged(Extent heapSize); + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,211 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.policy.ImmortalSpace; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + + at Uninterruptible public abstract class Memory { + + /** + * Allows for the VM to reserve space between HEAP_START() + * and AVAILABLE_START() for its own purposes. MMTk should + * expect to encounter objects in this range, but may not + * allocate in this range. + * + * MMTk expects the virtual address space between AVAILABLE_START() + * and AVAILABLE_END() to be contiguous and unmapped. + * Allows for the VM to reserve space between HEAP_END() + * and AVAILABLE_END() for its own purposes. MMTk should + * expect to encounter objects in this range, but may not + * allocate in this range. + * + * MMTk expects the virtual address space between AVAILABLE_START() + * and AVAILABLE_END() to be contiguous and unmapped. + * + * @return The high bound of the memory that MMTk can allocate. + */ + + /** + * Return the space associated with/reserved for the VM. In the + * case of Jikes RVM this is the boot image space.

    + * + * @return The space managed by the virtual machine. + */ + @Interruptible + public abstract ImmortalSpace getVMSpace(); + + /** Global preparation for a collection. */ + public abstract void globalPrepareVMSpace(); + + /** Per-collector preparation for a collection. */ + public abstract void collectorPrepareVMSpace(); + + /** Per-collector post-collection work. */ + public abstract void collectorReleaseVMSpace(); + + /** Global post-collection work. */ + public abstract void globalReleaseVMSpace(); + + /** + * Sets the range of addresses associated with a heap. + * + * @param id the heap identifier + * @param start the address of the start of the heap + * @param end the address of the end of the heap + */ + public abstract void setHeapRange(int id, Address start, Address end); + + /** + * Demand zero mmaps an area of virtual memory. + * + * @param start the address of the start of the area to be mapped + * @param size the size, in bytes, of the area to be mapped + * @return 0 if successful, otherwise the system errno + */ + public abstract int dzmmap(Address start, int size); + + /** + * Protects access to an area of virtual memory. + * + * @param start the address of the start of the area to be mapped + * @param size the size, in bytes, of the area to be mapped + * @return true if successful, otherwise + * false + */ + public abstract boolean mprotect(Address start, int size); + + /** + * Allows access to an area of virtual memory. + * + * @param start the address of the start of the area to be mapped + * @param size the size, in bytes, of the area to be mapped + * @return true if successful, otherwise + * false + */ + public abstract boolean munprotect(Address start, int size); + + /** + * Zero a region of memory. + * @param start Start of address range (inclusive) + * @param len Length in bytes of range to zero + * Returned: nothing + */ + public abstract void zero(Address start, Extent len); + + /** + * Zero a range of pages of memory. + * @param start Start of address range (must be a page address) + * @param len Length in bytes of range (must be multiple of page size) + */ + public abstract void zeroPages(Address start, int len); + + /** + * Logs the contents of an address and the surrounding memory to the + * error output. + * + * @param start the address of the memory to be dumped + * @param beforeBytes the number of bytes before the address to be + * included + * @param afterBytes the number of bytes after the address to be + * included + */ + public abstract void dumpMemory(Address start, int beforeBytes, + int afterBytes); + + /** + * Wait for preceeding cache flush/invalidate instructions to complete + * on all processors. Ensures that all memory writes before this + * point are visible to all processors. + */ + @Inline + public abstract void sync(); + + /** + * Wait for all preceeding instructions to complete and discard any + * prefetched instructions on this processor. Also prevents the + * compiler from performing code motion across this point. + */ + @Inline + public abstract void isync(); + + /* + * NOTE: The following methods must be implemented by subclasses of this + * class, but are internal to the VM<->MM interface glue, so are never + * called by MMTk users. + */ + /** @return The lowest address in the virtual address space known to MMTk */ + protected abstract Address getHeapStartConstant(); + /** @return The highest address in the virtual address space known to MMTk */ + protected abstract Address getHeapEndConstant(); + /** @return The lowest address in the contiguous address space available to MMTk */ + protected abstract Address getAvailableStartConstant(); + /** @return The highest address in the contiguous address space available to MMTk */ + protected abstract Address getAvailableEndConstant(); + /** @return The log base two of the size of an address */ + protected abstract byte getLogBytesInAddressConstant(); + /** @return The log base two of the size of a word */ + protected abstract byte getLogBytesInWordConstant(); + /** @return The log base two of the size of an OS page */ + protected abstract byte getLogBytesInPageConstant(); + /** @return The log base two of the minimum allocation alignment */ + protected abstract byte getLogMinAlignmentConstant(); + /** @return The log base two of (MAX_ALIGNMENT/MIN_ALIGNMENT) */ + protected abstract byte getMaxAlignmentShiftConstant(); + /** @return The maximum number of bytes of padding to prepend to an object */ + protected abstract int getMaxBytesPaddingConstant(); + /** @return The value to store in alignment holes */ + protected abstract int getAlignmentValueConstant(); + + /* + * NOTE: These methods should not be called by anything other than the + * reflective mechanisms in org.mmtk.vm.VM, and are not implemented by + * subclasses. This hack exists only to allow us to declare the respective + * methods as protected. + */ + static Address heapStartTrapdoor(Memory m) { + return m.getHeapStartConstant(); + } + static Address heapEndTrapdoor(Memory m) { + return m.getHeapEndConstant(); + } + static Address availableStartTrapdoor(Memory m) { + return m.getAvailableStartConstant(); + } + static Address availableEndTrapdoor(Memory m) { + return m.getAvailableEndConstant(); + } + static byte logBytesInAddressTrapdoor(Memory m) { + return m.getLogBytesInAddressConstant(); + } + static byte logBytesInWordTrapdoor(Memory m) { + return m.getLogBytesInWordConstant(); + } + static byte logBytesInPageTrapdoor(Memory m) { + return m.getLogBytesInPageConstant(); + } + static byte logMinAlignmentTrapdoor(Memory m) { + return m.getLogMinAlignmentConstant(); + } + static byte maxAlignmentShiftTrapdoor(Memory m) { + return m.getMaxAlignmentShiftConstant(); + } + static int maxBytesPaddingTrapdoor(Memory m) { + return m.getMaxBytesPaddingConstant(); + } + static int alignmentValueTrapdoor(Memory m) { + return m.getAlignmentValueConstant(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,256 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.*; + + at Uninterruptible public abstract class ObjectModel { + /** + * Copy an object using a plan's allocCopy to get space and install + * the forwarding pointer. On entry, from must have + * been reserved for copying by the caller. This method calls the + * plan's getStatusForCopy() method to establish a new + * status word for the copied object and postCopy() to + * allow the plan to perform any post copy actions. + * + * @param from the address of the object to be copied + * @param allocator The allocator to use. + * @return the address of the new object + */ + public abstract ObjectReference copy(ObjectReference from, int allocator); + + /** + * Copy an object to be pointer to by the to address. This is required + * for delayed-copy collectors such as compacting collectors. During the + * collection, MMTk reserves a region in the heap for an object as per + * requirements found from ObjectModel and then asks ObjectModel to + * determine what the object's reference will be post-copy. + * + * @param from the address of the object to be copied + * @param to The target location. + * @param region The start of the region that was reserved for this object + * @return Address The address past the end of the copied object + */ + public abstract Address copyTo(ObjectReference from, ObjectReference to, Address region); + + /** + * Return the reference that an object will be refered to after it is copied + * to the specified region. Used in delayed-copy collectors such as compacting + * collectors. + * + * @param from The object to be copied. + * @param to The region to be copied to. + * @return The resulting reference. + */ + public abstract ObjectReference getReferenceWhenCopiedTo(ObjectReference from, Address to); + + + /** + * Return the size required to copy an object + * + * @param object The object whose size is to be queried + * @return The size required to copy obj + */ + public abstract int getSizeWhenCopied(ObjectReference object); + + /** + * Return the alignment requirement for a copy of this object + * + * @param object The object whose size is to be queried + * @return The alignment required for a copy of obj + */ + public abstract int getAlignWhenCopied(ObjectReference object); + + /** + * Return the alignment offset requirements for a copy of this object + * + * @param object The object whose size is to be queried + * @return The alignment offset required for a copy of obj + */ + public abstract int getAlignOffsetWhenCopied(ObjectReference object); + + + /** + * Return the size used by an object + * + * @param object The object whose size is to be queried + * @return The size of obj + */ + public abstract int getCurrentSize(ObjectReference object); + + /** + * Return the next object in the heap under contiguous allocation + */ + public abstract ObjectReference getNextObject(ObjectReference object); + + /** + * Return an object reference from knowledge of the low order word + */ + public abstract ObjectReference getObjectFromStartAddress(Address start); + /** + * Gets a pointer to the address just past the end of the object. + * + * @param object The objecty. + */ + public abstract Address getObjectEndAddress(ObjectReference object); + + + /** + * Get the type descriptor for an object. + * + * @param ref address of the object + * @return byte array with the type descriptor + */ + public abstract byte[] getTypeDescriptor(ObjectReference ref); + + /** + * Is the passed object an array? + * + * @param object address of the object + */ + public abstract boolean isArray(ObjectReference object); + + /** + * Is the passed object a primitive array? + * + * @param object address of the object + */ + public abstract boolean isPrimitiveArray(ObjectReference object); + + /** + * Get the length of an array object. + * + * @param object address of the object + * @return The array length, in elements + */ + public abstract int getArrayLength(ObjectReference object); + + /** + * Attempts to set the bits available for memory manager use in an + * object. The attempt will only be successful if the current value + * of the bits matches oldVal. The comparison with the + * current value and setting are atomic with respect to other + * allocators. + * + * @param object the address of the object + * @param oldVal the required current value of the bits + * @param newVal the desired new value of the bits + * @return true if the bits were set, + * false otherwise + */ + public abstract boolean attemptAvailableBits(ObjectReference object, + Word oldVal, Word newVal); + + /** + * Gets the value of bits available for memory manager use in an + * object, in preparation for setting those bits. + * + * @param object the address of the object + * @return the value of the bits + */ + public abstract Word prepareAvailableBits(ObjectReference object); + + /** + * Sets the byte available for memory manager use in an object. + * + * @param object the address of the object + * @param val the new value of the byte + */ + public abstract void writeAvailableByte(ObjectReference object, byte val); + /** + * Read the byte available for memory manager use in an object. + * + * @param object the address of the object + * @return the value of the byte + */ + public abstract byte readAvailableByte(ObjectReference object); + + /** + * Sets the bits available for memory manager use in an object. + * + * @param object the address of the object + * @param val the new value of the bits + */ + public abstract void writeAvailableBitsWord(ObjectReference object, Word val); + /** + * Read the bits available for memory manager use in an object. + * + * @param object the address of the object + * @return the value of the bits + */ + public abstract Word readAvailableBitsWord(ObjectReference object); + + /** + * Gets the offset of the memory management header from the object + * reference address. XXX The object model / memory manager + * interface should be improved so that the memory manager does not + * need to know this. + * + * @return the offset, relative the object reference address + */ + public abstract Offset GC_HEADER_OFFSET(); + + /** + * Returns the lowest address of the storage associated with an object. + * + * @param object the reference address of the object + * @return the lowest address of the object + */ + public abstract Address objectStartRef(ObjectReference object); + + /** + * Returns an address guaranteed to be inside the storage assocatied + * with and object. + * + * @param object the reference address of the object + * @return an address inside the object + */ + public abstract Address refToAddress(ObjectReference object); + + /** + * Checks if a reference of the given type in another object is + * inherently acyclic. The type is given as a TIB. + * + * @return true if a reference of the type is + * inherently acyclic + */ + public abstract boolean isAcyclic(ObjectReference typeRef); + + /** + * Dump debugging information for an object. + * + * @param object The object whose information is to be dumped + */ + public abstract void dumpObject(ObjectReference object); + + /* + * NOTE: The following methods must be implemented by subclasses of this + * class, but are internal to the VM<->MM interface glue, so are never + * called by MMTk users. + */ + /** @return The offset from array reference to element zero */ + protected abstract Offset getArrayBaseOffset(); + + /* + * NOTE: These methods should not be called by anything other than the + * reflective mechanisms in org.mmtk.vm.VM, and are not implemented by + * subclasses. + * + * This hack exists only to allow us to declare the respective + * methods as protected. + */ + static Offset arrayBaseOffsetTrapdoor(ObjectModel o) { + return o.getArrayBaseOffset(); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,50 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.plan.TraceLocal; +import org.vmmagic.pragma.Uninterruptible; + +/** + * This class manages SoftReferences, WeakReferences, and + * PhantomReferences. + */ + at Uninterruptible +public abstract class ReferenceProcessor { + + public enum Semantics { SOFT, WEAK, PHANTOM } + + /** + * Clear the contents of the table. This is called when reference types are + * disabled to make it easier for VMs to change this setting at runtime. + */ + public abstract void clear(); + + /** + * Scan through the list of references. + * + * @param trace the thread local trace element. + * @param nursery true if it is safe to only scan new references. + */ + public abstract void scan(TraceLocal trace, boolean nursery); + + /** + * Iterate over all references and forward. + */ + public abstract void forward(TraceLocal trace, boolean nursery); + + /** + * @return the number of references objects on the queue + */ + public abstract int countWaitingReferences(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,137 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.plan.TraceLocal; +import org.mmtk.plan.TransitiveClosure; +import org.mmtk.utility.Constants; + +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.*; + + at Uninterruptible public abstract class Scanning implements Constants { + /** + * Delegated scanning of a object, processing each pointer field + * encountered. + * + * @param object The object to be scanned. + */ + public abstract void scanObject(TransitiveClosure trace, ObjectReference object); + + /** + * Invoke a specialized scan method. Note that these methods must have been allocated + * explicitly through Plan and PlanConstraints. + * + * @param id The specialized method id + * @param trace The trace the method has been specialized for + * @param object The object to be scanned + */ + public abstract void specializedScanObject(int id, TransitiveClosure trace, ObjectReference object); + + /** + * Delegated precopying of a object's children, processing each pointer field + * encountered. + * + * @param trace The trace object to use for precopying. + * @param object The object to be scanned. + */ + public abstract void precopyChildren(TraceLocal trace, ObjectReference object); + + /** + * Prepares for using the computeAllRoots method. The + * thread counter allows multiple GC threads to co-operatively + * iterate through the thread data structure (if load balancing + * parallel GC threads were not important, the thread counter could + * simply be replaced by a for loop). + */ + public abstract void resetThreadCounter(); + + /** + * Pre-copy all potentially movable instances used in the course of + * GC. This includes the thread objects representing the GC threads + * themselves. It is crucial that these instances are forwarded + * prior to the GC proper. Since these instances are + * not enqueued for scanning, it is important that when roots + * are computed the same instances are explicitly scanned and + * included in the set of roots. The existence of this method + * allows the actions of calculating roots and forwarding GC + * instances to be decoupled. + */ + public abstract void preCopyGCInstances(TraceLocal trace); + + /** + * Computes static roots. This method establishes all such roots for + * collection and places them in the root locations queue. This method + * should not have side effects (such as copying or forwarding of + * objects). There are a number of important preconditions: + * + *

      + *
    • All objects used in the course of GC (such as the GC thread + * objects) need to be "pre-copied" prior to calling this method. + *
    • The threadCounter must be reset so that load + * balancing parallel GC can share the work of scanning threads. + *
    + * + * @param trace The trace to use for computing roots. + */ + public abstract void computeStaticRoots(TraceLocal trace); + + /** + * Computes global roots. This method establishes all such roots for + * collection and places them in the root locations queue. This method + * should not have side effects (such as copying or forwarding of + * objects). There are a number of important preconditions: + * + *
      + *
    • All objects used in the course of GC (such as the GC thread + * objects) need to be "pre-copied" prior to calling this method. + *
    • The threadCounter must be reset so that load + * balancing parallel GC can share the work of scanning threads. + *
    + * + * @param trace The trace to use for computing roots. + */ + public abstract void computeGlobalRoots(TraceLocal trace); + + /** + * Computes roots pointed to by threads, their associated registers + * and stacks. This method places these roots in the root values, + * root locations and interior root locations queues. This method + * should not have side effects (such as copying or forwarding of + * objects). There are a number of important preconditions: + * + *
      + *
    • All objects used in the course of GC (such as the GC thread + * objects) need to be "pre-copied" prior to calling this method. + *
    • The threadCounter must be reset so that load + * balancing parallel GC can share the work of scanning threads. + *
    + * + * @param trace The trace to use for computing roots. + */ + public abstract void computeThreadRoots(TraceLocal trace); + + /** + * Compute all roots out of the VM's boot image (if any). This method is a no-op + * in the case where the VM does not maintain an MMTk-visible Java space. However, + * when the VM does maintain a space (such as a boot image) which is visible to MMTk, + * that space could either be scanned by MMTk as part of its transitive closure over + * the whole heap, or as a (considerable) performance optimization, MMTk could avoid + * scanning the space if it is aware of all pointers out of that space. This method + * is used to establish the root set out of the scannable space in the case where + * such a space exists. + * + * @param trace The trace object to use to report root locations. + */ + public abstract void computeBootImageRoots(TraceLocal trace); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,79 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; + + + at Uninterruptible public abstract class Statistics { + /** + * Returns the number of collections that have occurred. + * + * @return The number of collections that have occurred. + */ + public abstract int getCollectionCount(); + + /** + * Read cycle counter + */ + public abstract long nanoTime(); + + /** + * Convert nanoseconds to milliseconds + */ + public abstract double nanosToMillis(long c); + + /** + * Convert nanoseconds to seconds + */ + public abstract double nanosToSecs(long c); + + /** + * Convert milliseconds to nanoseconds + */ + public abstract long millisToNanos(double t); + + /** + * Convert seconds to nanoseconds + */ + public abstract long secsToNanos(double t); + + /** + * Read the cycle counter + */ + public abstract long cycles(); + + /** + * Initialize performance counters + * + * @param metric An integer identifying the metric being read + */ + public abstract void perfCtrInit(int metric); + + /** + * Read the current cycle count from the perfctr libraries + * + * @return the current cycle count from the perfctr libraries + */ + public abstract long perfCtrReadCycles(); + + /** + * Read the current event count for the metric being measured by the + * perfctr libraries + * + * @return the current event count for the metric being measured by the + * perfctr libraries + */ + public abstract long perfCtrReadMetric(); + +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,51 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; + + + at Uninterruptible public abstract class Strings { + /** + * Log a message. + * + * @param c character array with message starting at index 0 + * @param len number of characters in message + */ + public abstract void write(char [] c, int len); + + /** + * Log a thread identifier and a message. + * + * @param c character array with message starting at index 0 + * @param len number of characters in message + */ + public abstract void writeThreadId(char [] c, int len); + + /** + * Copies characters from the string into the character array. + * Thread switching is disabled during this method's execution. + *

    + * TODO: There are special memory management semantics here that + * someone should document. + * + * @param src the source string + * @param dst the destination array + * @param dstBegin the start offset in the desination array + * @param dstEnd the index after the last character in the + * destination to copy to + * @return the number of characters copied. + */ + public abstract int copyStringToChars(String src, char [] dst, + int dstBegin, int dstEnd); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,43 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.pragma.Uninterruptible; + + +/** + * A counter that supports atomic increment and reset. + */ + at Uninterruptible public abstract class SynchronizedCounter { + + /** + * Reset the counter to 0, returning its previous value. + * + * @return The value of the counter, prior to reset. + */ + public abstract int reset(); + + /** + * Adds 1 to the counter. + * + * @return the value before the add + */ + public abstract int increment(); + + /** + * Peek at the counter + * + * @return The current value of the counter. + */ + public abstract int peek(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,80 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Class that supports scanning Objects or Arrays for references + * during tracing, handling those references, and computing death times + */ + at Uninterruptible public abstract class TraceInterface { + + + /*********************************************************************** + * + * Public Methods + */ + + /** + * Returns if the VM is ready for a garbage collection. + * + * @return True if the VM is ready for GC, false otherwise. + */ + public abstract boolean gcEnabled(); + + /** + * This adjusts the offset into an object to reflect what it would look like + * if the fields were laid out in memory space immediately after the object + * pointer. + * + * @param isScalar If this is a pointer store to a scalar object + * @param src The address of the source object + * @param slot The address within src into which + * the update will be stored + * @return The easy to understand offset of the slot + */ + public abstract Offset adjustSlotOffset(boolean isScalar, + ObjectReference src, + Address slot); + + /** + * This skips over the frames added by the tracing algorithm, outputs + * information identifying the method the containts the "new" call triggering + * the allocation, and returns the address of the first non-trace, non-alloc + * stack frame. + * + *@param typeRef The type reference (tib) of the object just allocated + * @return The frame pointer address for the method that allocated the object + */ + @Interruptible + public abstract Address skipOwnFramesAndDump(ObjectReference typeRef); + + /*********************************************************************** + * + * Wrapper methods + */ + public abstract void updateDeathTime(ObjectReference obj); + public abstract void setDeathTime(ObjectReference ref, Word time_); + public abstract void setLink(ObjectReference ref, ObjectReference link); + public abstract void updateTime(Word time_); + public abstract Word getOID(ObjectReference ref); + public abstract Word getDeathTime(ObjectReference ref); + public abstract ObjectReference getLink(ObjectReference ref); + public abstract Address getBootImageLink(); + public abstract Word getOID(); + public abstract void setOID(Word oid); + public abstract int getHeaderSize(); + public abstract int getHeaderEndOffset(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,386 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm; + +import org.mmtk.utility.options.Options; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.vm.gcspy.ByteStream; +import org.mmtk.vm.gcspy.IntStream; +import org.mmtk.vm.gcspy.ServerInterpreter; +import org.mmtk.vm.gcspy.ServerSpace; +import org.mmtk.vm.gcspy.ShortStream; +import org.mmtk.vm.gcspy.Util; +import org.vmmagic.pragma.Untraced; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Offset; + +/** + * This class is responsible for all VM-specific functionality required + * by MMTk.

    + * + * The class has three major elements. First it defines VM-specific + * constants which are used throughout MMTk, second, it declares + * singleton instances of each of the abstract classes in this + * package, and third, it provides factory methods for VM-specific + * instances which are needed by MMTk (such as Lock).

    + * + * Both the constants and the singleton instances are initialized to + * VM-specific values at build time using reflection and a VM-specific + * factory class. The system property mmtk.hostjvm is + * interrogated at build time to establish concrete instantations of + * the abstract classes in this package. By convention, + * mmtk.hostjvm will identify a VM-provided package which + * includes concrete instances of each of the abstract classes, with + * each concrete class having the same base class name (but different + * package name) as the abstract classes defined here. The class + * initializer for this class then uses the system property + * mmtk.hostjvm to load the VM-specific concrete classes + * and initialize the constants and singletons defined here. + */ +public final class VM { + /* + * VM-specific constant values + */ + /** true if assertions should be verified */ + public static final boolean VERIFY_ASSERTIONS; + /** The lowest address in virtual memory known to MMTk */ + public static final Address HEAP_START; + /** The highest address in virtual memory known to MMTk */ + public static final Address HEAP_END; + /** The lowest address in the contiguously available memory available to MMTk */ + public static final Address AVAILABLE_START; + /** The highest address in the contiguously available memory available to MMTk */ + public static final Address AVAILABLE_END; + /** The log base two of the size of an address */ + public static final byte LOG_BYTES_IN_ADDRESS; + /** The log base two of the size of a word */ + public static final byte LOG_BYTES_IN_WORD; + /** The log base two of the size of an OS page */ + public static final byte LOG_BYTES_IN_PAGE; + /** The log base two of the minimum allocation alignment */ + public static final byte LOG_MIN_ALIGNMENT; + /** The log base two of (MAX_ALIGNMENT/MIN_ALIGNMENT) */ + public static final byte MAX_ALIGNMENT_SHIFT; + /** The maximum number of bytes of padding to prepend to an object */ + public static final int MAX_BYTES_PADDING; + /** The value to store in alignment holes */ + public static final int ALIGNMENT_VALUE; + /** The offset from an array reference to element zero */ + public static final Offset ARRAY_BASE_OFFSET; + /** Global debugging switch */ + public static final boolean DEBUG; + + /* + * VM-specific functionality captured in a series of singleton classs + */ + @Untraced + public static final ActivePlan activePlan; + @Untraced + public static final Assert assertions; + @Untraced + public static final Barriers barriers; + @Untraced + public static final Collection collection; + @Untraced + public static final Config config; + @Untraced + public static final Memory memory; + @Untraced + public static final ObjectModel objectModel; + @Untraced + public static final ReferenceProcessor weakReferences; + @Untraced + public static final ReferenceProcessor softReferences; + @Untraced + public static final ReferenceProcessor phantomReferences; + @Untraced + public static final FinalizableProcessor finalizableProcessor; + @Untraced + public static final Scanning scanning; + @Untraced + public static final Statistics statistics; + @Untraced + public static final Strings strings; + @Untraced + public static final TraceInterface traceInterface; + @Untraced + public static final MMTk_Events events; + @Untraced + public static final Debug debugging; + + /* + * The remainder is does the static initialization of the + * above, reflectively binding to the appropriate host jvm + * classes. + */ + private static final Factory factory; + private static final String vmFactory; + + /** + * This class initializer establishes a VM-specific factory class + * using reflection, and then uses that to create VM-specific concrete + * instances of all of the vm classes, initializing the singltons in + * this class. Finally the constants declared in this class are + * initialized using the VM-specific singletons. + */ + static { + /* Identify the VM-specific factory using reflection */ + vmFactory = System.getProperty("mmtk.hostjvm"); + Factory xfa = null; + try { + xfa = (Factory) Class.forName(vmFactory).newInstance(); + } catch (Exception e) { + e.printStackTrace(); + System.exit(-1); // we must *not* go on if the above has failed + } + factory = xfa; + + /* Now instantiate the singletons using the factory */ + activePlan = factory.newActivePlan(); + assertions = factory.newAssert(); + barriers = factory.newBarriers(); + collection = factory.newCollection(); + memory = factory.newMemory(); + objectModel = factory.newObjectModel(); + Options.set = factory.getOptionSet(); + weakReferences = factory.newReferenceProcessor(ReferenceProcessor.Semantics.WEAK); + softReferences = factory.newReferenceProcessor(ReferenceProcessor.Semantics.SOFT); + phantomReferences = factory.newReferenceProcessor(ReferenceProcessor.Semantics.PHANTOM); + finalizableProcessor = factory.newFinalizableProcessor(); + scanning = factory.newScanning(); + statistics = factory.newStatistics(); + strings = factory.newStrings(); + traceInterface = factory.newTraceInterface(); + events = factory.newEvents(); + debugging = factory.newDebug(); + config = new Config(factory.newBuildTimeConfig()); + + /* Now initialize the constants using the vm-specific singletons */ + VERIFY_ASSERTIONS = Assert.verifyAssertionsTrapdoor(assertions); + HEAP_START = Memory.heapStartTrapdoor(memory); + HEAP_END = Memory.heapEndTrapdoor(memory); + AVAILABLE_START = Memory.availableStartTrapdoor(memory); + AVAILABLE_END = Memory.availableEndTrapdoor(memory); + LOG_BYTES_IN_ADDRESS = Memory.logBytesInAddressTrapdoor(memory); + LOG_BYTES_IN_WORD = Memory.logBytesInWordTrapdoor(memory); + LOG_BYTES_IN_PAGE = Memory.logBytesInPageTrapdoor(memory); + LOG_MIN_ALIGNMENT = Memory.logMinAlignmentTrapdoor(memory); + MAX_ALIGNMENT_SHIFT = Memory.maxAlignmentShiftTrapdoor(memory); + MAX_BYTES_PADDING = Memory.maxBytesPaddingTrapdoor(memory); + ALIGNMENT_VALUE = Memory.alignmentValueTrapdoor(memory); + ARRAY_BASE_OFFSET = ObjectModel.arrayBaseOffsetTrapdoor(objectModel); + DEBUG = Debug.isEnabledTrapdoor(debugging); + } + + /** + * Create a new Lock instance using the appropriate VM-specific + * concrete Lock sub-class. + * + * @see Lock + * + * @param name The string to be associated with this lock instance + * @return A concrete VM-specific Lock instance. + */ + public static Lock newLock(String name) { + return factory.newLock(name); + } + + /** + * Create a new SynchronizedCounter instance using the appropriate + * VM-specific concrete SynchronizedCounter sub-class. + * + * @see SynchronizedCounter + * + * @return A concrete VM-specific SynchronizedCounter instance. + */ + public static SynchronizedCounter newSynchronizedCounter() { + return factory.newSynchronizedCounter(); + } + + /********************************************************************** + * GCspy methods + */ + + /** + * Create a new Util instance using the appropriate + * VM-specific concrete Util sub-class. + * + * @see Util + * + * @return A concrete VM-specific Util instance. + */ + public static Util newGCspyUtil() { + return factory.newGCspyUtil(); + } + + /** + * Create a new ServerInterpreter instance using the appropriate + * VM-specific concrete ServerInterpreter sub-class. + * + * @see ServerInterpreter + * + * @return A concrete VM-specific ServerInterpreter instance. + */ + public static ServerInterpreter newGCspyServerInterpreter() { + return factory.newGCspyServerInterpreter(); + } + + /** + * Create a new ServerInterpreter instance using the appropriate + * VM-specific concrete ServerInterpreter sub-class. + * + * @see ServerInterpreter + * + * @return A concrete VM-specific ServerInterpreter instance. + */ + public static ServerSpace newGCspyServerSpace( + ServerInterpreter serverInterpreter, + String serverName, + String driverName, + String title, + String blockInfo, + int tileNum, + String unused, + boolean mainSpace) { + return factory.newGCspyServerSpace(serverInterpreter, serverName, driverName, + title, blockInfo, tileNum, unused, + mainSpace); + } + + /** + * Create a new ByteStream instance using the appropriate + * VM-specific concrete ByteStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see IntStream + * + * @return A concrete VM-specific ByteStream instance. + */ + public static ByteStream newGCspyByteStream( + AbstractDriver driver, + String name, + byte minValue, + byte maxValue, + byte zeroValue, + byte defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + return factory.newGCspyByteStream(driver, name, minValue, maxValue, + zeroValue, defaultValue, stringPre, stringPost, + presentation, paintStyle, indexMaxStream, + colour, summary); + } + + /** + * Create a new IntStream instance using the appropriate + * VM-specific concrete IntStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see IntStream + * + * @return A concrete VM-specific IntStream instance. + */ + public static IntStream newGCspyIntStream( + AbstractDriver driver, + String name, + int minValue, + int maxValue, + int zeroValue, + int defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + return factory.newGCspyIntStream(driver, name, minValue, maxValue, + zeroValue, defaultValue, stringPre, stringPost, + presentation, paintStyle, indexMaxStream, + colour, summary); + } + + /** + * Create a new ShortStream instance using the appropriate + * VM-specific concrete ShortStream sub-class. + * + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @see IntStream + * + * @return A concrete VM-specific IntStream instance. + */ + public static ShortStream newGCspyShortStream( + AbstractDriver driver, + String name, + short minValue, + short maxValue, + short zeroValue, + short defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + return factory.newGCspyShortStream(driver, name, minValue, maxValue, + zeroValue, defaultValue, stringPre, stringPost, + presentation, paintStyle, indexMaxStream, + colour, summary); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,147 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm.gcspy; + +import org.mmtk.utility.Log; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.GCspy; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.*; + +/** + * Set up a GCspy Stream with data type BYTE_TYPE + */ + + at Uninterruptible public abstract class ByteStream extends Stream { + + /**************************************************************************** + * + * Instance variables + */ + private byte[] data; // The stream data + private byte defaultValue; // The default value for the data items + + + /**************************************************************************** + * + * Initialization + */ + + /** + * Construct a new GCspy stream of BYTE_TYPE + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + */ + public ByteStream( + AbstractDriver driver, + String name, + byte minValue, + byte maxValue, + byte zeroValue, + byte defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + + super(driver, StreamConstants.BYTE_TYPE, name, + minValue, maxValue, zeroValue, defaultValue, + stringPre, stringPost, presentation, paintStyle, + indexMaxStream, colour, summary); + + data = (byte[])GCspy.util.createDataArray(new byte[0], driver.getMaxTileNum()); + this.defaultValue = defaultValue; + } + + /** + * Reset all data in this stream to default values. + */ + public void resetData() { + for (int i = 0; i < data.length; i++) + data[i] = defaultValue; + } + + + /** + * Distribute a value across a sequence of tiles. This handles the case + * when when an object spans two or more tiles and its value is to be + * attributed to each tile proportionally. + * + * @param start the index of the starting tile + * @param remainder the value left in the starting tile + * @param blockSize the size of each tile + * @param value the value to distribute + */ + public void distribute(int start, byte remainder, int blockSize, byte value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(remainder <= blockSize); + if (value <= remainder) { // fits in this tile + data[start] += value; + //checkspace(start, value, "scanObject fits in first tile"); + } else { + data[start] += remainder; + //checkspace(start, remainder, "scanObject remainder put in first tile"); + value -= remainder; + start++; + while (value >= blockSize) { + data[start] += blockSize; + //checkspace(start, blockSize, "scanObject subsequent tile"); + value -= blockSize; + start++; + } + data[start] += value; + //checkspace(start, value, "scanObject last tile"); + } + } + + /** + * Increment the value of a tile. + * @param index the index + * @param value the increment + */ + public void increment(int index, byte value) { data[index] += value; } + + /** + * Send the data and summary for this stream. + * @param event The event + * @param numTiles The number of tiles to send (which may be less than maxTileNum) + * @see #ByteStream + */ + public void send(int event, int numTiles) { + if (DEBUG) { + Log.write("sending "); Log.write(numTiles); Log.writeln(" int values"); + } + serverSpace.stream(streamId, numTiles); + for (int index = 0; index < numTiles; index++) + serverSpace.streamByteValue(data[index]); + serverSpace.streamEnd(); + sendSummary(); + } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,147 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm.gcspy; + +import org.mmtk.utility.Log; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.GCspy; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.*; + +/** + * Set up a GCspy Stream with data type INT_TYPE. + */ + at Uninterruptible public abstract class IntStream extends Stream { + + /**************************************************************************** + * + * Instance variables + */ + private int[] data; // The stream data + private int defaultValue; // The default value for the data items + + + /**************************************************************************** + * + * Initialization + */ + + /** + * Construct a new GCspy stream of INT_TYPE + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + */ + public IntStream( + AbstractDriver driver, + String name, + int minValue, + int maxValue, + int zeroValue, + int defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + + super(driver, StreamConstants.INT_TYPE, name, + minValue, maxValue, zeroValue, defaultValue, + stringPre, stringPost, presentation, paintStyle, + indexMaxStream, colour, summary); + + data = (int[])GCspy.util.createDataArray(new int[0], driver.getMaxTileNum()); + this.defaultValue = defaultValue; + } + + /** + * Reset all data in this stream to default values. + */ + public void resetData() { + for (int i = 0; i < data.length; i++) + data[i] = defaultValue; + } + + + /** + * Distribute a value across a sequence of tiles. This handles the case + * when when an object spans two or more tiles and its value is to be + * attributed to each tile proportionally. + * + * @param start the index of the starting tile + * @param remainder the value left in the starting tile + * @param blockSize the size of each tile + * @param value the value to distribute + */ + public void distribute(int start, int remainder, int blockSize, int value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(remainder <= blockSize); + if (value <= remainder) { // fits in this tile + data[start] += value; + //checkspace(start, value, "scanObject fits in first tile"); + } else { + data[start] += remainder; + //checkspace(start, remainder, "scanObject remainder put in first tile"); + value -= remainder; + start++; + while (value >= blockSize) { + data[start] += blockSize; + //checkspace(start, blockSize, "scanObject subsequent tile"); + value -= blockSize; + start++; + } + data[start] += value; + //checkspace(start, value, "scanObject last tile"); + } + } + + /** + * Increment the value of a tile. + * @param index the index + * @param value the increment + */ + public void increment(int index, int value) { data[index] += value; } + + /** + * Send the data and summary for this stream. + * @param event The event + * @param numTiles The number of tiles to send (which may be less than maxTileNum) + */ + public void send(int event, int numTiles) { + if (DEBUG) { + Log.write("sending "); Log.write(numTiles); Log.writeln(" int values"); + } + + serverSpace.stream(streamId, numTiles); + for (int index = 0; index < numTiles; index++) + serverSpace.streamIntValue(data[index]); + serverSpace.streamEnd(); + + sendSummary(); + } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,124 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm.gcspy; + +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; + +/** + * Abstract class for the GCspy server interpreter + * + * Implementing classes will mostly forward calls to the C gcspy library. + */ + at Uninterruptible public abstract class ServerInterpreter { + + protected static final int MAX_LEN = 64 * 1024; // Buffer size + protected static final int MAX_SPACES = 32; // Maximum number of spaces + protected static boolean initialised = false; + + protected ServerSpace[] spaces; // The server's spaces + protected Address server; // a pointer to the c server, gcspy_main_server_t server + + protected static final boolean DEBUG = false; + + /** + * Create a new ServerInterpreter singleton. + * @param name The name of the server + * @param port The number of the port on which to communicate + * @param verbose Whether the server is to run verbosely + */ + @Interruptible + public abstract void init(String name, int port, boolean verbose); + + /** + * Add an event to the ServerInterpreter. + * @param num the event number + * @param name the event name + */ + public abstract void addEvent(int num, String name); + + /** + * Set the general info for the ServerInterpreter. + * @param info the information + */ + public abstract void setGeneralInfo(String info); + + /** + * Get a pointer to the C server, gcspy_main_server_t. + * This address is used in alll calls to the server in the C library. + * @return the address of the server + */ + public Address getServerAddress() { return server; } + + /** + * Add a GCspy ServerSpace to the ServerInterpreter. + * This method returns a unique space ID for the ServerSpace + * (again used in calls to the C library). + * + * @param space the ServerSpace to add + * @return a unique id for this space + * @exception IndexOutOfBoundsException on attempt to add more than + * MAX_SPACES spaces + */ + @Interruptible + public int addSpace(ServerSpace space) { + int id = 0; + while (id < MAX_SPACES) { + if (spaces[id] == null) { + spaces[id] = space; + return id; + } + id++; + } + throw new IndexOutOfBoundsException( + "Too many spaces to add to interpreter.\nSet MAX_SPACES to higher value in ServerInterpreter."); + } + + /** + * Start the server, running its main loop in a pthread. + * @param wait Whether to wait for the client to connect + */ + public abstract void startServer(boolean wait); + + /** + * Are we connected to a GCspy client? + * @param event The current event + * @return true if we are connected + */ + public abstract boolean isConnected(int event); + + /** + * Start compensation timer so that time spent gathering data is + * not confused with the time spent in the application and the VM. + */ + public abstract void startCompensationTimer(); + + /** + * Stop compensation timer so that time spent gathering data is + * not confused with the time spent in the application and the VM.r + */ + public abstract void stopCompensationTimer(); + + /** + * Indicate that we are at a server safe point (e.g. the end of a GC). + * This is a point at which the server can pause, play one, etc. + * @param event The current event + */ + public abstract void serverSafepoint(int event); + + /** + * Discover the smallest header size for objects. + * @return the size in bytes + */ + public abstract int computeHeaderSize(); +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,160 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm.gcspy; + +import org.mmtk.utility.Log; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Abstract class for the GCspy Space abstraction. + * + * Implementing classes will largely forward calls to the gcspy C library. + */ + at Uninterruptible public abstract class ServerSpace { + + /**************************************************************************** + * + * Class variables + */ + protected static final String DEFAULT_UNUSED_STRING = "NOT USED"; // The "unused" string + + /**************************************************************************** + * + * Instance variables + */ + protected int spaceId; // the space's ID + protected Address driver; // a pointer to the C driver, gcspy_gc_drivert *driver; + protected static final boolean DEBUG = false; + + + /** + * Get a pointer to the native driver + * @return The address of the C driver, gcspy_gc_drivert *, used in all calls + * to the C library. + */ + Address getDriverAddress() { + return driver; + } + + /** + * Tell the native driver the tile name. + * @param i the number of the tile + * @param start the starting address of the tile + * @param end the end address + */ + public abstract void setTilename(int i, Address start, Address end); + + /** + * Tell the native driver the tile name. + * @param i the number of the tile + * @param format the name of the tile, a format string + * @param value The value for the format string + */ + public abstract void setTilename(int i, Address format, long value); + + /** + * Tell the native driver the tile names. + * @param i the number of the tile + * @param format The name, including format tags + * @param value The value for the format string + */ + public abstract void setTilename(int i, String format, long value); + + /** + * Tell the C driver to resize + * @param size the new driver size + */ + public abstract void resize(int size); + + /** + * Start a transmission + */ + public abstract void startCommunication(); + + /** + * Add a stream to the native driver + * @param id the stream's ID + * @return the address of the C gcspy_gc_stream_t + */ + public abstract Address addStream(int id); + + /** + * Start transmitting a stream. + * @param id The stream's ID + * @param len The number of items in the stream + */ + public abstract void stream(int id, int len); + + /** + * Send a byte + * @param value The byte + */ + public abstract void streamByteValue(byte value); + + /** + * Send a short + * @param value The short + */ + public abstract void streamShortValue(short value); + + /** + * Send an int + * @param value The int + */ + public abstract void streamIntValue(int value); + + /** + * End of this stream + */ + public abstract void streamEnd(); + + /** + * Start to send a summary + * @param id The stream's ID + * @param len The number of items to be sent + */ + public abstract void summary(int id, int len); + + /** + * Send a summary value + * @param val The value + */ + public abstract void summaryValue(int val); + + /** + * End the summary + */ + public abstract void summaryEnd(); + + /** + * Send all the control info for the space + * @param space The GCspy driver for this space + * @param tileNum The number of tiles + */ + public abstract void sendControls(AbstractDriver space, int tileNum); + + /** + * Send info for this space + * @param info A pointer to the information (held as C string) + */ + public abstract void spaceInfo(Address info); + + /** + * End the transmission (for this event) + */ + public void endCommunication() { + if (DEBUG) Log.write("endComm\n"); + } +} Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,146 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm.gcspy; + +import org.mmtk.utility.Log; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.GCspy; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.*; + +/** + * Set up a GCspy Stream with data type SHORT_TYPE. + */ + at Uninterruptible public abstract class ShortStream extends Stream { + + /**************************************************************************** + * + * Instance variables + */ + private short[] data; // The stream data + private short defaultValue; // The default value for the data items + + /**************************************************************************** + * + * Initialization + */ + + /** + * Construct a new GCspy stream of SHORT_TYPE + * @param driver The driver that owns this Stream + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. + * Values less than this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. + * Values greater than this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + */ + public ShortStream( + AbstractDriver driver, + String name, + short minValue, + short maxValue, + short zeroValue, + short defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + + super(driver, StreamConstants.SHORT_TYPE, name, + minValue, maxValue, zeroValue, defaultValue, + stringPre, stringPost, presentation, paintStyle, + indexMaxStream, colour, summary); + + data = (short[])GCspy.util.createDataArray(new short[0], driver.getMaxTileNum()); + this.defaultValue = defaultValue; + } + + /** + * Reset all data in this stream to default values. + */ + public void resetData() { + for (int i = 0; i < data.length; i++) + data[i] = defaultValue; + } + + + /** + * Distribute a value across a sequence of tiles. This handles the case + * when when an object spans two or more tiles and its value is to be + * attributed to each tile proportionally. + * + * @param start the index of the starting tile + * @param remainder the value left in the starting tile + * @param blockSize the size of each tile + * @param value the value to distribute + */ + public void distribute(int start, short remainder, int blockSize, short value) { + if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(remainder <= blockSize); + if (value <= remainder) { // fits in this tile + data[start] += value; + //checkspace(start, value, "scanObject fits in first tile"); + } else { + data[start] += remainder; + //checkspace(start, remainder, "scanObject remainder put in first tile"); + value -= remainder; + start++; + while (value >= blockSize) { + data[start] += blockSize; + //checkspace(start, blockSize, "scanObject subsequent tile"); + value -= blockSize; + start++; + } + data[start] += value; + //checkspace(start, value, "scanObject last tile"); + } + } + + /** + * Increment the value of a tile. + * @param index the index + * @param value the increment + */ + public void increment(int index, short value) { data[index] += value; } + + /** + * Send the data and summary for this stream. + * @param event The event + * @param numTiles The number of tiles to send (which may be less than maxTileNum) + */ + public void send(int event, int numTiles) { + if (DEBUG) { + Log.write("sending "); Log.write(numTiles); Log.writeln(" int values"); + } + serverSpace.stream(streamId, numTiles); + for (int index = 0; index < numTiles; index++) + serverSpace.streamShortValue(data[index]); + serverSpace.streamEnd(); + + // send the summary + sendSummary(); + } +} + Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,217 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm.gcspy; + +import org.mmtk.utility.Log; +import org.mmtk.utility.gcspy.Color; +import org.mmtk.utility.gcspy.StreamConstants; +import org.mmtk.utility.gcspy.drivers.AbstractDriver; +import org.mmtk.vm.VM; +import org.vmmagic.pragma.*; +import org.vmmagic.unboxed.Address; + +/** + * + * Abstract class for a GCspy Stream. + * Implementing classes will mostly forward calls + * to the gcspy C library + */ + + at Uninterruptible public abstract class Stream { + + /**************************************************************************** + * + * Instance variables + */ + + /** + * The address of the C stream, gcspy_gc_stream_t *stream, used in all calls + * to the C library + */ + protected Address stream; + + /** The owning GCspy space */ + protected ServerSpace serverSpace; + + /** The stream's ID */ + protected int streamId; + + /** + * A summary has 1 or 2 values depending on presentation style + * (PERCENT* styles require 2 values). + */ + protected int summaryLen; + + /** The first summary value */ + protected int summary0; + + /** The second summary value (if any) */ + protected int summary1; + + private int min; // The minimum value for tiles + + private int max; // The maximum value for tiles + + /** use summaries? */ + protected boolean summaryEnabled; + + /** the presentation style */ + protected int presentation; + + protected static final boolean DEBUG = false; + + /** + * Construct a new GCspy stream. + * + * @param driver The AbstractDriver that owns this Stream + * @param dataType The stream's data type, one of BYTE_TYPE, SHORT_TYPE or INT_TYPE + * @param name The name of the stream (e.g. "Used space") + * @param minValue The minimum value for any item in this stream. Values less than + * this will be represented as "minValue-" + * @param maxValue The maximum value for any item in this stream. Values greater than + * this will be represented as "maxValue+" + * @param zeroValue The zero value for this stream + * @param defaultValue The default value for this stream + * @param stringPre A string to prefix values (e.g. "Used: ") + * @param stringPost A string to suffix values (e.g. " bytes.") + * @param presentation How a stream value is to be presented. + * @param paintStyle How the value is to be painted. + * @param indexMaxStream The index for the maximum stream if the presentation is *_VAR. + * @param colour The default colour for tiles of this stream + * @param summary Is a summary enabled? + */ + protected Stream( + AbstractDriver driver, + int dataType, + String name, + int minValue, + int maxValue, + int zeroValue, + int defaultValue, + String stringPre, + String stringPost, + int presentation, + int paintStyle, + int indexMaxStream, + Color colour, + boolean summary) { + + serverSpace = driver.getServerSpace(); + summaryEnabled = summary; + this.presentation = presentation; + if (summary) + setupSummary(presentation); + min = minValue; + max = maxValue; + + driver.addStream(this); + if (DEBUG) { + Log.write("Adding stream "); + Log.write(name); + Log.writeln(" id=", streamId); + } + } + + + /** + * Set the stream address and id (called by AbstractDriver.addStream). + * @param id the id + * @param str the address of the gcspy C gcspy_gc_stream_t *stream + */ + public void setStream(int id, Address str) { + streamId = id; + stream = str; + } + + /** + * Return the minimum value expected for this stream. + * @return the minimum value + */ + public int getMinValue() { return min; } + + /** + * Return the maximum value expected for this stream. + * @return the maximum value + */ + public int getMaxValue() { return max; } + + /** + * Setup the summary array. + * @param presentation the presentation style + */ + @Interruptible + private void setupSummary(int presentation) { + switch (presentation) { + case StreamConstants.PRESENTATION_PLAIN: + case StreamConstants.PRESENTATION_PLUS: + case StreamConstants.PRESENTATION_MAX_VAR: + case StreamConstants.PRESENTATION_ENUM: + summaryLen = 1; + break; + case StreamConstants.PRESENTATION_PERCENT: + case StreamConstants.PRESENTATION_PERCENT_VAR: + summaryLen = 2; + break; + default: + VM.assertions._assert(false); + } + } + + /** + * Set the summary value for presentation styles with just one value + * @param value0 the value + */ + public void setSummary(int value0) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(presentation != StreamConstants.PRESENTATION_PERCENT && + presentation != StreamConstants.PRESENTATION_PERCENT_VAR); + summary0 = value0; + } + + /** + * Set the summary values for presentation styles with two values (i.e. + * PRESENTATION_PERCENT and PRESENTATION_PERCENT_VAR). + * @param value0 the numerator value + * @param value1 the denominator value + */ + public void setSummary(int value0, int value1) { + if (VM.VERIFY_ASSERTIONS) + VM.assertions._assert(presentation == StreamConstants.PRESENTATION_PERCENT || + presentation == StreamConstants.PRESENTATION_PERCENT_VAR); + summary0 = value0; + summary1 = value1; + } + + /** + * Send the data for this stream. + * @param event the event. + * @param numTiles the number of tiles to send. + */ + public abstract void send(int event, int numTiles); + + /** + * Send the summary data for this stream. + */ + public void sendSummary() { + if (summaryEnabled) { + serverSpace.summary(streamId, summaryLen); + serverSpace.summaryValue(summary0); + if (summaryLen == 2) + serverSpace.summaryValue(summary1); + serverSpace.summaryEnd(); + } + } + +} + + Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java (added) +++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,166 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Eclipse Public License (EPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/eclipse-1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.mmtk.vm.gcspy; + +import org.mmtk.utility.Log; +import org.vmmagic.unboxed.*; +import org.vmmagic.pragma.*; + +/** + * Abstract class that provides generally useful + * methods. + */ + at Uninterruptible public abstract class Util { + + /** + * Allocate an array of bytes with malloc + * + * @param size The size to allocate + * @return The start address of the memory allocated in C space + * @see #free + */ + public abstract Address malloc(int size); + + /** + * Free an array of bytes previously allocated with malloc + * + * @param addr The address of some memory previously allocated with malloc + * @see #malloc + */ + public abstract void free(Address addr); + + /** + * Dump a range in format [start,end) + * + * @param start The start of the range + * @param end The end of the range + */ + public static void dumpRange(Address start, Address end) { + Log.write("["); Log.write(start); + Log.write(","); Log.write(end); + Log.write(')'); + } + + /** + * Convert a String to a 0-terminated array of bytes + * + * @param str The string to convert + * @return The address of a null-terminated array in C-space + */ + public abstract Address getBytes(String str); + + /** + * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate + * + * @param buffer The buffer (in C space) in which to place the formatted size + * @param size The size in bytes + */ + public abstract void formatSize(Address buffer, int size); + + /** + * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate + * + * @param format A format string + * @param bufsize The size of a buffer large enough to hold the formatted result + * @param size The size in bytes + */ + public abstract Address formatSize(String format, int bufsize, int size); + +// public abstract Address formatSize(String format, int bufsize, int size); + + /** + * Place a string representation of a long in an array of bytes + * without incurring allocation + * + * @param buffer The byte array + * @param value The long to convert + * @return The length of the string representation of the integer + * -1 indicates some problem (e.g the char buffer was too small) + */ + public static int numToBytes(byte[] buffer, long value) { + return numToBytes(buffer, value, 10); + } + + /** + * Place a string representation of a long in an array of bytes + * without incurring allocation + * + * @param buffer The byte array + * @param value The long to convert + * @param radix the base to use for conversion + * @return The length of the string representation of the integer + * -1 indicates some problem (e.g the char buffer was too small) + */ + public static int numToBytes(byte[] buffer, long value, int radix) { + + if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) + radix = 10; + + if (value == 0) { + buffer[0] = (byte)'0'; + return 1; + } + + boolean negative; + long longValue; + int count; + if (!(negative = (value < 0))) { + longValue = -value; + count = 1; + } else { + longValue = value; + count = 2; + } + + long j = longValue; + while ((j /= radix) != 0) count++; + if (count > buffer.length) + return -1; // overflow + + int i = count; + do { + int ch = (int) -(longValue % radix); + if (ch > 9) + ch -= (10 - (int) 'a'); + else + ch += (int) '0'; + buffer [--i] = (byte) ch; + } while ((longValue /= radix) != 0); + if (negative) buffer [0] = (byte)'-'; + + return count; + + } + + /** + * sprintf(char *str, char *format, char* value) + * + * @param str The destination 'string' (memory in C space) + * @param format The format 'string' (memory in C space) + * @param value The value 'string' (memory in C space) + * @return The number of characters printed (as returned by C's sprintf + */ + public abstract int sprintf(Address str, Address format, Address value); + + /** + * Create an array of a particular type. + * The easiest way to use this is: + * Foo[] x = (Foo [])Stream.createDataArray(new Foo[0], numElements); + * @param templ a data array to use as a template + * @param numElements number of elements in new array + * @return the new array + */ + @Interruptible + public abstract Object createDataArray(Object templ, int numElements); +} + Added: vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,40 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; + +/** + * An intrinsic method is a method that is built in (that is, intrinsic) to the compiler + * rather than part of a class library. Intrinsic methods are an escape hatch to provide + * "magic" that is inexpressible int the Java programming language. A compiler intrinsic + * will usually generate a specific code sequence that is inlined and optimized as part + * by the compiler. Unless an intrinsic method is expected to be executed in a non-intrinsic + * aware compiler, the body of the method should be empty. + * + *

    If the Intrinsic annotation is applied to a method then then the method is a compiler + * intrinsic. If the Intrinsic annotation is applied to a class then all the methods of + * the class AND all subclasses are intrinsic.

    + * + *

    NOTE: At the current time the Intrinsic annotation is only used for documentation + * purposes but in the near future it is expected that the semantics of the annotation will + * be enforced by the compiler.

    + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE,ElementType.METHOD}) + at Inherited +public @interface Intrinsic { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,38 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; + +/** + * A Pragma is a mechanism for supplying information to the compiler to alter the code it + * generates for a method. A Pragma is similar to an {@link org.vmmagic.Intrinsic} + * but it does not provide any behaviour but provides information to the compiler that modifies + * optimizations, calling conventions and activation frame layout. + * + *

    If the Pragma annotation is applied to a method then then the method is a handled specially + * by the compiler. If the Pragma annotation is applied to a class then then all the methods in that + * class are handled specially by the compiler.

    + * + *

    NOTE: At the current time the Pragma annotation is only used for documentation + * purposes but in the near future it is expected that the semantics of the annotation will + * be enforced by the compiler.

    + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE,ElementType.METHOD}) + at Inherited +public @interface Pragma { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,44 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; + +/** + * The Unboxed annotation marks a type as unboxed. Besides the primitive types, all Java values + * are boxed types. Conceptually, they are represented by a pointer to a heap object. However, + * an unboxed type is represented by the value itself. All methods on an unboxed type are + * {@link Intrinsic}s. + * + *

    As an unboxed type is not a regular java object there are a few constraints on the way unboxed + * types are handled;

    + *
      + *
    • All methods are {@link Intrinsic} and thus there can be no virtual methods.
    • + *
    • An unboxed type can not be synchronized on.
    • + *
    • An unboxed type has no hashcode.
    • + *
    • An unboxed type MUST NOT be passed where an object is expected or when two overloaded methods + * can only be distinguished by by Object vs unboxed parameter type.
    • + *
    + * + *

    NOTE: At the current time the Unboxed annotation is only used for documentation + * purposes but in the near future it is expected that the semantics of the annotation will + * be enforced by the compiler.

    + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.TYPE) + at Inherited +public @interface Unboxed { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * Some methods shouldn't use registers for locals and stack values. + * E.g. CollectorThread can't relocate refs in registers of its own. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface BaselineNoRegisters { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * Methods with this pragma that are BaselineCompiled should save in its prologue, ALL registers that + * can be used to store local and stack registers in any BaselineCompiled method. Used by OSR. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface BaselineSaveLSRegisters { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,37 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * Methods of a class that implements this interface are treated specially + * by the compilers. + * + *

    Instead of saving just the non-volatile registers used by the method into + * the register save area of the method's stackframe, the compiler generates + * code to save *all* GPR and FPR registers except GPR0, FPR0, JTOC, and FP. + * + *

    Methods of a class that implement this interface may not return. + * (it is assumed that execution is resumed via a call to Magic.dynamicBridgeTo) + * + * @see org.jikesrvm.runtime.Magic#dynamicBridgeTo(org.jikesrvm.ArchitectureSpecific.CodeArray) + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.TYPE) + at Pragma +public @interface DynamicBridge { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,29 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * The entrypoint annotation indicates that the method or field is + * directly accessed by the compiler. We cache resolved values for + * these elements in Entrypoints. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.METHOD, ElementType.FIELD}) + at Pragma +public @interface Entrypoint { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,63 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma indicates that a particular method should always be inlined + * by the optimizing compiler. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface Inline { + /** + * Enumeration defining when to inline + */ + public enum When { + /** + * Always inline, regardless of arguments + */ + Always, + /** + * Inline when all the arguments are constants + */ + AllArgumentsAreConstant, + /** + * Inline when the specified arguments are constants + */ + ArgumentsAreConstant, + /** + * Inline when the VM is built without Assertions (VM.VerifyAssertions == false). + * Note: It would be nicer to have the more general ExpressionIsTrue annotation, + * but the argument expression to the annotation is restricted to be a fairly + * trivial constant, and that isn't enough to handle how VM.VERIFY_ASSERTIONS + * is defined in MMTk. + */ + AssertionsDisabled + } + /** + * When to inline, default When.Always + */ + When value() default When.Always; + /** + * Arguments that must be constant to cause inlining. NB for static methods 0 + * is the first argument whilst for virtual methods 0 is this + */ + int[] arguments() default {}; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,48 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * By default all Java code is interruptible, that is scheduling or garbage + * collection may occur at points within the code. Code can be marked as + * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to + * avoid garbage collection and thread scheduling. The {@link Uninterruptible} + * annotation disallows any operation that may cause garbage collection or + * thread scheduling, for example memory allocation. The {@link Unpreemptible} + * annotation doesn't disallow operations that can cause garbage collection or + * scheduling, but instructs the JVM to avoid inserting such operations during a + * block of code. + * + * In the internals of a VM most code wants to be {@link Uninterruptible}. + * However, code involved in scheduling and locking will cause context switches, + * and creating exception objects may trigger garbage collection, this code is + * therefore {@link Unpreemptible}. + * + * This pragma is used to declare that a particular method is interruptible. It + * is used to override the class-wide pragma {@link Uninterruptible}. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface Interruptible { + /** + * @return Explanation of why code needs to be interruptible + */ + String value() default ""; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,51 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * A pragma that can be used to declare that a particular method is logically + * uninterruptible even though it contains bytecodes that are actually + * interruptible. + * + * The effect of this pragma is to suppress warning messages about violations of + * uninterruptiblity when compiling a method that throws this exception. There + * are two cases in which using the pragma is justified. + *

      + *
    • Uninterruptibility is ensured via some other mechanism. For example, the + * method explicitly disables threadswitching around the interruptible regions + * (VM.sysWrite on String). Or the interruptible regions are not reachable when + * the VM is running (various VM.sysWrite that check VM.runningVM). + *
    • The interruptible regions represent an 'error' condition that will never + * be executed unless the VM is already in the process of reporting an error, + * for example RuntimeEntrypoints.raiseClassCastException. + *
        + * Extreme care must be exercised when using this pragma since it suppresses the + * checking of uninterruptibility. + *

        + * Use of this pragma is being phased out since it lumps together two possible + * special cases. Use either {@link Unpreemptible} or + * {@link UninterruptibleNoWarn} instead. + * {@link RVM-115} for more + * context. + * @deprecated + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface LogicallyUninterruptible { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * Methods of a class that implements this interface are treated specially + * by the compilers: + * -They are only called from C or C++ program + * -The compiler will generate the necessary prolog to insert a glue stack + * frame to map from the native stack/register convention to RVM's convention + * -It is an error to call these methods from Java + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.TYPE) + at Pragma +public @interface NativeBridge { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma indicates that a particular method should never have bounds + * checks generated. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface NoBoundsCheck { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * Use this annotation to mark methods that won't cause their reference arguments + * to escape. If we can convert the object referenced in to registers then the + * method marked with this annotation will be removed. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +public @interface NoEscapes { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma indicates that a particular method should never be inlined + * by the optimizing compiler. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface NoInline { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma indicates that a particular method should never have null checks + * generated. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface NoNullCheck { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,29 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma indicates that a particular method should never be + * compiled by the optimizing compiler. It also implies that the + * method will never be inlined by the optimizing compiler. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE, ElementType.METHOD}) + at Pragma +public @interface NoOptCompile { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * Use this annotation to mark types that must never move. This is intended for + * a very small set of VM internal types that are accessed without knowledge of the + * memory manager. This includes code, that is CALLed and fields that are loaded + * directly (such as Untraced fields). + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.TYPE) +public @interface NonMoving { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,27 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * Use this annotation to mark methods for which all allocation must never + * move. This is intended for a very small set of VM internal methods that + * specifically require these semantics. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) +public @interface NonMovingAllocation { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,48 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * By default all Java code is interruptible, that is scheduling or garbage + * collection may occur at points within the code. Code can be marked as + * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to + * avoid garbage collection and thread scheduling. The {@link Uninterruptible} + * annotation disallows any operation that may cause garbage collection or + * thread scheduling, for example memory allocation. The {@link Unpreemptible} + * annotation doesn't disallow operations that can cause garbage collection or + * scheduling, but instructs the JVM to avoid inserting such operations during a + * block of code. + * + * In the internals of a VM most code wants to be {@link Uninterruptible}. + * However, code involved in scheduling and locking will cause context switches, + * and creating exception objects may trigger garbage collection, this code is + * therefore {@link Unpreemptible}. + * + * This pragma is used to declare that a particular method is preemptible. It + * is used to override the class-wide pragma {@link Unpreemptible}. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE, ElementType.METHOD}) + at Pragma +public @interface Preemptible { + /** + * @return Explanation of why code needs to be preemptible + */ + String value() default ""; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,31 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma is used to indicate a method has no side effects. Use this pragma + * with care as it can cause compile time invocation of the method it is placed + * on. This pragma is used to imply weak purity of a method, and as such cannot + * remove calls to pure methods - as they may throw exceptions. + * {@link RVM-503}. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.METHOD}) + at Pragma +public @interface Pure { /* annotation has no value */ } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,36 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * When applied to class this annotation indicates that the data component + * of this field consists of an intrisically managed chunk of raw memory of + * the specified size. This is used as the basic building block for native + * width types. + * + * To construct types larger than those possible with RawStorage, simply + * construct an type with multiple (Unboxed) fields. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE}) + at Pragma +public @interface RawStorage { + boolean lengthInWords(); + int length(); +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma is used to indicate a field will be final in the running VM. We + * can't indicate all fields are final as some are used in the boot strap + * process. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.FIELD}) + at Pragma +public @interface RuntimeFinal { + /** The value of the field. Currently only boolean values can be RuntimeFinal. */ + boolean value(); +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,36 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma is a variant of Pure that is used to mark methods that have a + * special behaviour at boot image writing time and are Pure at runtime + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.METHOD}) + at Pragma +public @interface RuntimePure { + /** Enumeration of the special boot image return values */ + public enum ReturnValue { + /** the return value is unavailable until runtime*/ + Unavailable + } + /** What value should be returned */ + ReturnValue value() default ReturnValue.Unavailable; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,30 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * Methods of a class that implements this interface + * are treated specially by the machine code compiler: + * the method prologue saves all the volatile registers + * and the method epilogue restores all the volatile registers + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.TYPE) + at Pragma +public @interface SaveVolatile { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,30 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * This pragma indicates that a particular method is a specialized + * method invocation point, and could be optimized as such. + * + * All such methods must be static. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.METHOD) + at Pragma +public @interface SpecializedMethodInvoke { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,29 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.vmmagic.Pragma; + +/** + * This interface designates an object which should always be allocated a + * thin lock, since it is likely to be synchronized. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.TYPE) + at Pragma +public @interface SynchronizedObject { +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,32 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * An annotation for static native methods to show that they should be + * compiled as system calls. A system call is a lightweight call to a + * C function that doesn't set up the JNI environment and is therefore + * cheaper than JNI. The first argument to the function is the address + * of the C function to run. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.METHOD}) + at Pragma +public @interface SysCallNative { +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,64 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * By default all Java code is interruptible, that is scheduling or garbage + * collection may occur at points within the code. Code can be marked as + * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to + * avoid garbage collection and thread scheduling. The {@link Uninterruptible} + * annotation disallows any operation that may cause garbage collection or + * thread scheduling, for example memory allocation. The {@link Unpreemptible} + * annotation doesn't disallow operations that can cause garbage collection or + * scheduling, but instructs the JVM to avoid inserting such operations during a + * block of code. + * + * In the internals of a VM most code wants to be {@link Uninterruptible}. + * However, code involved in scheduling and locking will cause context switches, + * and creating exception objects may trigger garbage collection, this code is + * therefore {@link Unpreemptible}. + * + * Any method that is marked as uninterruptible is treated specially by the + * machine code compiler: + * + * (1) the normal thread switch test that would be emitted in the method + * prologue is omitted. + * + * (2) the stack overflow test that would be emitted in the method prologue is + * omitted. + * + * (3) calls to preemptible code causes warnings. + * + * (4) bytecodes that can cause interruption cause warnings. + * + * (5) uninterruptible code will be generated assuming no RuntimeExceptions are + * raised and without any GC maps (since by definition there can be noGC if + * control is not lost). + * + * This is the inverse of {@link Interruptible}. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE, ElementType.METHOD}) + at Pragma +public @interface Uninterruptible { + /** + * @return Explanation of why code needs to be uninterruptible + */ + String value() default ""; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,35 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * A pragma that has the same direct effect as {@link Uninterruptible} + * but also suppresses checking of uninterruptibility violations for + * the method. This should be used with care and is only justified + * for code only executed when creating the boot image. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE, ElementType.METHOD}) + at Pragma +public @interface UninterruptibleNoWarn { + /** + * @return Explanation of why uninterruptible warnings are disabled + */ + String value() default ""; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,58 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * By default all Java code is interruptible, that is scheduling or garbage + * collection may occur at points within the code. Code can be marked as + * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to + * avoid garbage collection and thread scheduling. The {@link Uninterruptible} + * annotation disallows any operation that may cause garbage collection or + * thread scheduling, for example memory allocation. The {@link Unpreemptible} + * annotation doesn't disallow operations that can cause garbage collection or + * scheduling, but instructs the JVM to avoid inserting such operations during a + * block of code. + * + * In the internals of a VM most code wants to be {@link Uninterruptible}. + * However, code involved in scheduling and locking will cause context switches, + * and creating exception objects may trigger garbage collection, this code is + * therefore {@link Unpreemptible}. + * + * Any method that is marked as unpreemptible is treated specially by the + * machine code compiler: + * + * (1) the normal thread switch test that would be emitted in the method + * prologue is omitted. + * + * (2) the stack overflow test that would be emitted in the method prologue is + * omitted. + * + * (3) calls to preemptible code causes warnings. + * + * This is the inverse of {@link Preemptible}. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE, ElementType.METHOD}) + at Pragma +public @interface Unpreemptible { + /** + * @return Explanation of why code needs to be unpreemptible + */ + String value() default ""; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,33 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import org.vmmagic.Pragma; + +/** + * A special case of {@link Unpreemptible} where the code may call out to other + * interruptible routines. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target({ElementType.TYPE, ElementType.METHOD}) + at Pragma +public @interface UnpreemptibleNoWarn { + /** + * @return Explanation of why code needs to be unpreemptible + */ + String value() default ""; +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,31 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.pragma; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * Use this annotation to mark fields that are read without the knowledge of the + * memory management system. This means that barriers are not triggered and + * the reference is also not traced by the garbage collector. + * + * As annotations are loaded at class resolution time, fields marked with this + * annotation must be private so that no unresolved accesses are compiled to them with + * barriers. + */ + at Retention(RetentionPolicy.RUNTIME) + at Target(ElementType.FIELD) +public @interface Untraced { } Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,952 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.unboxed; + +import org.vmmagic.Unboxed; +import org.vmmagic.pragma.RawStorage; + +/** + * Stub implementation of an Address type, intended only to + * allow the core of MMTk to be compiled. This must be + * replaced with a concrete implementation appropriate to a specific + * VM. + * + * The address type is used by the runtime system and collector to + * denote machine addresses. We use a separate type instead of the + * Java int type for coding clarity, machine-portability (it can map + * to 32 bit and 64 bit integral types), and access to unsigned + * operations (Java does not have unsigned int types). + */ + at Unboxed + at RawStorage(lengthInWords = true, length = 1) +public final class Address { + + /**************************************************************************** + * + * Special values + */ + + /** + * Return an Address instance that reflects the value + * zero. + * + * @return An address instance that reflects the value zero. + */ + public static Address zero() { + return null; + } + + /** + * Return true if this instance is zero. + * + * @return true if this instance is zero. + */ + public boolean isZero() { + return false; + } + + /** + * Return an Address instance that reflects the maximum + * allowable Address value. + * + * @return An Address instance that reflects the + * maximum allowable Address value. + */ + public static Address max() { + return null; + } + + /** + * Return true if this instance is the maximum + * allowable Address value. + * + * @return true if this instance is the maximum + * allowable Address valu. + */ + public boolean isMax() { + return false; + } + + /**************************************************************************** + * + * Conversions + */ + + /** + * Fabricate an Address instance from an integer, after + * sign extending the integer. + * + * @param address the integer from which to create an Address + * instance + * @return An address instance + */ + public static Address fromIntSignExtend(int address) { + return null; + } + + /** + * Fabricate an Address instance from an integer, after + * zero extending the integer. + * + * @param address the integer from which to create an Address + * instance + * @return An address instance + */ + public static Address fromIntZeroExtend(int address) { + return null; + } + + /** + * Fabricate an Address instance from an integer + * + * @param address the integer from which to create an Address + * instance + * @return An address instance + */ + public static Address fromLong(long address) { + return null; + } + + /** + * Fabricate an ObjectReference instance from an + * Address instance. It is the user's responsibility + * to ensure that the Address is suitable (i.e. it + * points to the object header, or satisfies any other VM-specific + * requirement for such a conversion). + * + * @return An ObjectReference instance. + */ + public ObjectReference toObjectReference() { + return null; + } + + /** + * Return an integer that reflects the value of this + * Address instance. + * + * @return An integer that reflects the value of this + * Address instance. + */ + public int toInt() { + return 0; + } + + /** + * Return an long that reflects the value of this + * Address instance. + * + * @return An long that reflects the value of this + * Address instance. + */ + public long toLong() { + return 0; + } + + /** + * Return a Word instance that reflects the value of + * this Address instance. + * + * @return A Word instance that reflects the value of + * this Address instance. + */ + public Word toWord() { + return null; + } + + /**************************************************************************** + * + * Arithemtic operators + */ + + /** + * Add an integer to this Address, and return the sum. + * + * @param v the value to be added to this Address + * @return An Address instance that reflects the result + * of the addition. + */ + public Address plus(int v) { + return null; + } + + /** + * Add an Offset to this Address, and + * return the sum. + * + * @param offset the Offset to be added to the address + * @return An Address instance that reflects the result + * of the addition. + */ + public Address plus(Offset offset) { + return null; + } + + /** + * Add an Extent to this Address, and + * return the sum. + * + * @param extent the Extent to be added to this + * Address + * @return An Address instance that reflects the result + * of the addition. + */ + public Address plus(Extent extent) { + return null; + } + + /** + * Subtract an integer from this Address, and return + * the result. + * + * @param v the integer to be subtracted from this + * Address. + * @return An Address instance that reflects the result + * of the subtraction. + */ + public Address minus(int v) { + return null; + } + + /** + * Subtract an Offset from this Address, and + * return the result. + * + * @param offset the Offset to be subtracted from this + * Address. + * @return An Address instance that reflects the result + * of the subtraction. + */ + public Address minus(Offset offset) { + return null; + } + + /** + * Subtract an Extent from this Address, and + * return the result. + * + * @param extent the Extent to be subtracted from this + * Address. + * @return An Address instance that reflects the result + * of the subtraction. + */ + public Address minus(Extent extent) { + return null; + } + + /** + * Compute the difference between two Addresses and + * return the result. + * + * @param addr2 the Address to be subtracted from this + * Address. + * @return An Offset instance that reflects the result + * of the subtraction. + */ + public Offset diff(Address addr2) { + return null; + } + + /**************************************************************************** + * + * Boolean operators + */ + + /** + * Return true if this Address instance is less + * than addr2. + * + * @param addr2 the Address to be compared to this + * Address. + * @return true if this Address instance is less + * than addr2. + */ + public boolean LT(Address addr2) { + return false; + } + + /** + * Return true if this Address instance is less + * than or equal to addr2. + * + * @param addr2 the Address to be compared to this + * Address. + * @return true if this Address instance is less + * than or equal to addr2. + */ + public boolean LE(Address addr2) { + return false; + } + + /** + * Return true if this Address instance is greater + * than addr2. + * + * @param addr2 the Address to be compared to this + * Address. + * @return true if this Address instance is greater + * than addr2. + */ + public boolean GT(Address addr2) { + return false; + } + + /** + * Return true if this Address instance is greater + * than or equal to addr2. + * + * @param addr2 the Address to be compared to this + * Address. + * @return true if this Address instance is greater + * than or equal to addr2. + */ + public boolean GE(Address addr2) { + return false; + } + + /** + * Return true if this Address instance is equal + * to addr2. + * + * @param addr2 the Address to be compared to this + * Address. + * @return true if this Address instance is equal + * to addr2. + */ + public boolean EQ(Address addr2) { + return false; + } + + /** + * Return true if this Address instance is not equal + * to addr2. + * + * @param addr2 the Address to be compared to this + * Address. + * @return true if this Address instance is not + * equal to addr2. + */ + public boolean NE(Address addr2) { + return false; + } + + /**************************************************************************** + * + * Software prefetch operators etc + */ + + /** + * Prefetch a cache-line, architecture-independent + */ + public void prefetch() { + } + + /**************************************************************************** + * + * Memory access operators + */ + + /** + * Loads a reference from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public ObjectReference loadObjectReference() { + return null; + } + + /** + * Loads a reference from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public ObjectReference loadObjectReference(Offset offset) { + return null; + } + + /** + * Loads a byte from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public byte loadByte() { + return (byte) 0; + } + + /** + * Loads a byte from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public byte loadByte(Offset offset) { + return (byte) 0; + } + + /** + * Loads a char from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public char loadChar() { + return (char) 0; + } + + /** + * Loads a char from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public char loadChar(Offset offset) { + return (char) 0; + } + + /** + * Loads a short from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public short loadShort() { + return (short) 0; + } + + /** + * Loads a short from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public short loadShort(Offset offset) { + return (short) 0; + } + + /** + * Loads a float from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public float loadFloat() { + return (float) 0; + } + + /** + * Loads a float from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public float loadFloat(Offset offset) { + return (float) 0; + } + + /** + * Loads an int from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public int loadInt() { + return 0; + } + + /** + * Loads an int from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public int loadInt(Offset offset) { + return 0; + } + + + /** + * Loads a long from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public long loadLong() { + return 0L; + } + + /** + * Loads a long from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public long loadLong(Offset offset) { + return 0L; + } + + /** + * Loads a double from the memory location pointed to by the + * current instance. + * + * @return the read value + */ + public double loadDouble() { + return 0; + } + + /** + * Loads a double from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read value + */ + public double loadDouble(Offset offset) { + return 0; + } + + + /** + * Loads an address value from the memory location pointed to by the + * current instance. + * + * @return the read address value. + */ + public Address loadAddress() { + return null; + } + + /** + * Loads an address value from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read address value. + */ + public Address loadAddress(Offset offset) { + return null; + } + + /** + * Loads a word value from the memory location pointed to by the + * current instance. + * + * @return the read word value. + */ + public Word loadWord() { + return null; + } + + /** + * Loads a word value from the memory location pointed to by the + * current instance. + * + * @param offset the offset to the value. + * @return the read word value. + */ + public Word loadWord(Offset offset) { + return null; + } + + /** + * Stores the address value in the memory location pointed to by the + * current instance. + * + * @param value The address value to store. + */ + public void store(ObjectReference value) { + } + + /** + * Stores the object reference value in the memory location pointed + * to by the current instance. + * + * @param value The object reference value to store. + * @param offset the offset to the value. + */ + public void store(ObjectReference value, Offset offset) { + } + + /** + * Stores the address value in the memory location pointed to by the + * current instance. + * + * @param value The address value to store. + */ + public void store(Address value) { + } + + /** + * Stores the address value in the memory location pointed to by the + * current instance. + * + * @param value The address value to store. + * @param offset the offset to the value. + */ + public void store(Address value, Offset offset) { + } + + /** + * Stores the float value in the memory location pointed to by the + * current instance. + * + * @param value The float value to store. + */ + public void store(float value) { + } + + /** + * Stores the float value in the memory location pointed to by the + * current instance. + * + * @param value The float value to store. + * @param offset the offset to the value. + */ + public void store(float value, Offset offset) { + } + + /** + * Stores the word value in the memory location pointed to by the + * current instance. + * + * @param value The word value to store. + */ + public void store(Word value) { + } + + /** + * Stores the word value in the memory location pointed to by the + * current instance. + * + * @param value The word value to store. + * @param offset the offset to the value. + */ + public void store(Word value, Offset offset) { + } + + /** + * Stores the byte value in the memory location pointed to by the + * current instance. + * + * @param value The byte value to store. + */ + public void store(byte value) { + } + + /** + * Stores the byte value in the memory location pointed to by the + * current instance. + * + * @param value The byte value to store. + * @param offset the offset to the value. + */ + public void store(byte value, Offset offset) { + } + + + /** + * Stores an int value in memory location pointed to by the + * current instance. + * + * @param value The int value to store. + */ + public void store(int value) { + } + + /** + * Stores an int value in memory location pointed to by the + * current instance. + * + * @param value The int value to store. + * @param offset the offset to the value. + */ + public void store(int value, Offset offset) { + } + + /** + * Stores a double value in memory location pointed to by the + * current instance. + * + * @param value The double value to store. + */ + public void store(double value) { + } + + /** + * Stores a double value in memory location pointed to by the + * current instance. + * + * @param value The double value to store. + * @param offset the offset to the value. + */ + public void store(double value, Offset offset) { + } + + + /** + * Stores a double value in memory location pointed to by the + * current instance. + * + * @param value The double value to store. + */ + public void store(long value) { + } + + /** + * Stores a double value in memory location pointed to by the + * current instance. + * + * @param value The double value to store. + * @param offset the offset to the value. + */ + public void store(long value, Offset offset) { + } + + /** + * Stores a char value in the memory location pointed to by the + * current instance. + * + * @param value the char value to store. + */ + public void store(char value) { + } + + /** + * Stores a char value in the memory location pointed to by the + * current instance. + * + * @param value the char value to store. + * @param offset the offset to the value. + */ + public void store(char value, Offset offset) { + } + + /** + * Stores a short value in the memory location pointed to by the + * current instance. + * + * @param value the short value to store. + */ + public void store(short value) { + } + + /** + * Stores a short value in the memory location pointed to by the + * current instance. + * + * @param value the short value to store. + * @param offset the offset to the value. + */ + public void store(short value, Offset offset) { + } + + /**************************************************************************** + * + * Atomic memory access operators (compare and swap) + */ + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @return the old value to be passed to an attempt call. + */ + public Word prepareWord() { + return null; + } + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @param offset the offset to the value. + * @return the old value to be passed to an attempt call. + */ + public Word prepareWord(Offset offset) { + return null; + } + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @return the old value to be passed to an attempt call. + */ + public ObjectReference prepareObjectReference() { + return null; + } + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @param offset the offset to the value. + * @return the old value to be passed to an attempt call. + */ + public ObjectReference prepareObjectReference(Offset offset) { + return null; + } + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @return the old value to be passed to an attempt call. + */ + public Address prepareAddress() { + return null; + } + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @param offset the offset to the value. + * @return the old value to be passed to an attempt call. + */ + public Address prepareAddress(Offset offset) { + return null; + } + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @return the old value to be passed to an attempt call. + */ + public int prepareInt() { + return 0; + } + + /** + * Prepare for an atomic store operation. This must be associated with + * a related call to attempt. + * + * @param offset the offset to the value. + * @return the old value to be passed to an attempt call. + */ + public int prepareInt(Offset offset) { + return 0; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @return true if the attempt was successful. + */ + public boolean attempt(int old, int value) { + return false; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @param offset the offset to the value. + * @return true if the attempt was successful. + */ + public boolean attempt(int old, int value, Offset offset) { + return false; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @return true if the attempt was successful. + */ + public boolean attempt(Word old, Word value) { + return false; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @param offset the offset to the value. + * @return true if the attempt was successful. + */ + public boolean attempt(Word old, Word value, Offset offset) { + return false; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @return true if the attempt was successful. + */ + public boolean attempt(ObjectReference old, ObjectReference value) { + return false; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @param offset the offset to the value. + * @return true if the attempt was successful. + */ + public boolean attempt(ObjectReference old, ObjectReference value, + Offset offset) { + return false; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @return true if the attempt was successful. + */ + public boolean attempt(Address old, Address value) { + return false; + } + + /** + * Attempt an atomic store operation. This must be associated with a + * related call to prepare. + * + * @param old the old value. + * @param value the new value. + * @param offset the offset to the value. + * @return true if the attempt was successful. + */ + public boolean attempt(Address old, Address value, Offset offset) { + return false; + } + +} Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,42 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.unboxed; + +public final class AddressArray { + + private final Address[] data; + + private AddressArray(int size) { + data = new Address[size]; + Address zero = Address.zero(); + for(int i=0; iWord instance is less than addr2 + */ + public boolean LT(Word addr2) { + return false; + } + + /** + * Less-than or equal comparison + * @param w2 + * @return true if this Word instance is less than or equal to w2 + */ + public boolean LE(Word w2) { + return false; + } + + /** + * Greater-than comparison + * @param w2 + * @return true if this Word instance is greater than w2 + */ + public boolean GT(Word w2) { + return false; + } + + /** + * Greater-than or equal comparison + * @param w2 + * @return true if this Word instance is greater than or equal to w2 + */ + public boolean GE(Word w2) { + return false; + } + + /** + * Equality comparison + * @param w2 + * @return true if this Word instance is equal to w2 + */ + public boolean EQ(Word w2) { + return false; + } + + /** + * Not-equal comparison + * @param w2 + * @return true if this Word instance is not equal to w2 + */ + public boolean NE(Word w2) { + return false; + } + + /** + * Bit-wise and of two words. + * @param w2 + * @return The word whose value is the bitwise and of this and w2 + */ + public Word and(Word w2) { + return null; + } + + /** + * Bit-wise or of two words. + * @param w2 + * @return The word whose value is the bitwise not of this and w2 + */ + public Word or(Word w2) { + return null; + } + + /** + * Bit-wise complement of a word. + * @return the bitwise complement of this + */ + public Word not() { + return null; + } + + /** + * Bit-wise exclusive or of two words. + * @param w2 + * @return The word whose value is the bitwise xor of this and w2 + */ + public Word xor(Word w2) { + return null; + } + + /** + * Left-shift a word. Shifts of a size greater than the Word are undefined and + * have an architecture and compiler specific behaviour. On Intel the shift + * amount ignores the most significant bits, for example for a 32bit Word 1 + * << 32 == 1, the result will be 0 on PowerPC. Shifts may or may not be + * combined by the compiler, this yields differing behaviour, for example for a + * 32bit Word 1 <<32 may or may not equal 1 << 16 << 16. + * + * @param amt the amount to shift by + * @return new Word shifted by the given amount + */ + public Word lsh(int amt) { + return null; + } + + /** + * Logical right-shift a word. Shifts of a size greater than the Word are undefined and + * have an architecture and compiler specific behaviour see also {@link #lsh(int)}. + * + * @param amt the amount to shift by + * @return new Word shifted by the given amount + */ + public Word rshl(int amt) { + return null; + } + + /** + * Arithmetic right-shift a word. Shifts of a size greater than the Word are undefined and + * have an architecture and compiler specific behaviour see also {@link #lsh(int)}. + * Arithmetic right-shift a word. Equivalent to the integer >> operator + * + * @param amt the amount to shift by + * @return new Word shifted by the given amount + */ + public Word rsha(int amt) { + return null; + } +} + Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,42 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmmagic.unboxed; + +public final class WordArray { + + private final Word[] data; + + private WordArray(int size) { + data = new Word[size]; + Word zero = Word.zero(); + for(int i=0; i"); + logNewLine(); + } + + /** + * Log the option values in Xml. + */ + public void logXml() { + logString(""); + logNewLine(); + + for(Option o = getFirst(); o != null; o = o.getNext()) { + logXml(o); + } + + logString(""); + logNewLine(); + } + + /** + * Format and log an option value. + * + * @param o The option. + * @param forXml Is this part of xml output? + */ + protected abstract void logValue(Option o, boolean forXml); + + /** + * Log a string. + */ + protected abstract void logString(String s); + + /** + * Print a new line. + */ + protected abstract void logNewLine(); + + /** + * Determine the VM specific key for a given option name. Option names are + * space delimited with capitalised words (e.g. "GC Verbosity Level"). + * + * @param name The option name. + * @return The VM specific key. + */ + protected abstract String computeKey(String name); + + /** + * A non-fatal error occurred during the setting of an option. This method + * calls into the VM and shall not cause the system to stop. + * + * @param o The responsible option. + * @param message The message associated with the warning. + */ + protected abstract void warn(Option o, String message); + + /** + * A fatal error occurred during the setting of an option. This method + * calls into the VM and is required to cause the system to stop. + * + * @param o The responsible option. + * @param message The error message associated with the failure. + */ + protected abstract void fail(Option o, String message); + + /** + * Convert bytes into pages, rounding up if necessary. + * + * @param bytes The number of bytes. + * @return The corresponding number of pages. + */ + @Uninterruptible + protected abstract int bytesToPages(Extent bytes); + + /** + * Convert from pages into bytes. + * @param pages the number of pages. + * @return The corresponding number of bytes. + */ + @Uninterruptible + protected abstract Extent pagesToBytes(int pages); +} + Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,114 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmutil.options; + +import org.vmmagic.pragma.Uninterruptible; +import org.vmmagic.unboxed.Extent; + +/** + * A memory option that stores values as a whole number of pages. + */ +public class PagesOption extends Option { + // values + protected int defaultValue; + protected int value; + + /** + * Create a new pages option. + * + * @param set The option set this option belongs to. + * @param name The space separated name for the option. + * @param desc The purpose of the option + * @param defaultPages The default value of the option. + */ + protected PagesOption(OptionSet set, String name, String desc, int defaultPages) { + super(set, PAGES_OPTION, name, desc); + this.value = this.defaultValue = defaultPages; + } + + /** + * Read the current value of the option in pages. + * + * @return The option value. + */ + @Uninterruptible + public int getPages() { + return this.value; + } + + /** + * Read the current value of the option in bytes. + * + * @return The option value. + */ + @Uninterruptible + public Extent getBytes() { + return set.pagesToBytes(this.value); + } + + /** + * Read the default value of the option in bytes. + * + * @return The default value. + */ + @Uninterruptible + public Extent getDefaultBytes() { + return set.pagesToBytes(this.defaultValue); + } + + /** + * Read the default value of the option in pages. + * + * @return The default value. + */ + @Uninterruptible + public int getDefaultPages() { + return this.defaultValue; + } + + /** + * Update the value of the option, echoing the change if logChanges is set. + * A warning is raised if the value is not a whole multiple of pages, and + * then the validate method is called to allow subclasses to perform any + * additional validation. + * + * @param value The new value for the option. + */ + public void setBytes(Extent value) { + int pages = set.bytesToPages(value); + warnIf(value.NE(set.pagesToBytes(pages)), "Value rounded up to a whole number of pages"); + setPages(pages); + } + + /** + * Update the value of the option, echoing the change if logChanges is set. + * The validate method is called to allow subclasses to perform any additional + * validation. + * + * @param pages The new value for the option. + */ + public void setPages(int pages) { + this.value = pages; + validate(); + set.logChange(this); + } + + /** + * Modify the default value of the option. + * + * @param value The new default value for the option. + */ + public void setDefaultPages(int value) { + this.value = this.defaultValue = value; + } +} Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java (added) +++ vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java Thu Jul 16 06:26:34 2009 @@ -0,0 +1,79 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.vmutil.options; + +import org.vmmagic.pragma.Uninterruptible; + +/** + * An option that has a simple string value. + */ +public class StringOption extends Option { + // values + protected String defaultValue; + protected String value; + + /** + * Create a new string option. + * + * @param set The option set this option belongs to. + * @param name The space separated name for the option. + * @param desc The purpose of the option + * @param defaultValue The default value of the option. + */ + protected StringOption(OptionSet set, String name, String desc, String defaultValue) { + super(set, STRING_OPTION, name, desc); + this.value = this.defaultValue = defaultValue; + } + + /** + * Read the current value of the option. + * + * @return The option value. + */ + @Uninterruptible + public String getValue() { + return this.value; + } + + /** + * Read the default value of the option + * + * @return The default value. + */ + @Uninterruptible + public String getDefaultValue() { + return this.defaultValue; + } + + /** + * Update the value of the option, echoing the change if the echoOptions + * option is set. This method also calls the validate method to allow + * subclasses to perform any required validation. + * + * @param value The new value for the option. + */ + public void setValue(String value) { + this.value = value; + validate(); + set.logChange(this); + } + + /** + * Modify the default value of the option. + * + * @param value The new default value for the option. + */ + public void setDefaultValue(String value) { + this.value = this.defaultValue = value; + } +} Added: vmkit/trunk/mmtk/magic/LowerJavaRT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/magic/LowerJavaRT.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/magic/LowerJavaRT.cpp (added) +++ vmkit/trunk/mmtk/magic/LowerJavaRT.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,73 @@ +//===-- LowerJavaRT.cpp - Remove references to RT classes and functions --===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" + +#include "jnjvm/JnjvmModule.h" + +#include + +using namespace llvm; + +namespace { + + class VISIBILITY_HIDDEN LowerJavaRT : public ModulePass { + public: + static char ID; + LowerJavaRT() : ModulePass((intptr_t)&ID) { } + + virtual bool runOnModule(Module &M); + private: + }; + char LowerJavaRT::ID = 0; + static RegisterPass X("LowerJavaRT", + "Remove references to RT"); + +bool LowerJavaRT::runOnModule(Module& M) { + bool Changed = true; + + for (Module::iterator I = M.begin(), E = M.end(); I != E;) { + GlobalValue& GV = *I; + ++I; + if (!strncmp(GV.getName().c_str(), "JnJVM_java", 10) || + !strncmp(GV.getName().c_str(), "java", 4)) { + GV.replaceAllUsesWith(M.getContext().getNullValue(GV.getType())); + GV.eraseFromParent(); + } + } + + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E;) { + GlobalValue& GV = *I; + ++I; + if (!strncmp(GV.getName().c_str(), "JnJVM_java", 10) || + !strncmp(GV.getName().c_str(), "java", 4)) { + GV.replaceAllUsesWith(M.getContext().getNullValue(GV.getType())); + GV.eraseFromParent(); + } + } + + + return Changed; +} + + +ModulePass* createLowerJavaRT() { + return new LowerJavaRT(); +} + +} Added: vmkit/trunk/mmtk/magic/LowerMagic.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/magic/LowerMagic.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/magic/LowerMagic.cpp (added) +++ vmkit/trunk/mmtk/magic/LowerMagic.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,1132 @@ +//===----- LowerConstantCalls.cpp - Changes arrayLength calls --------------===// +// +// JnJVM +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" + +#include + +using namespace llvm; + +namespace vmmagic { + + class VISIBILITY_HIDDEN LowerMagic : public FunctionPass { + public: + static char ID; + LowerMagic() : FunctionPass((intptr_t)&ID) { } + + virtual bool runOnFunction(Function &F); + private: + }; + char LowerMagic::ID = 0; + static RegisterPass X("LowerMagic", + "Lower magic calls"); + +static const char* AddressClass = "JnJVM_org_vmmagic_unboxed_Address_"; +static const char* AddressZeroMethod = 0; +static const char* AddressIsZeroMethod; +static const char* AddressMaxMethod; +static const char* AddressIsMaxMethod; +static const char* AddressFromIntSignExtendMethod; +static const char* AddressFromIntZeroExtendMethod; +static const char* AddressFromLongMethod; +static const char* AddressToObjectReferenceMethod; +static const char* AddressToIntMethod; +static const char* AddressToLongMethod; +static const char* AddressToWordMethod; +static const char* AddressPlusIntMethod; +static const char* AddressPlusOffsetMethod; +static const char* AddressPlusExtentMethod; +static const char* AddressMinusIntMethod; +static const char* AddressMinusOffsetMethod; +static const char* AddressMinusExtentMethod; +static const char* AddressDiffMethod; +static const char* AddressLTMethod; +static const char* AddressLEMethod; +static const char* AddressGTMethod; +static const char* AddressGEMethod; +static const char* AddressEQMethod; +static const char* AddressNEMethod; +static const char* AddressPrefetchMethod; +static const char* AddressLoadObjectReferenceMethod; +static const char* AddressLoadObjectReferenceAtOffsetMethod; +static const char* AddressLoadByteMethod; +static const char* AddressLoadByteAtOffsetMethod; +static const char* AddressLoadCharMethod; +static const char* AddressLoadCharAtOffsetMethod; +static const char* AddressLoadShortMethod; +static const char* AddressLoadShortAtOffsetMethod; +static const char* AddressLoadFloatMethod; +static const char* AddressLoadFloatAtOffsetMethod; +static const char* AddressLoadIntMethod; +static const char* AddressLoadIntAtOffsetMethod; +static const char* AddressLoadLongMethod; +static const char* AddressLoadLongAtOffsetMethod; +static const char* AddressLoadDoubleMethod; +static const char* AddressLoadDoubleAtOffsetMethod; +static const char* AddressLoadAddressMethod; +static const char* AddressLoadAddressAtOffsetMethod; +static const char* AddressLoadWordMethod; +static const char* AddressLoadWordAtOffsetMethod; +static const char* AddressStoreObjectReferenceMethod; +static const char* AddressStoreObjectReferenceAtOffsetMethod; +static const char* AddressStoreAddressMethod; +static const char* AddressStoreAddressAtOffsetMethod; +static const char* AddressStoreFloatMethod; +static const char* AddressStoreFloatAtOffsetMethod; +static const char* AddressStoreWordMethod; +static const char* AddressStoreWordAtOffsetMethod; +static const char* AddressStoreByteMethod; +static const char* AddressStoreByteAtOffsetMethod; +static const char* AddressStoreIntMethod; +static const char* AddressStoreIntAtOffsetMethod; +static const char* AddressStoreDoubleMethod; +static const char* AddressStoreDoubleAtOffsetMethod; +static const char* AddressStoreLongMethod; +static const char* AddressStoreLongAtOffsetMethod; +static const char* AddressStoreCharMethod; +static const char* AddressStoreCharAtOffsetMethod; +static const char* AddressStoreShortMethod; +static const char* AddressStoreShortAtOffsetMethod; +static const char* AddressPrepareWordMethod; +static const char* AddressPrepareWordAtOffsetMethod; +static const char* AddressPrepareObjectReferenceMethod; +static const char* AddressPrepareObjectReferenceAtOffsetMethod; +static const char* AddressPrepareAddressMethod; +static const char* AddressPrepareAddressAtOffsetMethod; +static const char* AddressPrepareIntMethod; +static const char* AddressPrepareIntAtOffsetMethod; +static const char* AddressAttemptIntMethod; +static const char* AddressAttemptIntAtOffsetMethod; +static const char* AddressAttemptWordMethod; +static const char* AddressAttemptWordAtOffsetMethod; +static const char* AddressAttemptObjectReferenceMethod; +static const char* AddressAttemptObjectReferenceAtOffsetMethod; +static const char* AddressAttemptAddressMethod; +static const char* AddressAttemptAddressAtOffsetMethod; + +static const char* ExtentClass = "JnJVM_org_vmmagic_unboxed_Extent_"; +static const char* ExtentToWordMethod = 0; +static const char* ExtentFromIntSignExtendMethod; +static const char* ExtentFromIntZeroExtendMethod; +static const char* ExtentZeroMethod; +static const char* ExtentOneMethod; +static const char* ExtentMaxMethod; +static const char* ExtentToIntMethod; +static const char* ExtentToLongMethod; +static const char* ExtentPlusIntMethod; +static const char* ExtentPlusExtentMethod; +static const char* ExtentMinusIntMethod; +static const char* ExtentMinusExtentMethod; +static const char* ExtentLTMethod; +static const char* ExtentLEMethod; +static const char* ExtentGTMethod; +static const char* ExtentGEMethod; +static const char* ExtentEQMethod; +static const char* ExtentNEMethod; + +static const char* ObjectReferenceClass = + "JnJVM_org_vmmagic_unboxed_ObjectReference_"; +static const char* ObjectReferenceFromObjectMethod = 0; +static const char* ObjectReferenceNullReferenceMethod; +static const char* ObjectReferenceToObjectMethod; +static const char* ObjectReferenceToAddressMethod; +static const char* ObjectReferenceIsNullMethod; + +static const char* OffsetClass = "JnJVM_org_vmmagic_unboxed_Offset_"; +static const char* OffsetFromIntSignExtendMethod = 0; +static const char* OffsetFromIntZeroExtendMethod; +static const char* OffsetZeroMethod; +static const char* OffsetMaxMethod; +static const char* OffsetToIntMethod; +static const char* OffsetToLongMethod; +static const char* OffsetToWordMethod; +static const char* OffsetPlusIntMethod; +static const char* OffsetMinusIntMethod; +static const char* OffsetMinusOffsetMethod; +static const char* OffsetEQMethod; +static const char* OffsetNEMethod; +static const char* OffsetSLTMethod; +static const char* OffsetSLEMethod; +static const char* OffsetSGTMethod; +static const char* OffsetSGEMethod; +static const char* OffsetIsZeroMethod; +static const char* OffsetIsMaxMethod; + +static const char* WordClass = "JnJVM_org_vmmagic_unboxed_Word_"; +static const char* WordFromIntSignExtendMethod = 0; +static const char* WordFromIntZeroExtendMethod; +static const char* WordFromLongMethod; +static const char* WordZeroMethod; +static const char* WordOneMethod; +static const char* WordMaxMethod; +static const char* WordToIntMethod; +static const char* WordToLongMethod; +static const char* WordToAddressMethod; +static const char* WordToOffsetMethod; +static const char* WordToExtentMethod; +static const char* WordPlusWordMethod; +static const char* WordPlusOffsetMethod; +static const char* WordPlusExtentMethod; +static const char* WordMinusWordMethod; +static const char* WordMinusOffsetMethod; +static const char* WordMinusExtentMethod; +static const char* WordIsZeroMethod; +static const char* WordIsMaxMethod; +static const char* WordLTMethod; +static const char* WordLEMethod; +static const char* WordGTMethod; +static const char* WordGEMethod; +static const char* WordEQMethod; +static const char* WordNEMethod; +static const char* WordAndMethod; +static const char* WordOrMethod; +static const char* WordNotMethod; +static const char* WordXorMethod; +static const char* WordLshMethod; +static const char* WordRshlMethod; +static const char* WordRshaMethod; + +static Function* CASPtr; +static Function* CASInt; + +static void initialiseFunctions(Module* M) { + if (!AddressZeroMethod) { + AddressZeroMethod = "JnJVM_org_vmmagic_unboxed_Address_zero__"; + AddressMaxMethod = "JnJVM_org_vmmagic_unboxed_Address_max__"; + AddressStoreObjectReferenceMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_ObjectReference_2"; + AddressLoadObjectReferenceMethod = "JnJVM_org_vmmagic_unboxed_Address_loadObjectReference__"; + AddressLoadAddressMethod = "JnJVM_org_vmmagic_unboxed_Address_loadAddress__"; + AddressLoadWordMethod = "JnJVM_org_vmmagic_unboxed_Address_loadWord__"; + AddressDiffMethod = "JnJVM_org_vmmagic_unboxed_Address_diff__Lorg_vmmagic_unboxed_Address_2"; + AddressPlusOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_plus__Lorg_vmmagic_unboxed_Offset_2"; + AddressStoreAddressMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Address_2"; + AddressPlusIntMethod = "JnJVM_org_vmmagic_unboxed_Address_plus__I"; + AddressLTMethod = "JnJVM_org_vmmagic_unboxed_Address_LT__Lorg_vmmagic_unboxed_Address_2"; + AddressGEMethod = "JnJVM_org_vmmagic_unboxed_Address_GE__Lorg_vmmagic_unboxed_Address_2"; + AddressStoreWordMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Word_2"; + AddressToObjectReferenceMethod = "JnJVM_org_vmmagic_unboxed_Address_toObjectReference__"; + AddressToWordMethod = "JnJVM_org_vmmagic_unboxed_Address_toWord__"; + AddressPrepareWordMethod = "JnJVM_org_vmmagic_unboxed_Address_prepareWord__"; + AddressAttemptWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_attempt__Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Offset_2"; + AddressPrepareWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_prepareWord__Lorg_vmmagic_unboxed_Offset_2"; + AddressLoadWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadWord__Lorg_vmmagic_unboxed_Offset_2"; + AddressStoreWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Offset_2"; + AddressPlusExtentMethod = "JnJVM_org_vmmagic_unboxed_Address_plus__Lorg_vmmagic_unboxed_Extent_2"; + AddressIsZeroMethod = "JnJVM_org_vmmagic_unboxed_Address_isZero__"; + AddressStoreAddressAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_Offset_2"; + AddressGTMethod = "JnJVM_org_vmmagic_unboxed_Address_GT__Lorg_vmmagic_unboxed_Address_2"; + AddressLoadAddressAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadAddress__Lorg_vmmagic_unboxed_Offset_2"; + AddressEQMethod = "JnJVM_org_vmmagic_unboxed_Address_EQ__Lorg_vmmagic_unboxed_Address_2"; + AddressLoadObjectReferenceAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadObjectReference__Lorg_vmmagic_unboxed_Offset_2"; + AddressLEMethod = "JnJVM_org_vmmagic_unboxed_Address_LE__Lorg_vmmagic_unboxed_Address_2"; + AddressAttemptWordMethod = "JnJVM_org_vmmagic_unboxed_Address_attempt__Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Word_2"; + AddressNEMethod = "JnJVM_org_vmmagic_unboxed_Address_NE__Lorg_vmmagic_unboxed_Address_2"; + AddressToLongMethod = "JnJVM_org_vmmagic_unboxed_Address_toLong__"; + AddressMinusExtentMethod = "JnJVM_org_vmmagic_unboxed_Address_minus__Lorg_vmmagic_unboxed_Extent_2"; + AddressLoadShortAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadShort__Lorg_vmmagic_unboxed_Offset_2"; + AddressStoreShortAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__SLorg_vmmagic_unboxed_Offset_2"; + AddressLoadShortMethod = "JnJVM_org_vmmagic_unboxed_Address_loadShort__"; + AddressStoreShortMethod = "JnJVM_org_vmmagic_unboxed_Address_store__S"; + AddressLoadByteMethod = "JnJVM_org_vmmagic_unboxed_Address_loadByte__"; + AddressLoadIntMethod = "JnJVM_org_vmmagic_unboxed_Address_loadInt__"; + AddressStoreIntMethod = "JnJVM_org_vmmagic_unboxed_Address_store__I"; + AddressStoreByteMethod = "JnJVM_org_vmmagic_unboxed_Address_store__B"; + AddressLoadByteAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadByte__Lorg_vmmagic_unboxed_Offset_2"; + AddressMinusIntMethod = "JnJVM_org_vmmagic_unboxed_Address_minus__I"; + AddressLoadIntAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadInt__Lorg_vmmagic_unboxed_Offset_2"; + AddressStoreByteAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__BLorg_vmmagic_unboxed_Offset_2"; + AddressFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Address_fromIntZeroExtend__I"; + AddressToIntMethod = "JnJVM_org_vmmagic_unboxed_Address_toInt__"; + + ExtentToWordMethod = "JnJVM_org_vmmagic_unboxed_Extent_toWord__"; + ExtentMinusExtentMethod = "JnJVM_org_vmmagic_unboxed_Extent_minus__Lorg_vmmagic_unboxed_Extent_2"; + ExtentPlusExtentMethod = "JnJVM_org_vmmagic_unboxed_Extent_plus__Lorg_vmmagic_unboxed_Extent_2"; + ExtentPlusIntMethod = "JnJVM_org_vmmagic_unboxed_Extent_plus__I"; + ExtentMinusIntMethod = "JnJVM_org_vmmagic_unboxed_Extent_minus__I"; + ExtentFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Extent_fromIntZeroExtend__I"; + ExtentFromIntSignExtendMethod = "JnJVM_org_vmmagic_unboxed_Extent_fromIntSignExtend__I"; + ExtentOneMethod = "JnJVM_org_vmmagic_unboxed_Extent_one__"; + ExtentNEMethod = "JnJVM_org_vmmagic_unboxed_Extent_NE__Lorg_vmmagic_unboxed_Extent_2"; + ExtentZeroMethod = "JnJVM_org_vmmagic_unboxed_Extent_zero__"; + ExtentToLongMethod = "JnJVM_org_vmmagic_unboxed_Extent_toLong__"; + ExtentToIntMethod = "JnJVM_org_vmmagic_unboxed_Extent_toInt__"; + ExtentEQMethod = "JnJVM_org_vmmagic_unboxed_Extent_EQ__Lorg_vmmagic_unboxed_Extent_2"; + ExtentGTMethod = "JnJVM_org_vmmagic_unboxed_Extent_GT__Lorg_vmmagic_unboxed_Extent_2"; + ExtentLTMethod = "JnJVM_org_vmmagic_unboxed_Extent_LT__Lorg_vmmagic_unboxed_Extent_2"; + ExtentMaxMethod = "JnJVM_org_vmmagic_unboxed_Extent_max__"; + + ObjectReferenceFromObjectMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_fromObject__Ljava_lang_Object_2"; + ObjectReferenceToObjectMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_toObject__"; + ObjectReferenceNullReferenceMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_nullReference__"; + ObjectReferenceToAddressMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_toAddress__"; + ObjectReferenceIsNullMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_isNull__"; + + WordOrMethod = "JnJVM_org_vmmagic_unboxed_Word_or__Lorg_vmmagic_unboxed_Word_2"; + WordRshlMethod = "JnJVM_org_vmmagic_unboxed_Word_rshl__I"; + WordToIntMethod = "JnJVM_org_vmmagic_unboxed_Word_toInt__"; + WordNotMethod = "JnJVM_org_vmmagic_unboxed_Word_not__"; + WordZeroMethod = "JnJVM_org_vmmagic_unboxed_Word_zero__"; + WordOneMethod = "JnJVM_org_vmmagic_unboxed_Word_one__"; + WordAndMethod = "JnJVM_org_vmmagic_unboxed_Word_and__Lorg_vmmagic_unboxed_Word_2"; + WordToAddressMethod = "JnJVM_org_vmmagic_unboxed_Word_toAddress__"; + WordLshMethod = "JnJVM_org_vmmagic_unboxed_Word_lsh__I"; + WordMinusWordMethod = "JnJVM_org_vmmagic_unboxed_Word_minus__Lorg_vmmagic_unboxed_Word_2"; + WordLTMethod = "JnJVM_org_vmmagic_unboxed_Word_LT__Lorg_vmmagic_unboxed_Word_2"; + WordPlusWordMethod = "JnJVM_org_vmmagic_unboxed_Word_plus__Lorg_vmmagic_unboxed_Word_2"; + WordLEMethod = "JnJVM_org_vmmagic_unboxed_Word_LE__Lorg_vmmagic_unboxed_Word_2"; + WordGEMethod = "JnJVM_org_vmmagic_unboxed_Word_GE__Lorg_vmmagic_unboxed_Word_2"; + WordEQMethod = "JnJVM_org_vmmagic_unboxed_Word_EQ__Lorg_vmmagic_unboxed_Word_2"; + WordNEMethod = "JnJVM_org_vmmagic_unboxed_Word_NE__Lorg_vmmagic_unboxed_Word_2"; + WordFromIntSignExtendMethod = "JnJVM_org_vmmagic_unboxed_Word_fromIntSignExtend__I"; + WordIsZeroMethod = "JnJVM_org_vmmagic_unboxed_Word_isZero__"; + WordXorMethod = "JnJVM_org_vmmagic_unboxed_Word_xor__Lorg_vmmagic_unboxed_Word_2"; + WordFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Word_fromIntZeroExtend__I"; + WordToExtentMethod = "JnJVM_org_vmmagic_unboxed_Word_toExtent__"; + WordMinusExtentMethod = "JnJVM_org_vmmagic_unboxed_Word_minus__Lorg_vmmagic_unboxed_Extent_2"; + WordToLongMethod = "JnJVM_org_vmmagic_unboxed_Word_toLong__"; + WordMaxMethod = "JnJVM_org_vmmagic_unboxed_Word_max__"; + WordToOffsetMethod = "JnJVM_org_vmmagic_unboxed_Word_toOffset__"; + WordGTMethod = "JnJVM_org_vmmagic_unboxed_Word_GT__Lorg_vmmagic_unboxed_Word_2"; + + + OffsetSLTMethod = "JnJVM_org_vmmagic_unboxed_Offset_sLT__Lorg_vmmagic_unboxed_Offset_2"; + OffsetFromIntSignExtendMethod = "JnJVM_org_vmmagic_unboxed_Offset_fromIntSignExtend__I"; + OffsetSGTMethod = "JnJVM_org_vmmagic_unboxed_Offset_sGT__Lorg_vmmagic_unboxed_Offset_2"; + OffsetPlusIntMethod = "JnJVM_org_vmmagic_unboxed_Offset_plus__I"; + OffsetZeroMethod = "JnJVM_org_vmmagic_unboxed_Offset_zero__"; + OffsetToWordMethod = "JnJVM_org_vmmagic_unboxed_Offset_toWord__"; + OffsetFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Offset_fromIntZeroExtend__I"; + OffsetSGEMethod = "JnJVM_org_vmmagic_unboxed_Offset_sGE__Lorg_vmmagic_unboxed_Offset_2"; + OffsetToIntMethod = "JnJVM_org_vmmagic_unboxed_Offset_toInt__"; + OffsetToLongMethod = "JnJVM_org_vmmagic_unboxed_Offset_toLong__"; + OffsetIsZeroMethod = "JnJVM_org_vmmagic_unboxed_Offset_isZero__"; + OffsetMinusIntMethod = "JnJVM_org_vmmagic_unboxed_Offset_minus__I"; + OffsetSLEMethod = "JnJVM_org_vmmagic_unboxed_Offset_sLE__Lorg_vmmagic_unboxed_Offset_2"; + OffsetEQMethod = "JnJVM_org_vmmagic_unboxed_Offset_EQ__Lorg_vmmagic_unboxed_Offset_2"; + OffsetMinusOffsetMethod = "JnJVM_org_vmmagic_unboxed_Offset_minus__Lorg_vmmagic_unboxed_Offset_2"; + } +} + +#include + +static bool removePotentialNullCheck(BasicBlock* Cur, Value* Obj) { + BasicBlock* BB = Cur->getUniquePredecessor(); + LLVMContext* Context = Cur->getParent()->getContext(); + if (BB) { + Instruction* T = BB->getTerminator(); + if (dyn_cast(T) && T != BB->begin()) { + BasicBlock::iterator BIE = BB->end(); + --BIE; // Terminator + --BIE; // Null test + if (ICmpInst* IE = dyn_cast(BIE)) { + if (IE->getPredicate() == ICmpInst::ICMP_EQ && + IE->getOperand(0) == Obj && + IE->getOperand(1) == Context->getNullValue(Obj->getType())) { + BIE->replaceAllUsesWith(ConstantInt::getFalse()); + BIE->eraseFromParent(); + return true; + } + } + } + } + return false; +} + +bool LowerMagic::runOnFunction(Function& F) { + Module* globalModule = F.getParent(); + LLVMContext& Context = globalModule->getContext(); + bool Changed = false; + const llvm::Type* pointerSizeType = + globalModule->getPointerSize() == llvm::Module::Pointer32 ? + Type::Int32Ty : Type::Int64Ty; + + initialiseFunctions(globalModule); + if (!CASPtr || CASPtr->getParent() != globalModule) { + if (pointerSizeType == Type::Int32Ty) { + CASPtr = globalModule->getFunction("llvm.atomic.cmp.swap.i32.p0i32"); + } else { + CASPtr = globalModule->getFunction("llvm.atomic.cmp.swap.i64.p0i64"); + } + CASInt = globalModule->getFunction("llvm.atomic.cmp.swap.i32.p0i32"); + } + + for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { + BasicBlock *Cur = BI; + for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) { + Instruction *I = II; + II++; + CallSite Call = CallSite::get(I); + Instruction* CI = Call.getInstruction(); + if (CI) { + Value* V = Call.getCalledValue(); + if (Function* FCur = dyn_cast(V)) { + const char* name = FCur->getNameStart(); + unsigned len = FCur->getNameLen(); + if (len > strlen(AddressClass) && + !memcmp(AddressClass, name, strlen(AddressClass))) { + + Changed = true; + // Remove the null check + if (Call.arg_begin() != Call.arg_end()) { + removePotentialNullCheck(Cur, Call.getArgument(0)); + } + + if (!strcmp(FCur->getNameStart(), AddressZeroMethod)) { + Constant* N = Context.getNullValue(FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressMaxMethod)) { + ConstantInt* M = Context.getConstantInt(Type::Int64Ty, (uint64_t)-1); + Constant* N = ConstantExpr::getIntToPtr(M, FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressStoreObjectReferenceMethod) || + !strcmp(FCur->getNameStart(), AddressStoreAddressMethod) || + !strcmp(FCur->getNameStart(), AddressStoreShortMethod) || + !strcmp(FCur->getNameStart(), AddressStoreByteMethod) || + !strcmp(FCur->getNameStart(), AddressStoreIntMethod) || + !strcmp(FCur->getNameStart(), AddressStoreWordMethod)) { + Value* Addr = Call.getArgument(0); + Value* Obj = Call.getArgument(1); + const llvm::Type* Ty = PointerType::getUnqual(Obj->getType()); + Addr = new BitCastInst(Addr, Ty, "", CI); + new StoreInst(Obj, Addr, CI); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressLoadObjectReferenceMethod) || + !strcmp(FCur->getNameStart(), AddressLoadAddressMethod) || + !strcmp(FCur->getNameStart(), AddressLoadWordMethod) || + !strcmp(FCur->getNameStart(), AddressLoadShortMethod) || + !strcmp(FCur->getNameStart(), AddressLoadByteMethod) || + !strcmp(FCur->getNameStart(), AddressLoadIntMethod) || + !strcmp(FCur->getNameStart(), AddressPrepareWordMethod)) { + Value* Addr = Call.getArgument(0); + const Type* Ty = PointerType::getUnqual(FCur->getReturnType()); + Addr = new BitCastInst(Addr, Ty, "", CI); + Value* LD = new LoadInst(Addr, "", CI); + CI->replaceAllUsesWith(LD); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressDiffMethod) || + !strcmp(FCur->getNameStart(), AddressMinusExtentMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressPlusOffsetMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressPlusIntMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressMinusIntMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressLTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressGTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressEQMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressNEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_NE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressLEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressGEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressToObjectReferenceMethod) || + !strcmp(FCur->getNameStart(), AddressToWordMethod)) { + Value* Val = Call.getArgument(0); + Val = new BitCastInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressAttemptWordAtOffsetMethod)) { + Value* Ptr = Call.getArgument(0); + Value* Old = Call.getArgument(1); + Value* Val = Call.getArgument(2); + Value* Offset = Call.getArgument(3); + + Ptr = new PtrToIntInst(Ptr, pointerSizeType, "", CI); + Offset = new PtrToIntInst(Offset, pointerSizeType, "", CI); + Ptr = BinaryOperator::CreateAdd(Ptr, Offset, "", CI); + const Type* Ty = PointerType::getUnqual(pointerSizeType); + Ptr = new IntToPtrInst(Ptr, Ty, "", CI); + Old = new PtrToIntInst(Old, pointerSizeType, "", CI); + Val = new PtrToIntInst(Val, pointerSizeType, "", CI); + + Value* Args[3] = { Ptr, Old, Val }; + Value* res = CallInst::Create(CASPtr, Args, Args + 3, "", CI); + res = new ICmpInst(CI, ICmpInst::ICMP_EQ, res, Old, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressAttemptWordMethod)) { + Value* Ptr = Call.getArgument(0); + Value* Old = Call.getArgument(1); + Value* Val = Call.getArgument(2); + + const Type* Ty = PointerType::getUnqual(pointerSizeType); + Ptr = new BitCastInst(Ptr, Ty, "", CI); + Old = new PtrToIntInst(Old, pointerSizeType, "", CI); + Val = new PtrToIntInst(Val, pointerSizeType, "", CI); + + Value* Args[3] = { Ptr, Old, Val }; + Value* res = CallInst::Create(CASPtr, Args, Args + 3, "", CI); + res = new ICmpInst(CI, ICmpInst::ICMP_EQ, res, Old, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressPrepareWordAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressLoadWordAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressLoadAddressAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressLoadObjectReferenceAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressLoadByteAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressLoadIntAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressLoadShortAtOffsetMethod)) { + Value* Ptr = Call.getArgument(0); + Value* Offset = Call.getArgument(1); + + Ptr = new PtrToIntInst(Ptr, pointerSizeType, "", CI); + Offset = new PtrToIntInst(Offset, pointerSizeType, "", CI); + Ptr = BinaryOperator::CreateAdd(Ptr, Offset, "", CI); + const Type* Ty = PointerType::getUnqual(FCur->getReturnType()); + Ptr = new IntToPtrInst(Ptr, Ty, "", CI); + Value* res = new LoadInst(Ptr, "", CI); + + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressStoreWordAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressStoreAddressAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressStoreByteAtOffsetMethod) || + !strcmp(FCur->getNameStart(), AddressStoreShortAtOffsetMethod)) { + Value* Ptr = Call.getArgument(0); + Value* Val = Call.getArgument(1); + Value* Offset = Call.getArgument(2); + + Ptr = new PtrToIntInst(Ptr, pointerSizeType, "", CI); + Offset = new PtrToIntInst(Offset, pointerSizeType, "", CI); + Ptr = BinaryOperator::CreateAdd(Ptr, Offset, "", CI); + const Type* Ty = PointerType::getUnqual(Val->getType()); + Ptr = new IntToPtrInst(Ptr, Ty, "", CI); + new StoreInst(Val, Ptr, CI); + + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressPlusExtentMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressIsZeroMethod)) { + Value* Val = Call.getArgument(0); + Constant* N = Context.getNullValue(Val->getType()); + Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, ""); + Res = new ZExtInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressToLongMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressFromIntZeroExtendMethod)) { + Value* Val = Call.getArgument(0); + if (pointerSizeType != Type::Int32Ty) + Val = new ZExtInst(Val, pointerSizeType, "", CI); + Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), AddressToIntMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else { + fprintf(stderr, "Implement me %s\n", name); + abort(); + } + + } else if (len > strlen(ExtentClass) && + !memcmp(ExtentClass, name, strlen(ExtentClass))) { + + Changed = true; + // Remove the null check + if (Call.arg_begin() != Call.arg_end()) { + removePotentialNullCheck(Cur, Call.getArgument(0)); + } + + if (!strcmp(FCur->getNameStart(), ExtentToWordMethod)) { + CI->replaceAllUsesWith(Call.getArgument(0)); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentMinusExtentMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentPlusExtentMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentPlusIntMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentMinusIntMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentFromIntZeroExtendMethod)) { + Value* Val = Call.getArgument(0); + if (pointerSizeType != Type::Int32Ty) + Val = new ZExtInst(Val, pointerSizeType, "", CI); + Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentFromIntSignExtendMethod)) { + Value* Val = Call.getArgument(0); + if (pointerSizeType != Type::Int32Ty) + Val = new SExtInst(Val, pointerSizeType, "", CI); + Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentOneMethod)) { + Constant* N = Context.getConstantInt(pointerSizeType, 1); + N = ConstantExpr::getIntToPtr(N, FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentNEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_NE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentEQMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentGTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentLTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentZeroMethod)) { + Constant* N = Context.getNullValue(FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentToLongMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentToIntMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ExtentMaxMethod)) { + ConstantInt* M = Context.getConstantInt(Type::Int64Ty, (uint64_t)-1); + Constant* N = ConstantExpr::getIntToPtr(M, FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else { + fprintf(stderr, "Implement me %s\n", name); + abort(); + } + } else if (len > strlen(OffsetClass) && + !memcmp(OffsetClass, name, strlen(OffsetClass))) { + + Changed = true; + // Remove the null check + if (Call.arg_begin() != Call.arg_end()) { + removePotentialNullCheck(Cur, Call.getArgument(0)); + } + + if (!strcmp(FCur->getNameStart(), OffsetSLTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_SLT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetToWordMethod)) { + Value* Val = Call.getArgument(0); + Val = new BitCastInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetZeroMethod)) { + Constant* N = Context.getNullValue(FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetSGTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_SGT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetSGEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_SGE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetSLEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_SLE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetEQMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetFromIntSignExtendMethod)) { + Value* Val = Call.getArgument(0); + if (pointerSizeType != Type::Int32Ty) + Val = new SExtInst(Val, pointerSizeType, "", CI); + Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetFromIntZeroExtendMethod)) { + Value* Val = Call.getArgument(0); + if (pointerSizeType != Type::Int32Ty) + Val = new ZExtInst(Val, pointerSizeType, "", CI); + Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetPlusIntMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetToIntMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetToLongMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetIsZeroMethod)) { + Value* Val = Call.getArgument(0); + Constant* N = Context.getNullValue(Val->getType()); + Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, ""); + Res = new ZExtInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetMinusIntMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), OffsetMinusOffsetMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else { + fprintf(stderr, "Implement me %s\n", name); + abort(); + } + } else if (len > strlen(ObjectReferenceClass) && + !memcmp(ObjectReferenceClass, name, strlen(ObjectReferenceClass))) { + + Changed = true; + // Remove the null check + if (Call.arg_begin() != Call.arg_end()) { + removePotentialNullCheck(Cur, Call.getArgument(0)); + } + + if (!strcmp(FCur->getNameStart(), ObjectReferenceNullReferenceMethod)) { + Constant* N = Context.getNullValue(FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ObjectReferenceFromObjectMethod)) { + Value* Val = Call.getArgument(0); + Val = new BitCastInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ObjectReferenceToAddressMethod)) { + Value* Val = Call.getArgument(0); + Val = new BitCastInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ObjectReferenceToObjectMethod)) { + Value* Val = Call.getArgument(0); + Val = new BitCastInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), ObjectReferenceIsNullMethod)) { + Value* Val = Call.getArgument(0); + Constant* N = Context.getNullValue(Val->getType()); + Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, ""); + Res = new ZExtInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else { + fprintf(stderr, "Implement me %s\n", name); + abort(); + } + } else if (len > strlen(WordClass) && + !memcmp(WordClass, name, strlen(WordClass))) { + + Changed = true; + // Remove the null check + if (Call.arg_begin() != Call.arg_end()) { + removePotentialNullCheck(Cur, Call.getArgument(0)); + } + + if (!strcmp(FCur->getNameStart(), WordOrMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* Res = BinaryOperator::CreateOr(Val1, Val2, "", CI); + Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordAndMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* Res = BinaryOperator::CreateAnd(Val1, Val2, "", CI); + Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordXorMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* Res = BinaryOperator::CreateXor(Val1, Val2, "", CI); + Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordRshlMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* Res = BinaryOperator::CreateLShr(Val1, Val2, "", CI); + Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordLshMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + if (Val2->getType() != pointerSizeType) + Val2 = new ZExtInst(Val2, pointerSizeType, "", CI); + Value* Res = BinaryOperator::CreateShl(Val1, Val2, "", CI); + Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordToIntMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordNotMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, pointerSizeType, "", CI); + Constant* M1 = Context.getConstantInt(pointerSizeType, -1); + Value* Res = BinaryOperator::CreateXor(Val, M1, "", CI); + Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordZeroMethod)) { + Constant* N = Context.getNullValue(FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordOneMethod)) { + Constant* N = Context.getConstantInt(pointerSizeType, 1); + N = ConstantExpr::getIntToPtr(N, FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordToAddressMethod) || + !strcmp(FCur->getNameStart(), WordToOffsetMethod) || + !strcmp(FCur->getNameStart(), WordToExtentMethod)) { + Value* Val = Call.getArgument(0); + Val = new BitCastInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordMinusWordMethod) || + !strcmp(FCur->getNameStart(), WordMinusExtentMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordPlusWordMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI); + res = new IntToPtrInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordLTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordLEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordGEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordEQMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordGTMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGT, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordNEMethod)) { + Value* Val1 = Call.getArgument(0); + Value* Val2 = Call.getArgument(1); + Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI); + Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI); + Value* res = new ICmpInst(CI, ICmpInst::ICMP_NE, Val1, Val2, ""); + res = new ZExtInst(res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordFromIntSignExtendMethod)) { + Value* Val = Call.getArgument(0); + if (pointerSizeType != Type::Int32Ty) + Val = new SExtInst(Val, pointerSizeType, "", CI); + Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordFromIntZeroExtendMethod)) { + Value* Val = Call.getArgument(0); + if (pointerSizeType != Type::Int32Ty) + Val = new ZExtInst(Val, pointerSizeType, "", CI); + Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordIsZeroMethod)) { + Value* Val = Call.getArgument(0); + Constant* N = Context.getNullValue(Val->getType()); + Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, ""); + Res = new ZExtInst(Res, FCur->getReturnType(), "", CI); + CI->replaceAllUsesWith(Res); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordToLongMethod)) { + Value* Val = Call.getArgument(0); + Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI); + CI->replaceAllUsesWith(Val); + CI->eraseFromParent(); + } else if (!strcmp(FCur->getNameStart(), WordMaxMethod)) { + ConstantInt* M = Context.getConstantInt(Type::Int64Ty, (uint64_t)-1); + Constant* N = ConstantExpr::getIntToPtr(M, FCur->getReturnType()); + CI->replaceAllUsesWith(N); + CI->eraseFromParent(); + } else { + fprintf(stderr, "Implement me %s\n", name); + abort(); + } + } + } + } + } + } + return Changed; +} + + +FunctionPass* createLowerMagicPass() { + return new LowerMagic(); +} + +} Added: vmkit/trunk/mmtk/magic/Makefile URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/magic/Makefile?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/magic/Makefile (added) +++ vmkit/trunk/mmtk/magic/Makefile Thu Jul 16 06:26:34 2009 @@ -0,0 +1,16 @@ +##===- mmtk/magic/Makefile ---------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = MMTKMagic +LOADABLE_MODULE = 1 +USEDLIBS = + +include $(LEVEL)/Makefile.common + Added: vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,22 @@ +//===------ ActivePlan.cpp - Implementation of the ActivePlan class ------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" JavaObject* Java_org_j3_mmtk_ActivePlan_getNextMutator__ (JavaObject* A) { + return 0; +} + +extern "C" void Java_org_j3_mmtk_ActivePlan_resetMutatorIterator__ (JavaObject* A) { + return; +} + +extern "C" void Java_org_j3_mmtk_ActivePlan_collectorCount__ () { abort(); } Added: vmkit/trunk/mmtk/mmtk-j3/Assert.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Assert.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Assert.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Assert.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,14 @@ +//===----------- Assert.cpp - Implementation of the Assert class ---------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_Assert_dumpStack__ () { abort(); } Added: vmkit/trunk/mmtk/mmtk-j3/Collection.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Collection.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Collection.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Collection.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,54 @@ +//===------- Collection.cpp - Implementation of the Collection class -----===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" void JnJVM_org_mmtk_plan_Plan_setCollectionTriggered__(); + +extern "C" void JnJVM_org_j3_config_Selected_00024Collector_staticCollect__(); + +extern "C" void JnJVM_org_mmtk_plan_Plan_collectionComplete__(); + + +extern "C" bool Java_org_j3_mmtk_Collection_isEmergencyAllocation__ (JavaObject* C) { + return false; +} + +extern "C" void Java_org_j3_mmtk_Collection_reportAllocationSuccess__ (JavaObject* C) { +} + + +extern "C" void Java_org_j3_mmtk_Collection_triggerCollection__I (JavaObject* C, int why) { + JnJVM_org_mmtk_plan_Plan_setCollectionTriggered__(); + JnJVM_org_j3_config_Selected_00024Collector_staticCollect__(); + JnJVM_org_mmtk_plan_Plan_collectionComplete__(); +} + +extern "C" int Java_org_j3_mmtk_Collection_rendezvous__I (JavaObject* C, int where) { + return 1; +} + +extern "C" int Java_org_j3_mmtk_Collection_maximumCollectionAttempt__ (JavaObject* C) { + return 1; +} + +extern "C" void Java_org_j3_mmtk_Collection_prepareCollector__Lorg_mmtk_plan_CollectorContext_2 (JavaObject* C, JavaObject* CC) { +} + + +extern "C" void Java_org_j3_mmtk_Collection_joinCollection__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Collection_reportPhysicalAllocationFailed__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Collection_triggerAsyncCollection__I () { abort(); } +extern "C" void Java_org_j3_mmtk_Collection_noThreadsInGC__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Collection_prepareMutator__Lorg_mmtk_plan_MutatorContext_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_Collection_activeGCThreads__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Collection_activeGCThreadOrdinal__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Collection_requestMutatorFlush__ () { abort(); } Added: vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,26 @@ +//===- FinalizableProcessor.cpp -------------------------------------------===// +//===- Implementation of the FinalizableProcessor class ------------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_FinalizableProcessor_clear__ () { + abort(); +} + +extern "C" void +Java_org_j3_mmtk_FinalizableProcessor_forward__Lorg_mmtk_plan_TraceLocal_2Z () { + abort(); +} + +extern "C" void +Java_org_j3_mmtk_FinalizableProcessor_scan__Lorg_mmtk_plan_TraceLocal_2Z () { +} Added: vmkit/trunk/mmtk/mmtk-j3/Lock.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Lock.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Lock.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Lock.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,28 @@ +//===----------- Lock.cpp - Implementation of the Lock class -------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" +#include "mvm/Threads/Locks.h" + +using namespace jnjvm; + +struct Lock { + JavaObject base; + mvm::SpinLock spin; +}; + + +extern "C" void Java_org_j3_mmtk_Lock_acquire__(Lock* l) { + l->spin.acquire(); +} +extern "C" void Java_org_j3_mmtk_Lock_check__I () { abort(); } + +extern "C" void Java_org_j3_mmtk_Lock_release__(Lock* l) { + l->spin.release(); +} Added: vmkit/trunk/mmtk/mmtk-j3/Makefile URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Makefile?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Makefile (added) +++ vmkit/trunk/mmtk/mmtk-j3/Makefile Thu Jul 16 06:26:34 2009 @@ -0,0 +1,18 @@ +##===- mmtk/magic/Makefile ---------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = MMTKRuntime +LOADABLE_MODULE = 1 +USEDLIBS = + +CXX.Flags += -I$(PROJ_OBJ_DIR)/../../lib/JnJVM/VMCore + +include $(LEVEL)/Makefile.common + Added: vmkit/trunk/mmtk/mmtk-j3/Memory.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Memory.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Memory.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Memory.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,76 @@ +//===------------ Memory.cpp - Implementation of the Memory class --------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + + +#include "JavaObject.h" + +using namespace jnjvm; +extern "C" uintptr_t Java_org_j3_mmtk_Memory_getHeapStartConstant__ () { + return (uintptr_t)0x30000000; +} + +extern "C" uintptr_t Java_org_j3_mmtk_Memory_getHeapEndConstant__ () { + return (uintptr_t)0x80000000; +} + +extern "C" uintptr_t Java_org_j3_mmtk_Memory_getAvailableStartConstant__ () { + return (uintptr_t)0x30000000; +} + +extern "C" uintptr_t Java_org_j3_mmtk_Memory_getAvailableEndConstant__ () { + return (uintptr_t)0x80000000; +} + +extern "C" sint32 +Java_org_j3_mmtk_Memory_dzmmap__Lorg_vmmagic_unboxed_Address_2I(JavaObject* M, + void* start, + sint32 size) { +#if defined (__MACH__) + uint32 flags = MAP_PRIVATE | MAP_ANON | MAP_FIXED; +#else + uint32 flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED; +#endif + void* baseAddr = mmap((void*)start, size, PROT_READ | PROT_WRITE, flags, + -1, 0); + if (baseAddr == MAP_FAILED) { + perror("mmap"); + abort(); + } + + return 0; +} + +extern "C" void +Java_org_j3_mmtk_Memory_mprotect__Lorg_vmmagic_unboxed_Address_2I () { + abort(); +} + +extern "C" void +Java_org_j3_mmtk_Memory_munprotect__Lorg_vmmagic_unboxed_Address_2I () { + abort(); +} + +extern "C" void +Java_org_j3_mmtk_Memory_zero__Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_Extent_2(JavaObject* M, + void* addr, + uintptr_t len) { + memset(addr, 0, len); +} + +extern "C" void +Java_org_j3_mmtk_Memory_zeroPages__Lorg_vmmagic_unboxed_Address_2I () { + abort(); +} + +extern "C" void +Java_org_j3_mmtk_Memory_dumpMemory__Lorg_vmmagic_unboxed_Address_2II () { + abort(); +} Added: vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,51 @@ +//===---- ObjectModel.cpp - Implementation of the ObjectModel class ------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" intptr_t Java_org_j3_mmtk_ObjectModel_getArrayBaseOffset__ () { + return sizeof(JavaObject) + sizeof(ssize_t); +} + +extern "C" intptr_t Java_org_j3_mmtk_ObjectModel_GC_1HEADER_1OFFSET__ () { + return sizeof(void*); +} + +extern "C" uintptr_t Java_org_j3_mmtk_ObjectModel_readAvailableBitsWord__Lorg_vmmagic_unboxed_ObjectReference_2 (JavaObject* OM, JavaObject* obj) { + return ((uintptr_t*)obj)[1]; +} + +extern "C" void Java_org_j3_mmtk_ObjectModel_writeAvailableBitsWord__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Word_2 (JavaObject* OM, JavaObject* obj, uintptr_t val) { + ((uintptr_t*)obj)[1] = val; +} + +extern "C" void Java_org_j3_mmtk_ObjectModel_copy__Lorg_vmmagic_unboxed_ObjectReference_2I () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_copyTo__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getReferenceWhenCopiedTo__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getObjectEndAddress__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getSizeWhenCopied__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getAlignWhenCopied__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getAlignOffsetWhenCopied__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getCurrentSize__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getNextObject__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getObjectFromStartAddress__Lorg_vmmagic_unboxed_Address_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getTypeDescriptor__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_getArrayLength__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_isArray__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_isPrimitiveArray__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_attemptAvailableBits__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Word_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_prepareAvailableBits__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_writeAvailableByte__Lorg_vmmagic_unboxed_ObjectReference_2B () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_readAvailableByte__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_objectStartRef__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_refToAddress__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_isAcyclic__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_ObjectModel_dumpObject__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } Added: vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,20 @@ +//===-------- ReferenceProcessor.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 "JavaObject.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_ReferenceProcessor_scan__Lorg_mmtk_plan_TraceLocal_2Z () { +} + +extern "C" void Java_org_j3_mmtk_ReferenceProcessor_forward__Lorg_mmtk_plan_TraceLocal_2Z () { abort(); } +extern "C" void Java_org_j3_mmtk_ReferenceProcessor_clear__ () { abort(); } +extern "C" void Java_org_j3_mmtk_ReferenceProcessor_countWaitingReferences__ () { abort(); } Added: vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,29 @@ +//===-------- Scanning.cpp - Implementation of the Scanning class --------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_Scanning_computeThreadRoots__Lorg_mmtk_plan_TraceLocal_2 () { +} + +extern "C" void Java_org_j3_mmtk_Scanning_computeGlobalRoots__Lorg_mmtk_plan_TraceLocal_2 () { +} + +extern "C" void Java_org_j3_mmtk_Scanning_computeStaticRoots__Lorg_mmtk_plan_TraceLocal_2 () { +} + +extern "C" void Java_org_j3_mmtk_Scanning_resetThreadCounter__ () { +} + +extern "C" void Java_org_j3_mmtk_Scanning_scanObject__Lorg_mmtk_plan_TransitiveClosure_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_Scanning_specializedScanObject__ILorg_mmtk_plan_TransitiveClosure_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_Scanning_precopyChildren__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_Scanning_preCopyGCInstances__Lorg_mmtk_plan_TraceLocal_2 () { abort(); } Added: vmkit/trunk/mmtk/mmtk-j3/Selected.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Selected.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Selected.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Selected.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,42 @@ +//===-------- 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 "JavaArray.h" +#include "JavaClass.h" +#include "JavaObject.h" +#include "JavaThread.h" + +using namespace jnjvm; + +#if 1 + +extern "C" JavaObject* org_j3_config_Selected_4Mutator_static; +extern "C" JavaObject* org_j3_config_Selected_4Collector_static; + + +extern "C" JavaObject* Java_org_j3_config_Selected_00024Collector_get__() { + JavaObject* obj = org_j3_config_Selected_4Collector_static; + return obj; +} + +extern "C" JavaObject* Java_org_j3_config_Selected_00024Mutator_get__() { + JavaObject* obj = org_j3_config_Selected_4Mutator_static; + return obj; +} + + +#else +extern "C" JavaObject* Java_org_j3_config_Selected_00024Collector_get__() { + return 0; +} + +extern "C" JavaObject* Java_org_j3_config_Selected_00024Mutator_get__() { + return 0; +} +#endif Added: vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,25 @@ +//===----- Statistics.cpp - Implementation of the Statistics class -------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_Statistics_perfCtrInit__I (JavaObject* S) { + // Implement me +} + +extern "C" int64_t Java_org_j3_mmtk_Statistics_cycles__ () { + return 0; +} + +extern "C" void Java_org_j3_mmtk_Statistics_getCollectionCount__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Statistics_nanoTime__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Statistics_perfCtrReadCycles__ () { abort(); } +extern "C" void Java_org_j3_mmtk_Statistics_perfCtrReadMetric__ () { abort(); } Added: vmkit/trunk/mmtk/mmtk-j3/Strings.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Strings.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/Strings.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/Strings.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,50 @@ +//===--------- Strings.cpp - Implementation of the Strings class ---------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaArray.h" +#include "JavaObject.h" +#include "JavaString.h" +#include "JavaThread.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_Strings_write___3CI(JavaObject* str, + ArrayUInt16* msg, + sint32 len) { + for (sint32 i = 0; i < len; ++i) + fprintf(stderr, "%c", msg->elements[i]); +} + +extern "C" void Java_org_j3_mmtk_Strings_writeThreadId___3CI(JavaObject*str, + ArrayUInt16* msg, + sint32 len) { + + fprintf(stderr, "[%p] ", (void*)JavaThread::get()); + + for (sint32 i = 0; i < len; ++i) + fprintf(stderr, "%c", msg->elements[i]); +} + + +extern "C" sint32 +Java_org_j3_mmtk_Strings_copyStringToChars__Ljava_lang_String_2_3CII( + JavaObject* obj, JavaString* str, ArrayUInt16* dst, uint32 dstBegin, + uint32 dstEnd) { + + sint32 len = str->count; + sint32 n = (dstBegin + len <= dstEnd) ? len : (dstEnd - dstBegin); + + for (sint32 i = 0; i < n; i++) { + dst->elements[dstBegin + i] = str->value->elements[str->offset + i]; + } + + return n; + +} + Added: vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,17 @@ +//===-------- SynchronizedCounter.cpp -------------------------------------===// +//===-------- Implementation of the SynchronizedCounter class ------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_SynchronizedCounter_reset__ () { abort(); } +extern "C" void Java_org_j3_mmtk_SynchronizedCounter_increment__ () { abort(); } + Added: vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,29 @@ +//===-- TraceInterface.cpp - Implementation of the TraceInterface class --===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_mmtk_TraceInterface_gcEnabled__ () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_adjustSlotOffset__ZLorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_skipOwnFramesAndDump__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_updateDeathTime__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_setDeathTime__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Word_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_setLink__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_updateTime__Lorg_vmmagic_unboxed_Word_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_getOID__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_getDeathTime__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_getLink__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_getBootImageLink__ () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_getOID__ () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_setOID__Lorg_vmmagic_unboxed_Word_2 () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_getHeaderSize__ () { abort(); } +extern "C" void Java_org_j3_mmtk_TraceInterface_getHeaderEndOffset__ () { abort(); } + Added: vmkit/trunk/mmtk/mmtk-j3/VM.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/VM.cpp?rev=75904&view=auto ============================================================================== --- vmkit/trunk/mmtk/mmtk-j3/VM.cpp (added) +++ vmkit/trunk/mmtk/mmtk-j3/VM.cpp Thu Jul 16 06:26:34 2009 @@ -0,0 +1,42 @@ +//===-------------- VM.cpp - Implementation of the VM class --------------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaObject.h" +#include "JavaThread.h" + +using namespace jnjvm; + +extern "C" void Java_org_j3_runtime_VM_sysWrite__Lorg_vmmagic_unboxed_Extent_2 () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysWrite__Lorg_vmmagic_unboxed_Address_2 () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysWrite__F () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysWrite__I () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysWrite__Ljava_lang_String_2 () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysWriteln__ () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysWriteln__Ljava_lang_String_2 () { abort(); } +extern "C" void Java_org_j3_runtime_VM__1assert__ZLjava_lang_String_2 () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysExit__I () { abort(); } +extern "C" void Java_org_j3_runtime_VM_sysFail__Ljava_lang_String_2 () { abort(); } + +extern "C" void Java_org_j3_runtime_VM__1assert__Z (bool cond) { + + assert(cond); +} + +extern "C" bool Java_org_j3_runtime_VM_buildFor64Addr__ () { + return false; +} + +extern "C" bool Java_org_j3_runtime_VM_buildForIA32__ () { + return true; +} + +extern "C" bool Java_org_j3_runtime_VM_verifyAssertions__ () { + return true; +} + From nicolas.geoffray at lip6.fr Thu Jul 16 04:29:37 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 16 Jul 2009 11:29:37 -0000 Subject: [vmkit-commits] [vmkit] r75905 - in /vmkit/trunk: LICENSE.TXT mmtk/LICENSE.html Message-ID: <200907161129.n6GBTcQt016920@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 16 06:29:36 2009 New Revision: 75905 URL: http://llvm.org/viewvc/llvm-project?rev=75905&view=rev Log: Add MMTK license. Added: vmkit/trunk/mmtk/LICENSE.html Modified: vmkit/trunk/LICENSE.TXT Modified: vmkit/trunk/LICENSE.TXT URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/LICENSE.TXT?rev=75905&r1=75904&r2=75905&view=diff ============================================================================== --- vmkit/trunk/LICENSE.TXT (original) +++ vmkit/trunk/LICENSE.TXT Thu Jul 16 06:29:36 2009 @@ -63,4 +63,4 @@ ------- --------- Mono libraries vmkit/lib/N3/Mono PNetlib libraries vmkit/lib/N3/PNet - +MMTk vmkit/mmtk/ Added: vmkit/trunk/mmtk/LICENSE.html URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/LICENSE.html?rev=75905&view=auto ============================================================================== --- vmkit/trunk/mmtk/LICENSE.html (added) +++ vmkit/trunk/mmtk/LICENSE.html Thu Jul 16 06:29:36 2009 @@ -0,0 +1,285 @@ + + + + + + +License Information + + + + + + +

        General Information

        + +

        Jikes RVM is free, open source software, distributed and freely +redistributable under the Eclipse Public License (EPL). The EPL has +been certified by the Open Source Initiative as an open source +license. The EPL meets the Debian Free Software Guidelines.

        + +

        Note: some code in the libraryInterface tree is distributed under +other open source licenses. See the various LICENSE files in that +tree for details.

        + +

        Note: some code in the external tree is distributed under +other open source licenses. See the various LICENSE files in that +tree for details.

        + +

        Note: rvm/src-generated/opt-burs/jburg contains a tool, jburg, +which was derived from iburg and is not distributed under the EPL. +See rvm/src-generated/opt-burs/jburg/LICENSE for details.

        + +

        The legal text of the Eclipse Public License is appended below for +reference

        + + + +

        Eclipse Public License - v 1.0

        + +

        THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE +PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR +DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS +AGREEMENT.

        + +

        1. DEFINITIONS

        + +

        "Contribution" means:

        + +

        a) in the case of the initial Contributor, the initial +code and documentation distributed under this Agreement, and

        +

        b) in the case of each subsequent Contributor:

        +

        i) changes to the Program, and

        +

        ii) additions to the Program;

        +

        where such changes and/or additions to the Program +originate from and are distributed by that particular Contributor. A +Contribution 'originates' from a Contributor if it was added to the +Program by such Contributor itself or anyone acting on such +Contributor's behalf. Contributions do not include additions to the +Program which: (i) are separate modules of software distributed in +conjunction with the Program under their own license agreement, and (ii) +are not derivative works of the Program.

        + +

        "Contributor" means any person or entity that distributes +the Program.

        + +

        "Licensed Patents" mean patent claims licensable by a +Contributor which are necessarily infringed by the use or sale of its +Contribution alone or when combined with the Program.

        + +

        "Program" means the Contributions distributed in accordance +with this Agreement.

        + +

        "Recipient" means anyone who receives the Program under +this Agreement, including all Contributors.

        + +

        2. GRANT OF RIGHTS

        + +

        a) Subject to the terms of this Agreement, each +Contributor hereby grants Recipient a non-exclusive, worldwide, +royalty-free copyright license to reproduce, prepare derivative works +of, publicly display, publicly perform, distribute and sublicense the +Contribution of such Contributor, if any, and such derivative works, in +source code and object code form.

        + +

        b) Subject to the terms of this Agreement, each +Contributor hereby grants Recipient a non-exclusive, worldwide, +royalty-free patent license under Licensed Patents to make, use, sell, +offer to sell, import and otherwise transfer the Contribution of such +Contributor, if any, in source code and object code form. This patent +license shall apply to the combination of the Contribution and the +Program if, at the time the Contribution is added by the Contributor, +such addition of the Contribution causes such combination to be covered +by the Licensed Patents. The patent license shall not apply to any other +combinations which include the Contribution. No hardware per se is +licensed hereunder.

        + +

        c) Recipient understands that although each Contributor +grants the licenses to its Contributions set forth herein, no assurances +are provided by any Contributor that the Program does not infringe the +patent or other intellectual property rights of any other entity. Each +Contributor disclaims any liability to Recipient for claims brought by +any other entity based on infringement of intellectual property rights +or otherwise. As a condition to exercising the rights and licenses +granted hereunder, each Recipient hereby assumes sole responsibility to +secure any other intellectual property rights needed, if any. For +example, if a third party patent license is required to allow Recipient +to distribute the Program, it is Recipient's responsibility to acquire +that license before distributing the Program.

        + +

        d) Each Contributor represents that to its knowledge it +has sufficient copyright rights in its Contribution, if any, to grant +the copyright license set forth in this Agreement.

        + +

        3. REQUIREMENTS

        + +

        A Contributor may choose to distribute the Program in object code +form under its own license agreement, provided that:

        + +

        a) it complies with the terms and conditions of this +Agreement; and

        + +

        b) its license agreement:

        + +

        i) effectively disclaims on behalf of all Contributors +all warranties and conditions, express and implied, including warranties +or conditions of title and non-infringement, and implied warranties or +conditions of merchantability and fitness for a particular purpose;

        + +

        ii) effectively excludes on behalf of all Contributors +all liability for damages, including direct, indirect, special, +incidental and consequential damages, such as lost profits;

        + +

        iii) states that any provisions which differ from this +Agreement are offered by that Contributor alone and not by any other +party; and

        + +

        iv) states that source code for the Program is available +from such Contributor, and informs licensees how to obtain it in a +reasonable manner on or through a medium customarily used for software +exchange.

        + +

        When the Program is made available in source code form:

        + +

        a) it must be made available under this Agreement; and

        + +

        b) a copy of this Agreement must be included with each +copy of the Program.

        + +

        Contributors may not remove or alter any copyright notices contained +within the Program.

        + +

        Each Contributor must identify itself as the originator of its +Contribution, if any, in a manner that reasonably allows subsequent +Recipients to identify the originator of the Contribution.

        + +

        4. COMMERCIAL DISTRIBUTION

        + +

        Commercial distributors of software may accept certain +responsibilities with respect to end users, business partners and the +like. While this license is intended to facilitate the commercial use of +the Program, the Contributor who includes the Program in a commercial +product offering should do so in a manner which does not create +potential liability for other Contributors. Therefore, if a Contributor +includes the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and +indemnify every other Contributor ("Indemnified Contributor") +against any losses, damages and costs (collectively "Losses") +arising from claims, lawsuits and other legal actions brought by a third +party against the Indemnified Contributor to the extent caused by the +acts or omissions of such Commercial Contributor in connection with its +distribution of the Program in a commercial product offering. The +obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In +order to qualify, an Indemnified Contributor must: a) promptly notify +the Commercial Contributor in writing of such claim, and b) allow the +Commercial Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement negotiations. The +Indemnified Contributor may participate in any such claim at its own +expense.

        + +

        For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those +performance claims and warranties, and if a court requires any other +Contributor to pay any damages as a result, the Commercial Contributor +must pay those damages.

        + +

        5. NO WARRANTY

        + +

        EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS +PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, +ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY +OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely +responsible for determining the appropriateness of using and +distributing the Program and assumes all risks associated with its +exercise of rights under this Agreement , including but not limited to +the risks and costs of program errors, compliance with applicable laws, +damage to or loss of data, programs or equipment, and unavailability or +interruption of operations.

        + +

        6. DISCLAIMER OF LIABILITY

        + +

        EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT +NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING +WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR +DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED +HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

        + +

        7. GENERAL

        + +

        If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further action +by the parties hereto, such provision shall be reformed to the minimum +extent necessary to make such provision valid and enforceable.

        + +

        If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other +software or hardware) infringes such Recipient's patent(s), then such +Recipient's rights granted under Section 2(b) shall terminate as of the +date such litigation is filed.

        + +

        All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of time +after becoming aware of such noncompliance. If all Recipient's rights +under this Agreement terminate, Recipient agrees to cease use and +distribution of the Program as soon as reasonably practicable. However, +Recipient's obligations under this Agreement and any licenses granted by +Recipient relating to the Program shall continue and survive.

        + +

        Everyone is permitted to copy and distribute copies of this +Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The +Agreement Steward reserves the right to publish new versions (including +revisions) of this Agreement from time to time. No one other than the +Agreement Steward has the right to modify this Agreement. The Eclipse +Foundation is the initial Agreement Steward. The Eclipse Foundation may +assign the responsibility to serve as the Agreement Steward to a +suitable separate entity. Each new version of the Agreement will be +given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the +Agreement under which it was received. In addition, after a new version +of the Agreement is published, Contributor may elect to distribute the +Program (including its Contributions) under the new version. Except as +expressly stated in Sections 2(a) and 2(b) above, Recipient receives no +rights or licenses to the intellectual property of any Contributor under +this Agreement, whether expressly, by implication, estoppel or +otherwise. All rights in the Program not expressly granted under this +Agreement are reserved.

        + +

        This Agreement is governed by the laws of the State of New York and +the intellectual property laws of the United States of America. No party +to this Agreement will bring a legal action under this Agreement more +than one year after the cause of action arose. Each party waives its +rights to a jury trial in any resulting litigation.

        + + + + \ No newline at end of file From nicolas.geoffray at lip6.fr Sun Jul 19 09:38:59 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Sun, 19 Jul 2009 16:38:59 -0000 Subject: [vmkit-commits] [vmkit] r76369 - in /vmkit/trunk: include/jnjvm/ include/mvm/Threads/ lib/JnJVM/Classpath/ lib/JnJVM/Compiler/ lib/JnJVM/LLVMRuntime/ lib/JnJVM/VMCore/ lib/Mvm/CommonThread/ Message-ID: <200907191639.n6JGd0FV007516@zion.cs.uiuc.edu> Author: geoffray Date: Sun Jul 19 11:38:58 2009 New Revision: 76369 URL: http://llvm.org/viewvc/llvm-project?rev=76369&view=rev Log: Handle references on object* in JNI, instead of references on object. This makes sure that the stack of threads running native methods can be precisely scanned. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/include/mvm/Threads/Thread.h vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Sun Jul 19 11:38:58 2009 @@ -421,6 +421,7 @@ virtual JavaObject* getFinalObject(llvm::Value* C) = 0; virtual llvm::Constant* getNativeClass(CommonClass* cl) = 0; virtual llvm::Constant* getJavaClass(CommonClass* cl) = 0; + virtual llvm::Constant* getJavaClassPtr(CommonClass* cl) = 0; virtual llvm::Constant* getStaticInstance(Class* cl) = 0; virtual llvm::Constant* getVirtualTable(JavaVirtualTable*) = 0; virtual llvm::Constant* getMethodInClass(JavaMethod* meth) = 0; @@ -492,6 +493,7 @@ virtual JavaObject* getFinalObject(llvm::Value* C); virtual llvm::Constant* getNativeClass(CommonClass* cl); virtual llvm::Constant* getJavaClass(CommonClass* cl); + virtual llvm::Constant* getJavaClassPtr(CommonClass* cl); virtual llvm::Constant* getStaticInstance(Class* cl); virtual llvm::Constant* getVirtualTable(JavaVirtualTable*); virtual llvm::Constant* getMethodInClass(JavaMethod* meth); @@ -546,6 +548,7 @@ virtual JavaObject* getFinalObject(llvm::Value* C); virtual llvm::Constant* getNativeClass(CommonClass* cl); virtual llvm::Constant* getJavaClass(CommonClass* cl); + virtual llvm::Constant* getJavaClassPtr(CommonClass* cl); virtual llvm::Constant* getStaticInstance(Class* cl); virtual llvm::Constant* getVirtualTable(JavaVirtualTable*); virtual llvm::Constant* getMethodInClass(JavaMethod* meth); Modified: vmkit/trunk/include/mvm/Threads/Thread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Threads/Thread.h (original) +++ vmkit/trunk/include/mvm/Threads/Thread.h Sun Jul 19 11:38:58 2009 @@ -218,6 +218,10 @@ return cpt; } + /// printBacktraceAfterSignal - Print the backtrace during a signal + /// handler. + /// + virtual void printBacktraceAfterSignal() {} }; Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Sun Jul 19 11:38:58 2009 @@ -76,7 +76,8 @@ #endif typedef int (*onLoad_t)(const void**, void*); -extern "C" void jnjvmJNIProceedPendingException(); +extern "C" void jnjvmJNIProceedPendingException(uint32** old); +extern "C" void* jnjvmGetSJLJBuffer(uint32* num, uint32** old); // Calls the JNI_OnLoad function of a dynamic library. void callOnLoad(void* res, JnjvmClassLoader* loader, Jnjvm* vm) { @@ -84,16 +85,15 @@ onLoad_t onLoad = (onLoad_t)loader->loadInLib("JNI_OnLoad", res); if (onLoad) { - JavaThread* th = JavaThread::get(); - mvm::Allocator& allocator = th->getJVM()->gcAllocator; - void** buf = (void**)allocator.allocateTemporaryMemory(sizeof(jmp_buf)); - th->sjlj_buffers.push_back((jmp_buf*)buf); - - th->startNative(1); + uint32 num = 0; + uint32* old = 0; + void* buf = jnjvmGetSJLJBuffer(&num, &old); + if (setjmp((jumpbuf_t)buf) == 0) { onLoad(&vm->javavmEnv, res); } - jnjvmJNIProceedPendingException(); + + jnjvmJNIProceedPendingException(&old); } } Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Sun Jul 19 11:38:58 2009 @@ -283,14 +283,21 @@ std::vector llvmArgs; uint32 size = signature->nbArguments; Typedef* const* arguments = signature->getArgumentsType(); - + + const llvm::Type* Ty = PointerType::getUnqual(JnjvmModule::JavaObjectType); + llvmArgs.push_back(mvm::MvmModule::ptrType); // JNIEnv - llvmArgs.push_back(JnjvmModule::JavaObjectType); // Class + llvmArgs.push_back(Ty); // Class for (uint32 i = 0; i < size; ++i) { Typedef* type = arguments[i]; LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(type); - llvmArgs.push_back(LAI.llvmType); + const llvm::Type* Ty = LAI.llvmType; + if (Ty == JnjvmModule::JavaObjectType) { + llvmArgs.push_back(LAI.llvmTypePtr); + } else { + llvmArgs.push_back(LAI.llvmType); + } } #if defined(ISOLATE_SHARING) @@ -299,7 +306,9 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); - nativeType = FunctionType::get(LAI.llvmType, llvmArgs, false); + const llvm::Type* RetType = LAI.llvmType == JnjvmModule::JavaObjectType ? + LAI.llvmTypePtr : LAI.llvmType; + nativeType = FunctionType::get(RetType, llvmArgs, false); mvm::MvmModule::unprotectIR(); } return nativeType; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Sun Jul 19 11:38:58 2009 @@ -206,7 +206,28 @@ return res; } else { return I->second; - } + } +} + +Constant* JavaAOTCompiler::getJavaClassPtr(CommonClass* cl) { +#ifdef ISOLATE + abort(); + return 0; +#else + // Make sure it's emitted. + getJavaClass(cl); + + Constant* Cl = getNativeClass(cl); + + Constant* GEP[2] = { JnjvmModule::constantZero, JnjvmModule::constantZero }; + + Constant* TCMArray = ConstantExpr::getGetElementPtr(Cl, GEP, 2); + + Constant* GEP2[2] = { JnjvmModule::constantZero, JnjvmModule::constantZero }; + + Constant* Ptr = ConstantExpr::getGetElementPtr(TCMArray, GEP2, 2); + return Ptr; +#endif } JavaObject* JavaAOTCompiler::getFinalObject(llvm::Value* obj) { Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Sun Jul 19 11:38:58 2009 @@ -278,17 +278,30 @@ currentBlock = createBasicBlock("start"); BasicBlock* executeBlock = createBasicBlock("execute"); endBlock = createBasicBlock("end block"); + + // Allocate currentLocalIndexNumber pointer + Value* temp = new AllocaInst(*llvmContext, Type::Int32Ty, "", + currentBlock); + new StoreInst(module->constantZero, temp, false, currentBlock); + + // Allocate oldCurrentLocalIndexNumber pointer + Value* oldCLIN = new AllocaInst(*llvmContext, + PointerType::getUnqual(Type::Int32Ty), "", + currentBlock); + + Value* Args2[2] = { temp, oldCLIN }; + + Value* buf = CallInst::Create(module->GetSJLJBufferFunction, + Args2, Args2 + 2, "", currentBlock); + Value* test = CallInst::Create(module->setjmpLLVM, buf, "", + currentBlock); - Value* buf = llvm::CallInst::Create(module->GetSJLJBufferFunction, - "", currentBlock); - Value* test = llvm::CallInst::Create(module->setjmpLLVM, buf, "", - currentBlock); test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, module->constantZero, ""); - llvm::BranchInst::Create(executeBlock, endBlock, test, currentBlock); + BranchInst::Create(executeBlock, endBlock, test, currentBlock); if (returnType != Type::VoidTy) { - endNode = llvm::PHINode::Create(returnType, "", endBlock); + endNode = PHINode::Create(returnType, "", endBlock); endNode->addIncoming(llvmContext->getNullValue(returnType), currentBlock); } @@ -317,21 +330,45 @@ if (stat) { #ifdef ISOLATE_SHARING Value* val = getClassCtp(); - Value* res = CallInst::Create(module->GetClassDelegateeFunction, - val, "", currentBlock); - nativeArgs.push_back(res); + Value* cl = CallInst::Create(module->GetClassDelegateePtrFunction, + val, "", currentBlock); #else - Value* cl = TheCompiler->getJavaClass(compilingClass); - nativeArgs.push_back(cl); + Value* cl = TheCompiler->getJavaClassPtr(compilingClass); #endif + nativeArgs.push_back(cl); index = 2; } else { index = 1; } for (Function::arg_iterator i = func->arg_begin(); index < nargs; ++i, ++index) { - - nativeArgs.push_back(i); + + if (i->getType() == module->JavaObjectType) { + BasicBlock* BB = createBasicBlock(""); + BasicBlock* NotZero = createBasicBlock(""); + const Type* Ty = PointerType::getUnqual(module->JavaObjectType); + PHINode* node = PHINode::Create(Ty, "", BB); + + test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, i, + module->JavaObjectNullConstant, ""); + + node->addIncoming(llvmContext->getNullValue(Ty), currentBlock); + BranchInst::Create(BB, NotZero, test, currentBlock); + + currentBlock = NotZero; + + Value* temp = new AllocaInst(*llvmContext, module->JavaObjectType, "", + currentBlock); + new StoreInst(i, temp, false, currentBlock); + node->addIncoming(temp, currentBlock); + BranchInst::Create(BB, currentBlock); + + currentBlock = BB; + + nativeArgs.push_back(node); + } else { + nativeArgs.push_back(i); + } } Value* nativeFunc = TheCompiler->getNativeFunction(compilingMethod, @@ -376,15 +413,32 @@ Value* result = llvm::CallInst::Create(nativeFunc, nativeArgs.begin(), nativeArgs.end(), "", currentBlock); - if (returnType != Type::VoidTy) + if (returnType == module->JavaObjectType) { + const Type* Ty = PointerType::getUnqual(module->JavaObjectType); + Constant* C = llvmContext->getNullValue(Ty); + Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, result, C, ""); + BasicBlock* loadBlock = createBasicBlock(""); + + endNode->addIncoming(module->JavaObjectNullConstant, currentBlock); + BranchInst::Create(endBlock, loadBlock, cmp, currentBlock); + + currentBlock = loadBlock; + result = new LoadInst(result, "", currentBlock); + + endNode->addIncoming(result, currentBlock); + + } else if (returnType != Type::VoidTy) { endNode->addIncoming(result, currentBlock); + } + BranchInst::Create(endBlock, currentBlock); + currentBlock = endBlock; if (isSynchro(compilingMethod->access)) endSynchronize(); - CallInst::Create(module->JniProceedPendingExceptionFunction, "", + CallInst::Create(module->JniProceedPendingExceptionFunction, oldCLIN, "", currentBlock); if (returnType != Type::VoidTy) Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Sun Jul 19 11:38:58 2009 @@ -73,6 +73,16 @@ return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } +Constant* JavaJITCompiler::getJavaClassPtr(CommonClass* cl) { + Jnjvm* vm = JavaThread::get()->getJVM(); + JavaObject* const* obj = cl->getClassDelegateePtr(vm); + assert(obj && "Delegatee not created"); + LLVMContext& Context = getLLVMModule()->getContext(); + Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64(obj)); + const Type* Ty = PointerType::getUnqual(JnjvmModule::JavaObjectType); + return ConstantExpr::getIntToPtr(CI, Ty); +} + JavaObject* JavaJITCompiler::getFinalObject(llvm::Value* obj) { if (ConstantExpr* CE = dyn_cast(obj)) { if (ConstantInt* C = dyn_cast(CE->getOperand(0))) { Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Sun Jul 19 11:38:58 2009 @@ -26,7 +26,7 @@ ;;; The Enveloppe type, which contains the first cache and all the info ;;; to lookup in the constant pool. -%Enveloppe = type { %CacheNode*, %UTF8*, %UTF8*, i8, %JavaClass*, %CacheNode } +%Enveloppe = type { %CacheNode*, %UTF8*, %UTF8*, i32, %JavaClass*, %CacheNode } ;;; The task class mirror. ;;; Field 1: The class state @@ -221,8 +221,8 @@ declare void @jnjvmThrowException(%JavaObject*) declare void @jnjvmThrowExceptionFromJIT() -declare void @jnjvmJNIProceedPendingException() -declare i8* @jnjvmGetSJLJBuffer() +declare void @jnjvmJNIProceedPendingException(i32**) +declare i8* @jnjvmGetSJLJBuffer(i32*, i32**) declare %JavaObject* @gcmalloc(i32, %VT*) Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Sun Jul 19 11:38:58 2009 @@ -989,6 +989,10 @@ return delegatee[JavaThread::get()->getJVM()->IsolateID]; } +JavaObject** CommonClass::getDelegateePtr() { + return &(delegatee[JavaThread::get()->getJVM()->IsolateID]); +} + JavaObject* CommonClass::setDelegatee(JavaObject* val) { JavaObject** obj = &(delegatee[JavaThread::get()->getJVM()->IsolateID]); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h Sun Jul 19 11:38:58 2009 @@ -289,6 +289,11 @@ /// JavaObject* getClassDelegatee(Jnjvm* vm, JavaObject* pd = 0); + /// getClassDelegateePtr - Return a pointer on the java/lang/Class + /// representation of this class. Used for JNI. + /// + JavaObject* const* getClassDelegateePtr(Jnjvm* vm, JavaObject* pd = 0); + /// CommonClass - Create a class with th given name. /// CommonClass(JnjvmClassLoader* loader, const UTF8* name); @@ -325,10 +330,18 @@ JavaObject* getDelegatee() const { return delegatee[0]; } + + /// getDelegatee - Get a pointer on the java/lang/Class object + /// representing this class. + /// + JavaObject* const* getDelegateePtr() const { + return delegatee; + } #else #if defined(ISOLATE) JavaObject* getDelegatee(); + JavaObject** getDelegateePtr(); #endif #endif @@ -1060,37 +1073,37 @@ //===----------------------------------------------------------------------===// /// This class of methods takes a variable argument list. - uint32 invokeIntSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap) + uint32 invokeIntSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap, bool jni = false) __attribute__ ((noinline)); - float invokeFloatSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap) + float invokeFloatSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap, bool jni = false) __attribute__ ((noinline)); double invokeDoubleSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, - va_list ap) __attribute__ ((noinline)); - sint64 invokeLongSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap) + va_list ap, bool jni = false) __attribute__ ((noinline)); + sint64 invokeLongSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap, bool jni = false) __attribute__ ((noinline)); JavaObject* invokeJavaObjectSpecialAP(Jnjvm* vm, UserClass*, JavaObject* obj, - va_list ap) __attribute__ ((noinline)); + va_list ap, bool jni = false) __attribute__ ((noinline)); - uint32 invokeIntVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap) + uint32 invokeIntVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap, bool jni = false) __attribute__ ((noinline)); - float invokeFloatVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap) + float invokeFloatVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap, bool jni = false) __attribute__ ((noinline)); double invokeDoubleVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, - va_list ap) __attribute__ ((noinline)); - sint64 invokeLongVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap) + va_list ap, bool jni = false) __attribute__ ((noinline)); + sint64 invokeLongVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, va_list ap, bool jni = false) __attribute__ ((noinline)); JavaObject* invokeJavaObjectVirtualAP(Jnjvm* vm, UserClass*, JavaObject* obj, - va_list ap) __attribute__ ((noinline)); + va_list ap, bool jni = false) __attribute__ ((noinline)); - uint32 invokeIntStaticAP(Jnjvm* vm, UserClass*, va_list ap) + uint32 invokeIntStaticAP(Jnjvm* vm, UserClass*, va_list ap, bool jni = false) __attribute__ ((noinline)); - float invokeFloatStaticAP(Jnjvm* vm, UserClass*, va_list ap) + float invokeFloatStaticAP(Jnjvm* vm, UserClass*, va_list ap, bool jni = false) __attribute__ ((noinline)); - double invokeDoubleStaticAP(Jnjvm* vm, UserClass*, va_list ap) + double invokeDoubleStaticAP(Jnjvm* vm, UserClass*, va_list ap, bool jni = false) __attribute__ ((noinline)); - sint64 invokeLongStaticAP(Jnjvm* vm, UserClass*, va_list ap) + sint64 invokeLongStaticAP(Jnjvm* vm, UserClass*, va_list ap, bool jni = false) __attribute__ ((noinline)); - JavaObject* invokeJavaObjectStaticAP(Jnjvm* vm, UserClass*, va_list ap) + JavaObject* invokeJavaObjectStaticAP(Jnjvm* vm, UserClass*, va_list ap, bool jni = false) __attribute__ ((noinline)); /// This class of methods takes a buffer which contain the arguments of the Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Sun Jul 19 11:38:58 2009 @@ -21,7 +21,7 @@ using namespace jnjvm; -#define readArgs(buf, signature, ap) \ +#define readArgs(buf, signature, ap, jni) \ Typedef* const* arguments = signature->getArgumentsType(); \ for (uint32 i = 0; i < signature->nbArguments; ++i) { \ const Typedef* type = arguments[i];\ @@ -48,7 +48,16 @@ abort();\ }\ } else{\ - ((JavaObject**)buf)[0] = va_arg(ap, JavaObject*);\ + if (jni) { \ + JavaObject** obj = va_arg(ap, JavaObject**);\ + if (obj) {\ + ((JavaObject**)buf)[0] = *obj;\ + } else {\ + ((JavaObject**)buf)[0] = 0;\ + }\ + } else { \ + ((JavaObject**)buf)[0] = va_arg(ap, JavaObject*);\ + } \ }\ buf += 8; \ }\ @@ -59,12 +68,12 @@ #if 1//defined(__PPC__) && !defined(__MACH__) #define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \ \ -TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) { \ +TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap, bool jni) { \ verifyNull(obj); \ Signdef* sign = getSignature(); \ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \ void* _buf = (void*)buf; \ - readArgs(buf, sign, ap); \ + readArgs(buf, sign, ap, jni); \ void* func = (((void***)obj)[0])[offset];\ JavaThread* th = JavaThread::get(); \ th->startJava(); \ @@ -78,12 +87,12 @@ return res; \ }\ \ -TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) {\ +TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap, bool jni) {\ verifyNull(obj);\ Signdef* sign = getSignature(); \ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \ void* _buf = (void*)buf; \ - readArgs(buf, sign, ap); \ + readArgs(buf, sign, ap, jni); \ void* func = this->compiledPtr();\ JavaThread* th = JavaThread::get(); \ th->startJava(); \ @@ -97,7 +106,7 @@ return res; \ }\ \ -TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(Jnjvm* vm, UserClass* cl, va_list ap) {\ +TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(Jnjvm* vm, UserClass* cl, va_list ap, bool jni) {\ if (!cl->isReady()) { \ cl->resolveClass(); \ cl->initialiseClass(vm); \ @@ -106,7 +115,7 @@ Signdef* sign = getSignature(); \ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \ void* _buf = (void*)buf; \ - readArgs(buf, sign, ap); \ + readArgs(buf, sign, ap, jni); \ void* func = this->compiledPtr();\ JavaThread* th = JavaThread::get(); \ th->startJava(); \ @@ -335,12 +344,12 @@ #if 1//defined(__PPC__) && !defined(__MACH__) #define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \ \ -TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) { \ +TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap, bool jni) { \ verifyNull(obj); \ Signdef* sign = getSignature(); \ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \ void* _buf = (void*)buf; \ - readArgs(buf, sign, ap); \ + readArgs(buf, sign, ap, jni); \ void* func = (((void***)obj)[0])[offset];\ JavaThread* th = JavaThread::get(); \ th->startJava(); \ @@ -353,12 +362,12 @@ return res; \ }\ \ -TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) {\ +TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap, bool jni) {\ verifyNull(obj);\ Signdef* sign = getSignature(); \ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \ void* _buf = (void*)buf; \ - readArgs(buf, sign, ap); \ + readArgs(buf, sign, ap, jni); \ void* func = this->compiledPtr();\ JavaThread* th = JavaThread::get(); \ th->startJava(); \ @@ -371,7 +380,7 @@ return res; \ }\ \ -TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(Jnjvm* vm, UserClass* cl, va_list ap) {\ +TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(Jnjvm* vm, UserClass* cl, va_list ap, bool jni) {\ if (!cl->isReady()) { \ cl->resolveClass(); \ cl->initialiseClass(vm); \ @@ -380,7 +389,7 @@ Signdef* sign = getSignature(); \ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \ void* _buf = (void*)buf; \ - readArgs(buf, sign, ap); \ + readArgs(buf, sign, ap, jni); \ void* func = this->compiledPtr();\ JavaThread* th = JavaThread::get(); \ th->startJava(); \ Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Sun Jul 19 11:38:58 2009 @@ -369,19 +369,20 @@ } // Does not call Java code. -extern "C" void jnjvmJNIProceedPendingException() { +extern "C" void jnjvmJNIProceedPendingException(uint32** oldLRN) { JavaThread* th = JavaThread::get(); jmp_buf* buf = th->sjlj_buffers.back(); // Remove the buffer. th->sjlj_buffers.pop_back(); - - // We're going back to Java, remove the native address. - th->addresses.pop_back(); - mvm::Allocator& allocator = th->getJVM()->gcAllocator; allocator.freeTemporaryMemory(buf); + // We're going back to Java + th->endJNI(); + + th->currentAddedReferences = *oldLRN; + #ifdef DWARF_EXCEPTIONS // If there's an exception, throw it now. if (JavaThread::get()->pendingException) { @@ -391,15 +392,18 @@ } // Never throws. -extern "C" void* jnjvmGetSJLJBuffer() { +extern "C" void* jnjvmGetSJLJBuffer(uint32* localReferencesNumber, + uint32** oldLocalReferencesNumber) { JavaThread* th = JavaThread::get(); mvm::Allocator& allocator = th->getJVM()->gcAllocator; void** buf = (void**)allocator.allocateTemporaryMemory(sizeof(jmp_buf)); th->sjlj_buffers.push_back((jmp_buf*)buf); + *oldLocalReferencesNumber = th->currentAddedReferences; + th->currentAddedReferences = localReferencesNumber; - // Start native because the next instruction after setjmp is a call to a - // native function. - th->startNative(2); + // Start JNI because the next instruction after setjmp is a call to a + // JNI function. + th->startJNI(2); // Finally, return the buffer that the Java code will use to do the setjmp. return (void*)buf; Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Sun Jul 19 11:38:58 2009 @@ -31,6 +31,9 @@ state = StateRunning; pendingException = 0; jniEnv = isolate->jniEnv; + localJNIRefs = new JNILocalReferences(); + currentAddedReferences = 0; + #ifdef SERVICE eipIndex = 0; replacedEIPs = new void*[100]; @@ -79,7 +82,19 @@ cur = (void**)cur[0]; // When entering, the number of addresses should be odd. - // Enable this when finalization gets proper support. + assert((addresses.size() % 2) && "Wrong stack"); + + addresses.push_back(cur); +} + +void JavaThread::startJNI(int level) { + // Caller of this function. + void** cur = (void**)FRAME_PTR(); + + while (level--) + cur = (void**)cur[0]; + + // When entering, the number of addresses should be odd. assert((addresses.size() % 2) && "Wrong stack"); addresses.push_back(cur); @@ -275,3 +290,39 @@ } } + +void JavaThread::printBacktraceAfterSignal() { + printBacktrace(); +} + +JavaObject** JNILocalReferences::addJNIReference(JavaThread* th, + JavaObject* obj) { + if (length == MAXIMUM_REFERENCES) { + JNILocalReferences* next = new JNILocalReferences(); + th->localJNIRefs = next; + next->prev = this; + return next->addJNIReference(th, obj); + } else { + localReferences[length] = obj; + return &localReferences[length++]; + } +} + +void JNILocalReferences::removeJNIReferences(JavaThread* th, uint32_t num) { + + if (th->localJNIRefs != this) { + delete th->localJNIRefs; + th->localJNIRefs = this; + } + + if (num > length) { + fprintf(stderr, "num = %d et length = %d\n", num, length); + if (!prev) { + JavaThread::get()->printBacktrace(); + } + assert(prev && "No prev and deleting too much local references"); + prev->removeJNIReferences(th, num - length); + } else { + length -= num; + } +} Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Sun Jul 19 11:38:58 2009 @@ -19,6 +19,7 @@ #include "mvm/Threads/Thread.h" #include "JavaObject.h" +#include "JNIReferences.h" namespace jnjvm { @@ -118,6 +119,23 @@ /// std::vector addresses; + /// currentAddedReferences - Current number of added local references. + /// + uint32_t* currentAddedReferences; + + /// localJNIRefs - List of local JNI references. + /// + JNILocalReferences* localJNIRefs; + + + JavaObject** pushJNIRef(JavaObject* obj) { + if (!obj) return 0; + + ++(*currentAddedReferences); + return localJNIRefs->addJNIReference(this, obj); + + } + /// tracer - Traces GC-objects pointed by this thread object. /// virtual void tracer(); @@ -201,6 +219,10 @@ /// startNative - Record that we are entering native code. /// void startNative(int level) __attribute__ ((noinline)); + + /// startNative - Record that we are entering native code. + /// + void startJNI(int level) __attribute__ ((noinline)); /// startJava - Record that we are entering Java code. /// @@ -213,6 +235,13 @@ addresses.pop_back(); } + void endJNI() { + assert(!(addresses.size() % 2) && "Wrong stack"); + + localJNIRefs->removeJNIReferences(this, *currentAddedReferences); + addresses.pop_back(); + } + /// endJava - Record that we are leaving Java code. /// void endJava() { @@ -244,6 +273,12 @@ /// void printBacktrace() __attribute__ ((noinline)); + /// printBacktraceAfterSignal - Prints the backtrace of this thread while + /// in a signal handler. + /// + virtual void printBacktraceAfterSignal() __attribute__ ((noinline)); + + /// printJavaBacktrace - Prints the backtrace of this thread. Only prints /// the Java methods on the stack. /// Modified: vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp Sun Jul 19 11:38:58 2009 @@ -27,9 +27,9 @@ } static UserClass* getClassFromStaticMethod(Jnjvm* vm, JavaMethod* meth, - jclass clazz) { + JavaObject* clazz) { #ifdef ISOLATE_SHARING - return (UserClass*)NativeUtil::resolvedImplClass(vm, vm, clazz, true); + return (UserClass*)UserCommonClass::resolvedImplClass(vm, clazz, false); #else return meth->classDef; #endif @@ -73,8 +73,9 @@ UserCommonClass* cl = loader->loadClassFromAsciiz(asciiz, true, true); if (cl && cl->asClass()) cl->asClass()->initialiseClass(vm); - return (jclass)(cl->getClassDelegatee(vm)); - + jclass res = (jclass)cl->getClassDelegateePtr(vm); + return res; + END_JNI_EXCEPTION return 0; } @@ -83,10 +84,12 @@ jmethodID FromReflectedMethod(JNIEnv *env, jobject method) { BEGIN_JNI_EXCEPTION - + + // Local object references. + JavaObject* meth = *(JavaObject**)method; + Jnjvm* vm = myVM(env); Classpath* upcalls = vm->upcalls; - JavaObject* meth = (JavaObject*)method; UserCommonClass* cl = meth->getClass(); if (cl == upcalls->newConstructor) { return (jmethodID)((JavaObjectMethod*)meth)->getInternalMethod(); @@ -106,15 +109,19 @@ } -jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup) { +jboolean IsAssignableFrom(JNIEnv *env, jclass _sub, jclass _sup) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* sub = *(JavaObject**)_sub; + JavaObject* sup = *(JavaObject**)_sup; Jnjvm* vm = JavaThread::get()->getJVM(); UserCommonClass* cl2 = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)sup, false); + UserCommonClass::resolvedImplClass(vm, sup, false); UserCommonClass* cl1 = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)sub, false); + UserCommonClass::resolvedImplClass(vm, sub, false); return cl1->isAssignableFrom(cl2); @@ -131,15 +138,19 @@ } -jint ThrowNew(JNIEnv* env, jclass Cl, const char *msg) { +jint ThrowNew(JNIEnv* env, jclass _Cl, const char *msg) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* Cl = *(JavaObject**)_Cl; + + Jnjvm* vm = JavaThread::get()->getJVM(); - Jnjvm* vm = myVM(env); verifyNull(Cl); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, true); - if (!cl->asClass()) return 0; + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, true); + if (!cl->isClass()) return 0; + UserClass* realCl = cl->asClass(); JavaObject* res = realCl->doNew(vm); JavaMethod* init = realCl->lookupMethod(vm->bootstrapLoader->initName, @@ -197,7 +208,11 @@ jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2) { - return ref1 == ref2; + + JavaObject* Ref1 = *(JavaObject**)ref1; + JavaObject* Ref2 = *(JavaObject**)ref2; + + return Ref1 == Ref2; } @@ -215,35 +230,53 @@ } -jobject AllocObject(JNIEnv *env, jclass clazz) { +jobject AllocObject(JNIEnv *env, jclass _clazz) { BEGIN_JNI_EXCEPTION - - Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - if (cl->isArray()) return 0; + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaObject* res = 0; - return (jobject)((UserClass*)cl)->doNew(JavaThread::get()->getJVM()); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + if (!cl->isClass()) return 0; + + // Store local reference + res = cl->asClass()->doNew(vm); + + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; } -jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { +jobject NewObject(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION - + + + // Local object references + JavaObject* clazz = *(JavaObject**)_clazz; + JavaObject* res = 0; + + JavaMethod* meth = (JavaMethod*)methodID; + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + if (!cl->isClass()) return 0; + + // Store local reference + res = cl->asClass()->doNew(vm); + va_list ap; va_start(ap, methodID); - JavaMethod* meth = (JavaMethod*)methodID; - Jnjvm* vm = JavaThread::get()->getJVM(); - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - JavaObject* res = cl->doNew(vm); - meth->invokeIntSpecialAP(vm, cl, res, ap); + meth->invokeIntSpecialAP(vm, cl->asClass(), res, ap, true); va_end(ap); - return (jobject)res; + + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -257,32 +290,91 @@ return 0; } +#define BufToBuf(_args, _buf, signature) \ + Typedef* const* arguments = signature->getArgumentsType(); \ + uintptr_t __buf = (uintptr_t)_buf; \ + uintptr_t __args = (uintptr_t)_args;\ + for (uint32 i = 0; i < signature->nbArguments; ++i) { \ + const Typedef* type = arguments[i];\ + if (type->isPrimitive()) {\ + const PrimitiveTypedef* prim = (PrimitiveTypedef*)type;\ + if (prim->isLong()) {\ + ((sint64*)__buf)[0] = ((sint64*)__args)[0];\ + } else if (prim->isInt()){ \ + ((sint32*)__buf)[0] = ((sint32*)__args)[0];\ + } else if (prim->isChar()) { \ + ((uint32*)__buf)[0] = ((uint32*)__args)[0];\ + } else if (prim->isShort()) { \ + ((uint32*)__buf)[0] = ((uint32*)__args)[0];\ + } else if (prim->isByte()) { \ + ((uint32*)__buf)[0] = ((uint32*)__args)[0];\ + } else if (prim->isBool()) { \ + ((uint32*)__buf)[0] = ((uint32*)__args)[0];\ + } else if (prim->isFloat()) {\ + ((float*)__buf)[0] = ((float*)__args)[0];\ + } else if (prim->isDouble()) {\ + ((double*)__buf)[0] = ((double*)__args)[0];\ + } else {\ + fprintf(stderr, "Can't happen");\ + abort();\ + }\ + } else{\ + JavaObject** obj = ((JavaObject***)__args)[0];\ + if (obj) {\ + ((JavaObject**)__buf)[0] = *obj;\ + } else {\ + ((JavaObject**)__buf)[0] = 0;\ + }\ + }\ + __buf += 8; \ + __args += 8; \ + }\ -jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, + +jobject NewObjectA(JNIEnv* env, jclass _clazz, jmethodID methodID, const jvalue *args) { + BEGIN_JNI_EXCEPTION - Jnjvm* vm = JavaThread::get()->getJVM(); + // Local object references + JavaObject* clazz = *(JavaObject**)_clazz; + JavaObject* res = 0; + + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); JavaMethod* meth = (JavaMethod*)methodID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - JavaObject* res = cl->doNew(vm); - meth->invokeIntSpecialBuf(vm, cl, res, (void*)args); - return (jobject)res; + + Signdef* sign = meth->getSignature(); + uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); + BufToBuf(args, buf, sign); + + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + + // Store local reference + res = cl->asClass()->doNew(vm); + + meth->invokeIntSpecialBuf(vm, cl->asClass(), res, (void*)buf); + + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; } -jclass GetObjectClass(JNIEnv *env, jobject obj) { +jclass GetObjectClass(JNIEnv *env, jobject _obj) { BEGIN_JNI_EXCEPTION - verifyNull((JavaObject*)obj); - Jnjvm* vm = JavaThread::get()->getJVM(); - return (jclass)((JavaObject*)obj)->getClass()->getClassDelegatee(vm); + // Local object references + JavaObject* obj = *(JavaObject**)_obj; + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + + // Store local reference + return (jclass)obj->getClass()->getClassDelegateePtr(vm); + END_JNI_EXCEPTION return 0; } @@ -303,7 +395,7 @@ jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, - jboolean isStatic) { + jboolean isStatic) { fprintf(stderr, "Implement me\n"); abort(); return 0; @@ -318,21 +410,18 @@ } -jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *aname, - const char *atype) { +jmethodID GetMethodID(JNIEnv* env, jclass _clazz, const char *aname, + const char *atype) { BEGIN_JNI_EXCEPTION - + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); - UserClass* realCl = 0; - if (cl->isClass()) { - realCl = cl->asClass(); - } else { - realCl = cl->super; - } + UserClass* realCl = cl->isClass() ? cl->asClass() : cl->super; const UTF8* name = cl->classLoader->hashUTF8->lookupAsciiz(aname); if (name) { @@ -348,19 +437,27 @@ } -jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { +jobject CallObjectMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION + verifyNull(_obj); + va_list ap; va_start(ap, methodID); - JavaObject* self = (JavaObject*)obj; + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; - Jnjvm* vm = JavaThread::get()->getJVM(); - UserClass* cl = getClassFromVirtualMethod(vm, meth, self->getClass()); - JavaObject* res = meth->invokeJavaObjectVirtualAP(vm, cl, self, ap); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); + + JavaObject* res = meth->invokeJavaObjectVirtualAP(vm, cl, obj, ap, true); va_end(ap); - return (jobject)res; + + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -372,11 +469,20 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaObject* res = 0; + JavaMethod* meth = (JavaMethod*)methodID; + JavaThread* th = JavaThread::get(); Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jobject)meth->invokeJavaObjectVirtualAP(vm, cl, obj, args); + + // Store local reference. + res = meth->invokeJavaObjectVirtualAP(vm, cl, obj, args, true); + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION @@ -395,15 +501,22 @@ jboolean CallBooleanMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION - + + verifyNull(_obj); + va_list ap; va_start(ap, methodID); - JavaObject* self = (JavaObject*)_obj; + + // Local object references. + JavaObject* self = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, self->getClass()); - uint32 res = meth->invokeIntVirtualAP(vm, cl, self, ap); + + uint32 res = meth->invokeIntVirtualAP(vm, cl, self, ap, true); va_end(ap); + return res; END_JNI_EXCEPTION @@ -416,11 +529,15 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jboolean)meth->invokeIntVirtualAP(vm, cl, obj, args); + return (jboolean)meth->invokeIntVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION @@ -446,12 +563,16 @@ va_list args) { BEGIN_JNI_EXCEPTION + + verifyNull(_obj); - JavaObject* obj = (JavaObject*)_obj; + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jbyte)meth->invokeIntVirtualAP(vm, cl, obj, args); + return (jbyte)meth->invokeIntVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION @@ -479,11 +600,16 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jchar)meth->invokeIntVirtualAP(vm, cl, obj, args); + return (jchar)meth->invokeIntVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION @@ -511,11 +637,15 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jshort)meth->invokeIntVirtualAP(vm, cl, obj, args); + return (jshort)meth->invokeIntVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION @@ -535,15 +665,22 @@ jint CallIntMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION - + + verifyNull(_obj); + va_list ap; va_start(ap, methodID); - JavaObject* obj = (JavaObject*)_obj; + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - uint32 res = meth->invokeIntVirtualAP(vm, cl, obj, ap); + + uint32 res = meth->invokeIntVirtualAP(vm, cl, obj, ap, true); va_end(ap); + return res; END_JNI_EXCEPTION @@ -556,11 +693,16 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jint)meth->invokeIntVirtualAP(vm, cl, obj, args); + + return (jint)meth->invokeIntVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION @@ -568,7 +710,7 @@ } -jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, +jint CallIntMethodA(JNIEnv *env, jobject _obj, jmethodID methodID, const jvalue *args) { fprintf(stderr, "Implement me\n"); abort(); @@ -577,7 +719,7 @@ -jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { +jlong CallLongMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) { fprintf(stderr, "Implement me\n"); abort(); return 0; @@ -589,11 +731,15 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jlong)meth->invokeLongVirtualAP(vm, cl, obj, args); + return (jlong)meth->invokeLongVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION @@ -613,14 +759,19 @@ jfloat CallFloatMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION - + + verifyNull(_obj); + va_list ap; va_start(ap, methodID); - JavaObject* obj = (JavaObject*)_obj; + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - jfloat res = meth->invokeFloatVirtualAP(vm, cl, obj, ap); + jfloat res = meth->invokeFloatVirtualAP(vm, cl, obj, ap, true); va_end(ap); return res; @@ -633,12 +784,16 @@ va_list args) { BEGIN_JNI_EXCEPTION + + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; - JavaObject* obj = (JavaObject*)_obj; JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jfloat)meth->invokeFloatVirtualAP(vm, cl, obj, args); + return (jfloat)meth->invokeFloatVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION @@ -658,14 +813,19 @@ jdouble CallDoubleMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION - + + verifyNull(_obj); + va_list ap; va_start(ap, methodID); - JavaObject* obj = (JavaObject*)_obj; + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - jdouble res = meth->invokeDoubleVirtualAP(vm, cl, obj, ap); + jdouble res = meth->invokeDoubleVirtualAP(vm, cl, obj, ap, true); va_end(ap); return res; @@ -679,11 +839,14 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - return (jdouble)meth->invokeDoubleVirtualAP(vm, cl, obj, args); + return (jdouble)meth->invokeDoubleVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION return 0.0; @@ -704,13 +867,18 @@ BEGIN_JNI_EXCEPTION + verifyNull(_obj); + va_list ap; va_start(ap, methodID); - JavaObject* obj = (JavaObject*)_obj; + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - meth->invokeIntVirtualAP(vm, cl, obj, ap); + meth->invokeIntVirtualAP(vm, cl, obj, ap, true); va_end(ap); END_JNI_EXCEPTION @@ -722,11 +890,15 @@ BEGIN_JNI_EXCEPTION - JavaObject* obj = (JavaObject*)_obj; + verifyNull(_obj); + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - meth->invokeIntVirtualAP(vm, cl, obj, args); + meth->invokeIntVirtualAP(vm, cl, obj, args, true); END_JNI_EXCEPTION } @@ -968,14 +1140,19 @@ jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION - + + verifyNull(_obj); + va_list ap; va_start(ap, methodID); - JavaObject* obj = (JavaObject*)_obj; + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - meth->invokeIntSpecialAP(vm, cl, obj, ap); + meth->invokeIntSpecialAP(vm, cl, obj, ap, true); va_end(ap); END_JNI_EXCEPTION @@ -996,14 +1173,16 @@ } -jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *aname, +jfieldID GetFieldID(JNIEnv *env, jclass _clazz, const char *aname, const char *sig) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); if (cl->isClass()) { const UTF8* name = cl->classLoader->hashUTF8->lookupAsciiz(aname); @@ -1023,240 +1202,285 @@ } -jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jobject GetObjectField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaObject* res = 0; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (jobject)field->getObjectField(o); + + // Store local reference. + res = field->getObjectField(obj); + + JavaThread* th = JavaThread::get(); + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; } -jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jboolean GetBooleanField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (uint8)field->getInt8Field(o); + return (uint8)field->getInt8Field(obj); END_JNI_EXCEPTION return 0; } -jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jbyte GetByteField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (sint8)field->getInt8Field(o); + return (sint8)field->getInt8Field(obj); END_JNI_EXCEPTION return 0; } -jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jchar GetCharField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (uint16)field->getInt16Field(o); + return (uint16)field->getInt16Field(obj); END_JNI_EXCEPTION return 0; } -jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jshort GetShortField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (sint16)field->getInt16Field(o); + return (sint16)field->getInt16Field(obj); END_JNI_EXCEPTION return 0; } -jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jint GetIntField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (sint32)field->getInt32Field(o); + return (sint32)field->getInt32Field(obj); END_JNI_EXCEPTION return 0; } -jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jlong GetLongField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (sint64)field->getLongField(o); + return (sint64)field->getLongField(obj); END_JNI_EXCEPTION return 0; } -jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jfloat GetFloatField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return field->getFloatField(o); + return field->getFloatField(obj); END_JNI_EXCEPTION return 0; } -jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID) { +jdouble GetDoubleField(JNIEnv *env, jobject _obj, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - return (jdouble)field->getDoubleField(o); + return (jdouble)field->getDoubleField(obj); END_JNI_EXCEPTION return 0; } -void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value) { +void SetObjectField(JNIEnv *env, jobject _obj, jfieldID fieldID, jobject _value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaObject* value = *(JavaObject**)_value; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setObjectField(o, (JavaObject*)value); + field->setObjectField(obj, value); END_JNI_EXCEPTION } -void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, +void SetBooleanField(JNIEnv *env, jobject _obj, jfieldID fieldID, jboolean value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setInt8Field(o, (uint8)value); + field->setInt8Field(obj, (uint8)value); END_JNI_EXCEPTION } -void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value) { +void SetByteField(JNIEnv *env, jobject _obj, jfieldID fieldID, jbyte value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setInt8Field(o, (uint8)value); + field->setInt8Field(obj, (uint8)value); END_JNI_EXCEPTION } -void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value) { +void SetCharField(JNIEnv *env, jobject _obj, jfieldID fieldID, jchar value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setInt16Field(o, (uint16)value); + field->setInt16Field(obj, (uint16)value); END_JNI_EXCEPTION } -void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value) { +void SetShortField(JNIEnv *env, jobject _obj, jfieldID fieldID, jshort value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setInt16Field(o, (sint16)value); + field->setInt16Field(obj, (sint16)value); END_JNI_EXCEPTION } -void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value) { +void SetIntField(JNIEnv *env, jobject _obj, jfieldID fieldID, jint value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setInt32Field(o, (sint32)value); + field->setInt32Field(obj, (sint32)value); END_JNI_EXCEPTION } -void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value) { +void SetLongField(JNIEnv *env, jobject _obj, jfieldID fieldID, jlong value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setLongField(o, (sint64)value); + field->setLongField(obj, (sint64)value); END_JNI_EXCEPTION } -void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value) { +void SetFloatField(JNIEnv *env, jobject _obj, jfieldID fieldID, jfloat value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setFloatField(o, (float)value); + field->setFloatField(obj, (float)value); END_JNI_EXCEPTION } -void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value) { +void SetDoubleField(JNIEnv *env, jobject _obj, jfieldID fieldID, jdouble value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* obj = *(JavaObject**)_obj; + JavaField* field = (JavaField*)fieldID; - JavaObject* o = (JavaObject*)obj; - field->setDoubleField(o, (float)value); + field->setDoubleField(obj, (float)value); END_JNI_EXCEPTION } -jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *aname, +jmethodID GetStaticMethodID(JNIEnv *env, jclass _clazz, const char *aname, const char *atype) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); if (cl->isClass()) { const UTF8* name = cl->classLoader->hashUTF8->lookupAsciiz(aname); @@ -1275,33 +1499,52 @@ } -jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, +jobject CallStaticObjectMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaObject* res = 0; + + JavaMethod* meth = (JavaMethod*)methodID; - Jnjvm* vm = JavaThread::get()->getJVM(); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jobject res = (jobject) meth->invokeJavaObjectStaticAP(vm, cl, ap); + + // Store local reference. + res = meth->invokeJavaObjectStaticAP(vm, cl, ap, true); va_end(ap); - return res; + + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; } -jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, - va_list args) { +jobject CallStaticObjectMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, + va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaObject* res = 0; + JavaMethod* meth = (JavaMethod*)methodID; - Jnjvm* vm = JavaThread::get()->getJVM(); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jobject)meth->invokeJavaObjectStaticAP(vm, cl, args); + + // Store local reference. + res = meth->invokeJavaObjectStaticAP(vm, cl, args, true); + + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -1316,17 +1559,21 @@ } -jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, +jboolean CallStaticBooleanMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - uint32 res = meth->invokeIntStaticAP(vm, cl, ap); + uint32 res = meth->invokeIntStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1335,15 +1582,18 @@ } -jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jboolean)meth->invokeIntStaticAP(vm, cl, args); + return (jboolean)meth->invokeIntStaticAP(vm, cl, args, true); END_JNI_EXCEPTION return 0; @@ -1358,16 +1608,19 @@ } -jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { +jbyte CallStaticByteMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + va_list ap; va_start(ap, methodID); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jbyte res = (jbyte) meth->invokeIntStaticAP(vm, cl, ap); + jbyte res = (jbyte) meth->invokeIntStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1376,15 +1629,18 @@ } -jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jbyte CallStaticByteMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jbyte)meth->invokeIntStaticAP(vm, cl, args); + return (jbyte)meth->invokeIntStaticAP(vm, cl, args, true); END_JNI_EXCEPTION return 0; @@ -1399,16 +1655,20 @@ } -jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { +jchar CallStaticCharMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jchar res = (jchar) meth->invokeIntStaticAP(vm, cl, ap); + jchar res = (jchar) meth->invokeIntStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1417,21 +1677,24 @@ } -jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jchar CallStaticCharMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jchar)meth->invokeIntStaticAP(vm, cl, args); + return (jchar)meth->invokeIntStaticAP(vm, cl, args, true); END_JNI_EXCEPTION return 0; } -jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, +jchar CallStaticCharMethodA(JNIEnv *env, jclass _clazz, jmethodID methodID, const jvalue *args) { fprintf(stderr, "Implement me\n"); abort(); @@ -1439,17 +1702,21 @@ } -jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, +jshort CallStaticShortMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jshort res = (jshort) meth->invokeIntStaticAP(vm, cl, ap); + jshort res = (jshort) meth->invokeIntStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1458,15 +1725,18 @@ } -jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jshort CallStaticShortMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jshort)meth->invokeIntStaticAP(vm, cl, args); + return (jshort)meth->invokeIntStaticAP(vm, cl, args, true); END_JNI_EXCEPTION return 0; @@ -1481,16 +1751,20 @@ } -jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { +jint CallStaticIntMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jint res = (jint) meth->invokeIntStaticAP(vm, cl, ap); + jint res = (jint) meth->invokeIntStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1499,14 +1773,17 @@ } -jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jint CallStaticIntMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jint)meth->invokeIntStaticAP(vm, cl, args); + return (jint)meth->invokeIntStaticAP(vm, cl, args, true); END_JNI_EXCEPTION @@ -1522,16 +1799,20 @@ } -jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { +jlong CallStaticLongMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jlong res = (jlong) meth->invokeLongStaticAP(vm, cl, ap); + jlong res = (jlong) meth->invokeLongStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1540,15 +1821,18 @@ } -jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jlong CallStaticLongMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jlong)meth->invokeLongStaticAP(vm, cl, args); + return (jlong)meth->invokeLongStaticAP(vm, cl, args, true); END_JNI_EXCEPTION @@ -1565,17 +1849,21 @@ -jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, +jfloat CallStaticFloatMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jfloat res = (jfloat) meth->invokeFloatStaticAP(vm, cl, ap); + jfloat res = (jfloat) meth->invokeFloatStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1584,15 +1872,18 @@ } -jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jfloat CallStaticFloatMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jfloat)meth->invokeFloatStaticAP(vm, cl, args); + return (jfloat)meth->invokeFloatStaticAP(vm, cl, args, true); END_JNI_EXCEPTION @@ -1608,17 +1899,21 @@ } -jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, +jdouble CallStaticDoubleMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - jdouble res = (jdouble) meth->invokeDoubleStaticAP(vm, cl, ap); + jdouble res = (jdouble) meth->invokeDoubleStaticAP(vm, cl, ap, true); va_end(ap); return res; @@ -1627,14 +1922,17 @@ } -jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - return (jdouble)meth->invokeDoubleStaticAP(vm, cl, args); + return (jdouble)meth->invokeDoubleStaticAP(vm, cl, args, true); END_JNI_EXCEPTION @@ -1650,31 +1948,38 @@ } -void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { +void CallStaticVoidMethod(JNIEnv *env, jclass _clazz, jmethodID methodID, ...) { BEGIN_JNI_EXCEPTION - + va_list ap; va_start(ap, methodID); + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - meth->invokeIntStaticAP(vm, cl, ap); + meth->invokeIntStaticAP(vm, cl, ap, true); va_end(ap); END_JNI_EXCEPTION } -void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, +void CallStaticVoidMethodV(JNIEnv *env, jclass _clazz, jmethodID methodID, va_list args) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromStaticMethod(vm, meth, clazz); - meth->invokeIntStaticAP(vm, cl, args); + meth->invokeIntStaticAP(vm, cl, args, true); END_JNI_EXCEPTION } @@ -1687,14 +1992,16 @@ } -jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *aname, +jfieldID GetStaticFieldID(JNIEnv *env, jclass _clazz, const char *aname, const char *sig) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); if (cl->isClass()) { const UTF8* name = cl->classLoader->hashUTF8->lookupAsciiz(aname); @@ -1713,31 +2020,36 @@ } -jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jobject GetStaticObjectField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; - Jnjvm* vm = JavaThread::get()->getJVM(); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); - return (jobject)field->getObjectField(Stat); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); + return (jobject)th->pushJNIRef(field->getObjectField(Stat)); END_JNI_EXCEPTION return 0; } -jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jboolean GetStaticBooleanField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jboolean)field->getInt8Field(Stat); END_JNI_EXCEPTION @@ -1745,15 +2057,17 @@ } -jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jbyte GetStaticByteField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jbyte)field->getInt8Field(Stat); END_JNI_EXCEPTION @@ -1761,15 +2075,17 @@ } -jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jchar GetStaticCharField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jchar)field->getInt16Field(Stat); END_JNI_EXCEPTION @@ -1777,15 +2093,17 @@ } -jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jshort GetStaticShortField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jshort)field->getInt16Field(Stat); END_JNI_EXCEPTION @@ -1793,15 +2111,17 @@ } -jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jint GetStaticIntField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jint)field->getInt32Field(Stat); END_JNI_EXCEPTION @@ -1809,15 +2129,17 @@ } -jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jlong GetStaticLongField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jlong)field->getLongField(Stat); END_JNI_EXCEPTION @@ -1825,15 +2147,17 @@ } -jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jfloat GetStaticFloatField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jfloat)field->getFloatField(Stat); END_JNI_EXCEPTION @@ -1841,15 +2165,17 @@ } -jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID) { +jdouble GetStaticDoubleField(JNIEnv *env, jclass _clazz, jfieldID fieldID) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); return (jdouble)field->getDoubleField(Stat); END_JNI_EXCEPTION @@ -1857,144 +2183,163 @@ } -void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, - jobject value) { +void SetStaticObjectField(JNIEnv *env, jclass _clazz, jfieldID fieldID, + jobject _value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + JavaObject* value = *(JavaObject**)_value; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); - field->setObjectField(Stat, (JavaObject*)value); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); + field->setObjectField(Stat, value); END_JNI_EXCEPTION } -void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticBooleanField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jboolean value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setInt8Field(Stat, (uint8)value); END_JNI_EXCEPTION } -void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticByteField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jbyte value) { BEGIN_JNI_EXCEPTION + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; + Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setInt8Field(Stat, (sint8)value); END_JNI_EXCEPTION } -void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticCharField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jchar value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setInt16Field(Stat, (uint16)value); END_JNI_EXCEPTION } -void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticShortField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jshort value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setInt16Field(Stat, (sint16)value); END_JNI_EXCEPTION } -void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticIntField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jint value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setInt32Field(Stat, (sint32)value); END_JNI_EXCEPTION } -void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticLongField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jlong value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setLongField(Stat, (sint64)value); END_JNI_EXCEPTION } -void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticFloatField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jfloat value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setFloatField(Stat, (float)value); END_JNI_EXCEPTION } -void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, +void SetStaticDoubleField(JNIEnv *env, jclass _clazz, jfieldID fieldID, jdouble value) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* clazz = *(JavaObject**)_clazz; Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; - UserClass* cl = (UserClass*) - UserCommonClass::resolvedImplClass(vm, (JavaObject*)clazz, true); - void* Stat = cl->getStaticInstance(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); + void* Stat = cl->asClass()->getStaticInstance(); field->setDoubleField(Stat, (double)value); END_JNI_EXCEPTION @@ -2032,8 +2377,9 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jstring)(vm->asciizToStr(bytes)); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + return (jstring)th->pushJNIRef(vm->asciizToStr(bytes)); END_JNI_EXCEPTION return 0; @@ -2047,65 +2393,92 @@ } -const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) { +const char *GetStringUTFChars(JNIEnv *env, jstring _string, jboolean *isCopy) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaString* string = *(JavaString**)_string; if (isCopy != 0) (*isCopy) = true; - return ((JavaString*)string)->strToAsciiz(); + return string->strToAsciiz(); END_JNI_EXCEPTION return 0; } -void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) { +void ReleaseStringUTFChars(JNIEnv *env, jstring _string, const char *utf) { delete[] utf; } -jsize GetArrayLength(JNIEnv *env, jarray array) { +jsize GetArrayLength(JNIEnv *env, jarray _array) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaArray* array = *(JavaArray**)_array; - return ((JavaArray*)array)->size; + return array->size; END_JNI_EXCEPTION return 0; } -jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, - jobject initialElement) { +jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass _elementClass, + jobject _initialElement) { BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); + + // Local object references. + JavaObject* elementClass = *(JavaObject**)_elementClass; + JavaObject* initialElement = _initialElement ? + *(JavaObject**)_initialElement : 0; + ArrayObject* res = 0; + + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + if (length < 0) vm->negativeArraySizeException(length); - UserCommonClass* base = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)elementClass, true); + UserCommonClass* base = + UserCommonClass::resolvedImplClass(vm, elementClass, true); JnjvmClassLoader* loader = base->classLoader; const UTF8* name = base->getName(); const UTF8* arrayName = loader->constructArrayName(1, name); UserClassArray* array = loader->constructArray(arrayName, base); - ArrayObject* res = (ArrayObject*)array->doNew(length, vm); + res = (ArrayObject*)array->doNew(length, vm); + if (initialElement) { for (sint32 i = 0; i < length; ++i) { - res->elements[i] = (JavaObject*)initialElement; + res->elements[i] = initialElement; } } - return (jobjectArray)res; + return (jobjectArray)th->pushJNIRef(res); + END_JNI_EXCEPTION return 0; } -jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) { +jobject GetObjectArrayElement(JNIEnv *env, jobjectArray _array, jsize index) { + BEGIN_JNI_EXCEPTION - ArrayObject* JA = (ArrayObject*)array; - if (index >= JA->size) - JavaThread::get()->getJVM()->indexOutOfBounds(JA, index); - return (jobject)JA->elements[index]; + // Local object references. + ArrayObject* array = *(ArrayObject**)_array; + JavaObject* res = 0; + + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + + if (index >= array->size) vm->indexOutOfBounds(array, index); + + // Store local refererence. + res = array->elements[index]; + + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION @@ -2113,15 +2486,20 @@ } -void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, - jobject val) { +void SetObjectArrayElement(JNIEnv *env, jobjectArray _array, jsize index, + jobject _val) { BEGIN_JNI_EXCEPTION - ArrayObject* JA = (ArrayObject*)array; - if (index >= JA->size) - JavaThread::get()->getJVM()->indexOutOfBounds(JA, index); - JA->elements[index] = (JavaObject*)val; + // Local object references. + ArrayObject* array = *(ArrayObject**)_array; + JavaObject* val = *(JavaObject**)_val; + + if (index >= array->size) + JavaThread::get()->getJVM()->indexOutOfBounds(array, index); + + // Store global reference. + array->elements[index] = val; END_JNI_EXCEPTION } @@ -2131,8 +2509,11 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jbooleanArray)vm->upcalls->ArrayOfByte->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfBool->doNew(len, vm); + return (jbooleanArray)th->pushJNIRef(res); + END_JNI_EXCEPTION return 0; @@ -2143,8 +2524,10 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jbyteArray)vm->upcalls->ArrayOfByte->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfByte->doNew(len, vm); + return (jbyteArray)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -2155,8 +2538,10 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jcharArray)vm->upcalls->ArrayOfChar->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfChar->doNew(len, vm); + return (jcharArray)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -2167,8 +2552,10 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jshortArray)vm->upcalls->ArrayOfShort->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfShort->doNew(len, vm); + return (jshortArray)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -2179,8 +2566,10 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jintArray)vm->upcalls->ArrayOfInt->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfInt->doNew(len, vm); + return (jintArray)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -2191,8 +2580,10 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jlongArray)vm->upcalls->ArrayOfLong->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfLong->doNew(len, vm); + return (jlongArray)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -2203,8 +2594,10 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jfloatArray)vm->upcalls->ArrayOfFloat->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfFloat->doNew(len, vm); + return (jfloatArray)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; @@ -2215,262 +2608,409 @@ BEGIN_JNI_EXCEPTION - Jnjvm* vm = myVM(env); - return (jdoubleArray)vm->upcalls->ArrayOfDouble->doNew(len, vm); + JavaThread* th = JavaThread::get(); + Jnjvm* vm = th->getJVM(); + JavaObject* res = vm->upcalls->ArrayOfDouble->doNew(len, vm); + return (jdoubleArray)th->pushJNIRef(res); END_JNI_EXCEPTION return 0; } -jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array, - jboolean *isCopy) { +jboolean* GetBooleanArrayElements(JNIEnv *env, jbooleanArray _array, + jboolean *isCopy) { BEGIN_JNI_EXCEPTION - - if (isCopy) (*isCopy) = false; - return (jboolean*)((ArrayUInt8*)array)->elements; + + // Local object references. + ArrayUInt8* array = *(ArrayUInt8**)_array; + + if (isCopy) (*isCopy) = true; + + sint32 len = array->size * sizeof(uint8); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); + + return (jboolean*)buffer; END_JNI_EXCEPTION return 0; } -jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) { +jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION - if (isCopy) (*isCopy) = false; - return ((ArraySInt8*)array)->elements; + // Local object references. + ArraySInt8* array = *(ArraySInt8**)_array; + + if (isCopy) (*isCopy) = true; + + sint32 len = array->size * sizeof(uint8); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); + + return (jbyte*)buffer; END_JNI_EXCEPTION return 0; } -jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy) { +jchar *GetCharArrayElements(JNIEnv *env, jcharArray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION + + // Local object references. + ArrayUInt16* array = *(ArrayUInt16**)_array; + + if (isCopy) (*isCopy) = true; + + sint32 len = array->size * sizeof(uint16); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); - if (isCopy) (*isCopy) = false; - return ((ArrayUInt16*)array)->elements; + return (jchar*)buffer; END_JNI_EXCEPTION return 0; } -jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, +jshort *GetShortArrayElements(JNIEnv *env, jshortArray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION - if (isCopy) (*isCopy) = false; - return ((ArraySInt16*)array)->elements; + // Local object references. + ArraySInt16* array = *(ArraySInt16**)_array; + + if (isCopy) (*isCopy) = true; + + sint32 len = array->size * sizeof(sint16); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); + + return (jshort*)buffer; END_JNI_EXCEPTION return 0; } -jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy) { +jint *GetIntArrayElements(JNIEnv *env, jintArray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION + + // Local object references. + ArraySInt32* array = *(ArraySInt32**)_array; + + if (isCopy) (*isCopy) = true; + + sint32 len = array->size * sizeof(sint32); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); - if (isCopy) (*isCopy) = false; - return ((ArraySInt32*)array)->elements; + return (jint*)buffer; END_JNI_EXCEPTION return 0; } -jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy) { +jlong *GetLongArrayElements(JNIEnv *env, jlongArray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION + + // Local object references. + ArrayLong* array = *(ArrayLong**)_array; + + if (isCopy) (*isCopy) = true; + + sint32 len = array->size * sizeof(sint64); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); - if (isCopy) (*isCopy) = false; - return (jlong*)(void*)(((ArrayLong*)array)->elements); + return (jlong*)buffer; END_JNI_EXCEPTION return 0; } -jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, +jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION + + // Local object references. + ArrayFloat* array = *(ArrayFloat**)_array; + + if (isCopy) (*isCopy) = true; - if (isCopy) (*isCopy) = false; - return ((ArrayFloat*)array)->elements; + sint32 len = array->size * sizeof(float); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); + + return (jfloat*)buffer; END_JNI_EXCEPTION return 0; } -jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array, +jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION - if (isCopy) (*isCopy) = false; - return ((ArrayDouble*)array)->elements; + // Local object references. + ArrayDouble* array = *(ArrayDouble**)_array; + + if (isCopy) (*isCopy) = true; + + sint32 len = array->size * sizeof(double); + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); + + return (jdouble*)buffer; END_JNI_EXCEPTION return 0; } -void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array, +void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray _array, jboolean *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } -void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, +void ReleaseByteArrayElements(JNIEnv *env, jbyteArray _array, jbyte *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } -void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems, +void ReleaseCharArrayElements(JNIEnv *env, jcharArray _array, jchar *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size << 1; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } -void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems, +void ReleaseShortArrayElements(JNIEnv *env, jshortArray _array, jshort *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size << 1; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } -void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems, +void ReleaseIntArrayElements(JNIEnv *env, jintArray _array, jint *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size << 2; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } -void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems, +void ReleaseLongArrayElements(JNIEnv *env, jlongArray _array, jlong *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size << 3; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } -void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, +void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray _array, jfloat *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size << 2; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } -void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array, +void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray _array, jdouble *elems, jint mode) { + if (mode == JNI_ABORT) { + free(elems); + } else { + JavaArray* array = *(JavaArray**)_array; + + sint32 len = array->size << 3; + memcpy(array->elements, elems, len); + + if (mode == 0) free(elems); + } } void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, jsize len, jboolean *buf) { - ArrayUInt8* Array = (ArrayUInt8*)array; + ArrayUInt8* Array = *(ArrayUInt8**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(uint8)); } void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf) { - ArraySInt8* Array = (ArraySInt8*)array; + ArraySInt8* Array = *(ArraySInt8**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(sint8)); } void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf) { - ArrayUInt16* Array = (ArrayUInt16*)array; + ArrayUInt16* Array = *(ArrayUInt16**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(uint16)); } void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf) { - ArraySInt16* Array = (ArraySInt16*)array; + ArraySInt16* Array = *(ArraySInt16**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(sint16)); } void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf) { - ArraySInt32* Array = (ArraySInt32*)array; + ArraySInt32* Array = *(ArraySInt32**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(sint32)); } void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf) { - ArrayLong* Array = (ArrayLong*)array; + ArrayLong* Array = *(ArrayLong**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(sint64)); } void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf) { - ArrayFloat* Array = (ArrayFloat*)array; + ArrayFloat* Array = *(ArrayFloat**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(float)); } void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf) { - ArrayDouble* Array = (ArrayDouble*)array; + ArrayDouble* Array = *(ArrayDouble**)array; memcpy(buf, &(Array->elements[start]), len * sizeof(double)); } void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, jsize len, const jboolean *buf) { - ArrayUInt8* Array = (ArrayUInt8*)array; + ArrayUInt8* Array = *(ArrayUInt8**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(uint8)); } void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf) { - ArraySInt8* Array = (ArraySInt8*)array; + abort(); + ArraySInt8* Array = *(ArraySInt8**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(sint8)); } void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf) { - ArrayUInt16* Array = (ArrayUInt16*)array; + ArrayUInt16* Array = *(ArrayUInt16**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(uint16)); } void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf) { - ArraySInt16* Array = (ArraySInt16*)array; + ArraySInt16* Array = *(ArraySInt16**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(sint16)); } void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf) { - ArraySInt32* Array = (ArraySInt32*)array; + ArraySInt32* Array = *(ArraySInt32**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(sint32)); } void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, const jlong *buf) { - ArrayLong* Array = (ArrayLong*)array; + ArrayLong* Array = *(ArrayLong**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(sint64)); } void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf) { - ArrayFloat* Array = (ArrayFloat*)array; + ArrayFloat* Array = *(ArrayFloat**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(float)); } void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf) { - ArrayDouble* Array = (ArrayDouble*)array; + ArrayDouble* Array = *(ArrayDouble**)array; memcpy(&(Array->elements[start]), buf, len * sizeof(double)); } @@ -2489,12 +3029,14 @@ return 0; } -jint MonitorEnter(JNIEnv *env, jobject obj) { +jint MonitorEnter(JNIEnv *env, jobject _obj) { BEGIN_JNI_EXCEPTION - if (obj) { - ((JavaObject*)obj)->acquire(); + JavaObject* Obj = *(JavaObject**)_obj; + + if (Obj) { + Obj->acquire(); return 0; } else { return -1; @@ -2506,11 +3048,11 @@ } -jint MonitorExit(JNIEnv *env, jobject obj) { +jint MonitorExit(JNIEnv *env, jobject _obj) { BEGIN_JNI_EXCEPTION - JavaObject* Obj = (JavaObject*)obj; + JavaObject* Obj = *(JavaObject**)_obj; if (Obj) { @@ -2553,19 +3095,40 @@ } -void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy) { +void *GetPrimitiveArrayCritical(JNIEnv *env, jarray _array, jboolean *isCopy) { BEGIN_JNI_EXCEPTION - if (isCopy) (*isCopy) = false; - return ((JavaArray*)array)->elements; + JavaArray* array = *(JavaArray**)_array; + + if (isCopy) (*isCopy) = true; + + UserClassArray* cl = array->getClass()->asArrayClass(); + uint32 logSize = cl->baseClass()->asPrimitiveClass()->logSize; + sint32 len = array->size << logSize; + void* buffer = malloc(len); + memcpy(buffer, array->elements, len); + + return (jchar*)buffer; END_JNI_EXCEPTION return 0; } -void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, +void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray _array, void *carray, jint mode) { + if (mode == JNI_ABORT) { + free(carray); + } else { + JavaArray* array = *(JavaArray**)_array; + + UserClassArray* cl = array->getClass()->asArrayClass(); + uint32 logSize = cl->baseClass()->asPrimitiveClass()->logSize; + sint32 len = array->size << logSize; + memcpy(array->elements, carray, len); + + if (mode == 0) free(carray); + } } @@ -2596,25 +3159,30 @@ jobject NewGlobalRef(JNIEnv* env, jobject obj) { - Jnjvm* vm = myVM(env); - vm->globalRefsLock.lock(); - vm->globalRefs.push_back((JavaObject*)obj); - vm->globalRefsLock.unlock(); - return obj; + + // Local object references. + if (obj) { + JavaObject* Obj = *(JavaObject**)obj; + + Jnjvm* vm = JavaThread::get()->getJVM(); + + + vm->globalRefsLock.lock(); + JavaObject** res = vm->globalRefs.addJNIReference(Obj); + vm->globalRefsLock.unlock(); + + return (jobject)res; + } else { + return 0; + } } void DeleteGlobalRef(JNIEnv* env, jobject globalRef) { + Jnjvm* vm = myVM(env); vm->globalRefsLock.lock(); - for (std::vector >::iterator i = - vm->globalRefs.begin(), - e = vm->globalRefs.end(); i!= e; ++i) { - if ((*i) == (JavaObject*)globalRef) { - vm->globalRefs.erase(i); - break; - } - } + vm->globalRefs.removeJNIReference((JavaObject**)globalRef); vm->globalRefsLock.unlock(); } @@ -2649,7 +3217,7 @@ (uint32)capacity, (uint32)capacity, 0); - return (jobject)res; + return (jobject)th->pushJNIRef(res); END_JNI_EXCEPTION @@ -2660,9 +3228,11 @@ void *GetDirectBufferAddress(JNIEnv *env, jobject _buf) { BEGIN_JNI_EXCEPTION + + // Local object references. + JavaObject* buf = *(JavaObject**)_buf; Jnjvm* vm = myVM(env); - JavaObject* buf = (JavaObject*)_buf; JavaObject* address = vm->upcalls->bufferAddress->getObjectField(buf); if (address != 0) { #if (__WORDSIZE == 32) Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Sun Jul 19 11:38:58 2009 @@ -673,6 +673,12 @@ return getDelegatee(); } +JavaObject* const* UserCommonClass::getClassDelegateePtr(Jnjvm* vm, JavaObject* pd) { + // Make sure it's created. + getClassDelegatee(vm, pd); + return getDelegateePtr(); +} + #define PATH_MANIFEST "META-INF/MANIFEST.MF" #define MAIN_CLASS "Main-Class: " #define MAIN_LOWER_CLASS "Main-class: " Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h Sun Jul 19 11:38:58 2009 @@ -21,6 +21,7 @@ #include "mvm/Threads/Locks.h" #include "JnjvmConfig.h" +#include "JNIReferences.h" #include "LockedMap.h" namespace jnjvm { @@ -221,7 +222,7 @@ /// globalRefs - Global references that JNI wants to protect. /// - std::vector > globalRefs; + JNIGlobalReferences globalRefs; /// globalRefsLock - Lock for adding a new global reference. /// Modified: vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Sun Jul 19 11:38:58 2009 @@ -265,9 +265,13 @@ if (appClassLoader) appClassLoader->getJavaClassLoader()->markAndTrace(); - for (std::vector >::iterator - i = globalRefs.begin(), e = globalRefs.end(); i!= e; ++i) { - (*i)->markAndTrace(); + JNIGlobalReferences* start = &globalRefs; + while (start) { + for (uint32 i = 0; i < start->length; ++i) { + JavaObject* obj = start->globalReferences[i]; + obj->markAndTrace(); + } + start = start->next; } for (StringMap::iterator i = hashStr.map.begin(), e = hashStr.map.end(); @@ -291,4 +295,13 @@ #ifdef SERVICE ServiceException->markAndTrace(); #endif + + JNILocalReferences* end = localJNIRefs; + while (end) { + for (uint32 i = 0; i < end->length; ++i) { + JavaObject* obj = end->localReferences[i]; + obj->markAndTrace(); + } + end = end->prev; + } } Modified: vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp?rev=76369&r1=76368&r2=76369&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp (original) +++ vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp Sun Jul 19 11:38:58 2009 @@ -57,6 +57,7 @@ fprintf(stderr, "I received a SIGSEGV: either the VM code or an external\n" "native method is bogus. Aborting...\n"); } + th->printBacktraceAfterSignal(); abort(); #if defined(__i386__) From nicolas.geoffray at lip6.fr Sun Jul 19 09:40:25 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Sun, 19 Jul 2009 16:40:25 -0000 Subject: [vmkit-commits] [vmkit] r76370 - /vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h Message-ID: <200907191640.n6JGePLN007572@zion.cs.uiuc.edu> Author: geoffray Date: Sun Jul 19 11:40:25 2009 New Revision: 76370 URL: http://llvm.org/viewvc/llvm-project?rev=76370&view=rev Log: Forgot this file from last commit. Added: vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h Added: vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h?rev=76370&view=auto ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h (added) +++ vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h Sun Jul 19 11:40:25 2009 @@ -0,0 +1,88 @@ +//===--------- JNIReferences.cpp - Management of JNI references -----------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef JNI_REFERENCES_H +#define JNI_REFERENCES_H + +namespace jnjvm { + +class JavaObject; +class JavaThread; + +#define MAXIMUM_REFERENCES 100 + +class JNILocalReferences { + friend class JavaThread; + +private: + JNILocalReferences* prev; + uint32_t length; + JavaObject* localReferences[MAXIMUM_REFERENCES]; + +public: + + JNILocalReferences() { + prev = 0; + length = 0; + } + + JavaObject** addJNIReference(JavaThread* th, JavaObject* obj); + + void removeJNIReferences(JavaThread* th, uint32_t num); + +}; + +class JNIGlobalReferences { + friend class Jnjvm; + +private: + JNIGlobalReferences* next; + JNIGlobalReferences* prev; + uint32_t length; + uint32_t count; + JavaObject* globalReferences[MAXIMUM_REFERENCES]; + + +public: + JNIGlobalReferences() { + next = 0; + prev = 0; + length = 0; + count = 0; + } + + JavaObject** addJNIReference(JavaObject* obj) { + if (length == MAXIMUM_REFERENCES) { + if (!next) { + next = new JNIGlobalReferences(); + next->prev = this; + } + return next->addJNIReference(obj); + } else { + ++count; + globalReferences[length] = obj; + return &globalReferences[length++]; + } + } + + void removeJNIReference(JavaObject** obj) { + if (((uintptr_t)obj >= (uintptr_t)globalReferences) && + ((uintptr_t)obj) < (uintptr_t)(globalReferences + MAXIMUM_REFERENCES)) { + *obj = 0; + --count; + } else { + assert(next && "No global reference located there"); + next->removeJNIReference(obj); + } + } +}; + +} + +#endif From nicolas.geoffray at lip6.fr Sun Jul 19 09:44:13 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Sun, 19 Jul 2009 16:44:13 -0000 Subject: [vmkit-commits] [vmkit] r76371 - /vmkit/trunk/include/mvm/Threads/Locks.h Message-ID: <200907191644.n6JGiD5E007709@zion.cs.uiuc.edu> Author: geoffray Date: Sun Jul 19 11:44:12 2009 New Revision: 76371 URL: http://llvm.org/viewvc/llvm-project?rev=76371&view=rev Log: Fix type. Modified: vmkit/trunk/include/mvm/Threads/Locks.h Modified: vmkit/trunk/include/mvm/Threads/Locks.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Locks.h?rev=76371&r1=76370&r2=76371&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Threads/Locks.h (original) +++ vmkit/trunk/include/mvm/Threads/Locks.h Sun Jul 19 11:44:12 2009 @@ -353,7 +353,7 @@ /// void acquire() { for (uint32 count = 0; count < 1000; ++count) { - uint8 res = __sync_val_compare_and_swap(&locked, 0, 1); + uint32 res = __sync_val_compare_and_swap(&locked, 0, 1); if (!res) return; } From nicolas.geoffray at lip6.fr Sun Jul 19 10:00:30 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Sun, 19 Jul 2009 17:00:30 -0000 Subject: [vmkit-commits] [vmkit] r76372 - in /vmkit/trunk/lib: JnJVM/Compiler/JavaAOTCompiler.cpp JnJVM/Compiler/JavaJIT.cpp Mvm/Compiler/EscapeAnalysis.cpp N3/VMCore/CLIJit.cpp N3/VMCore/Opcodes.cpp Message-ID: <200907191700.n6JH0VBg008196@zion.cs.uiuc.edu> Author: geoffray Date: Sun Jul 19 12:00:30 2009 New Revision: 76372 URL: http://llvm.org/viewvc/llvm-project?rev=76372&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp vmkit/trunk/lib/N3/VMCore/CLIJit.cpp vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=76372&r1=76371&r2=76372&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Sun Jul 19 12:00:30 2009 @@ -763,7 +763,7 @@ assert(ATy && "Malformed type"); Constant* TCM[1] = { getJavaClass(cl) }; - CommonClassElts.push_back(ConstantArray::get(ATy, TCM, 1)); + CommonClassElts.push_back(Context.getConstantArray(ATy, TCM, 1)); // access CommonClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->access)); @@ -1022,7 +1022,7 @@ TempElts.push_back(getStaticInstance(cl)); Constant* CStr[1] = { ConstantStruct::get(TCMTy, TempElts) }; TempElts.clear(); - ClassElts.push_back(ConstantArray::get(ATy, CStr, 1)); + ClassElts.push_back(Context.getConstantArray(ATy, CStr, 1)); // thinlock ClassElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76372&r1=76371&r2=76372&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Sun Jul 19 12:00:30 2009 @@ -280,13 +280,12 @@ endBlock = createBasicBlock("end block"); // Allocate currentLocalIndexNumber pointer - Value* temp = new AllocaInst(*llvmContext, Type::Int32Ty, "", + Value* temp = new AllocaInst(Type::Int32Ty, "", currentBlock); new StoreInst(module->constantZero, temp, false, currentBlock); // Allocate oldCurrentLocalIndexNumber pointer - Value* oldCLIN = new AllocaInst(*llvmContext, - PointerType::getUnqual(Type::Int32Ty), "", + Value* oldCLIN = new AllocaInst(PointerType::getUnqual(Type::Int32Ty), "", currentBlock); Value* Args2[2] = { temp, oldCLIN }; @@ -357,7 +356,7 @@ currentBlock = NotZero; - Value* temp = new AllocaInst(*llvmContext, module->JavaObjectType, "", + Value* temp = new AllocaInst(module->JavaObjectType, "", currentBlock); new StoreInst(i, temp, false, currentBlock); node->addIncoming(temp, currentBlock); @@ -408,7 +407,7 @@ // this problem because it passes first arguments in registers. // Therefore, it was overwriting the frame pointer when entering the // native method. - Value* Temp = new AllocaInst(*llvmContext, module->ptrType, "", currentBlock); + Value* Temp = new AllocaInst(module->ptrType, "", currentBlock); new StoreInst(FrameAddr, Temp, currentBlock); Value* result = llvm::CallInst::Create(nativeFunc, nativeArgs.begin(), nativeArgs.end(), "", currentBlock); @@ -691,21 +690,21 @@ Instruction* firstInstruction = firstBB->begin(); for (int i = 0; i < maxLocals; i++) { - intLocals.push_back(new AllocaInst(*llvmContext, Type::Int32Ty, "", firstInstruction)); - doubleLocals.push_back(new AllocaInst(*llvmContext, Type::DoubleTy, "", + intLocals.push_back(new AllocaInst(Type::Int32Ty, "", firstInstruction)); + doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", firstInstruction)); - longLocals.push_back(new AllocaInst(*llvmContext, Type::Int64Ty, "", firstInstruction)); - floatLocals.push_back(new AllocaInst(*llvmContext, Type::FloatTy, "", firstInstruction)); - objectLocals.push_back(new AllocaInst(*llvmContext, module->JavaObjectType, "", + longLocals.push_back(new AllocaInst(Type::Int64Ty, "", firstInstruction)); + floatLocals.push_back(new AllocaInst(Type::FloatTy, "", firstInstruction)); + objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", firstInstruction)); } } else { for (int i = 0; i < maxLocals; i++) { - intLocals.push_back(new AllocaInst(*llvmContext, Type::Int32Ty, "", firstBB)); - doubleLocals.push_back(new AllocaInst(*llvmContext, Type::DoubleTy, "", firstBB)); - longLocals.push_back(new AllocaInst(*llvmContext, Type::Int64Ty, "", firstBB)); - floatLocals.push_back(new AllocaInst(*llvmContext, Type::FloatTy, "", firstBB)); - objectLocals.push_back(new AllocaInst(*llvmContext, module->JavaObjectType, "", + intLocals.push_back(new AllocaInst(Type::Int32Ty, "", firstBB)); + doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", firstBB)); + longLocals.push_back(new AllocaInst(Type::Int64Ty, "", firstBB)); + floatLocals.push_back(new AllocaInst(Type::FloatTy, "", firstBB)); + objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", firstBB)); } } @@ -829,11 +828,11 @@ for (int i = 0; i < maxLocals; i++) { - intLocals.push_back(new AllocaInst(*llvmContext, Type::Int32Ty, "", currentBlock)); - doubleLocals.push_back(new AllocaInst(*llvmContext, Type::DoubleTy, "", currentBlock)); - longLocals.push_back(new AllocaInst(*llvmContext, Type::Int64Ty, "", currentBlock)); - floatLocals.push_back(new AllocaInst(*llvmContext, Type::FloatTy, "", currentBlock)); - objectLocals.push_back(new AllocaInst(*llvmContext, module->JavaObjectType, "", + intLocals.push_back(new AllocaInst(Type::Int32Ty, "", currentBlock)); + doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", currentBlock)); + longLocals.push_back(new AllocaInst(Type::Int64Ty, "", currentBlock)); + floatLocals.push_back(new AllocaInst(Type::FloatTy, "", currentBlock)); + objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", currentBlock)); } @@ -885,7 +884,7 @@ #if defined(ISOLATE_SHARING) ctpCache = i; - Value* addrCtpCache = new AllocaInst(*llvmContext, module->ConstantPoolType, "", + Value* addrCtpCache = new AllocaInst(module->ConstantPoolType, "", currentBlock); /// make it volatile to be sure it's on the stack new StoreInst(ctpCache, addrCtpCache, true, currentBlock); Modified: vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp?rev=76372&r1=76371&r2=76372&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp Sun Jul 19 12:00:30 2009 @@ -168,7 +168,6 @@ bool EscapeAnalysis::processMalloc(Instruction* I, Value* Size, Value* VT, Loop* CurLoop) { Instruction* Alloc = I; - LLVMContext* Context = I->getParent()->getContext(); ConstantInt* CI = dyn_cast(Size); bool hasFinalizer = true; @@ -220,7 +219,7 @@ BB->getInstList().insert(BB->getTerminator(), Alloc); } - AllocaInst* AI = new AllocaInst(*Context, Type::Int8Ty, Size, "", Alloc); + AllocaInst* AI = new AllocaInst(Type::Int8Ty, Size, "", Alloc); BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc); DOUT << "escape" << Alloc->getParent()->getParent()->getName() << "\n"; Alloc->replaceAllUsesWith(BI); Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=76372&r1=76371&r2=76372&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Sun Jul 19 12:00:30 2009 @@ -625,7 +625,7 @@ return; } else if (type->super == MSCorlib::pValue || type->super == MSCorlib::pEnum) { - obj = new AllocaInst(*(llvmFunction->getContext()), type->naturalType, "", currentBlock); + obj = new AllocaInst(type->naturalType, "", currentBlock); uint64 size = module->getTypeSize(type->naturalType); std::vector params; @@ -978,7 +978,7 @@ } if (nbe) { - supplLocal = new AllocaInst(*(llvmFunction->getContext()), VMObject::llvmType, "exceptionVar", + supplLocal = new AllocaInst(VMObject::llvmType, "exceptionVar", currentBlock); } @@ -1210,7 +1210,7 @@ const Type* cur = i->getType(); - AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cur, "", currentBlock); + AllocaInst* alloc = new AllocaInst(cur, "", currentBlock); new StoreInst(i, alloc, false, currentBlock); arguments.push_back(alloc); } @@ -1223,7 +1223,7 @@ e = temp.end(); i!= e; ++i) { VMCommonClass* cl = *i; cl->resolveType(false, false, genMethod); - AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cl->naturalType, "", currentBlock); + AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, currentBlock); @@ -1387,7 +1387,7 @@ const Type* cur = (*i)->getType(); - AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cur, "", currentBlock); + AllocaInst* alloc = new AllocaInst(cur, "", currentBlock); new StoreInst(*i, alloc, false, currentBlock); arguments.push_back(alloc); } @@ -1400,7 +1400,7 @@ e = temp.end(); i!= e; ++i) { VMCommonClass* cl = *i; cl->resolveType(false, false, genMethod); - AllocaInst* alloc = new AllocaInst(*(llvmFunction->getContext()), cl->naturalType, "", currentBlock); + AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, currentBlock); @@ -1623,7 +1623,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } Value* val = 0; @@ -1655,7 +1655,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } @@ -1692,7 +1692,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } @@ -1721,7 +1721,7 @@ funcType = funcType->getContainedType(0); } const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1); - ret = new AllocaInst(*(llvmFunction->getContext()), lastType->getContainedType(0), "", InsertAtEnd); + ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd); args.push_back(ret); } Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=76372&r1=76371&r2=76372&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Sun Jul 19 12:00:30 2009 @@ -191,7 +191,7 @@ return new LoadInst(val, name, currentBlock); } else { uint64 size = module->getTypeSize(contained); - Value* ret = new AllocaInst(*(llvmFunction->getContext()), contained, "", currentBlock); + Value* ret = new AllocaInst(contained, "", currentBlock); std::vector params; params.push_back(new BitCastInst(ret, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); @@ -1302,7 +1302,7 @@ if (val->getType()->getTypeID() != Type::PointerTyID) { convertValue(val, type->naturalType, currentBlock); - Value* tmp = new AllocaInst(*(llvmFunction->getContext()), type->naturalType, "", currentBlock); + Value* tmp = new AllocaInst(type->naturalType, "", currentBlock); new StoreInst(val, tmp, false, currentBlock); val = tmp; } @@ -1794,7 +1794,7 @@ true, genClass, genMethod); assert(type); - Value* val = new AllocaInst(*(llvmFunction->getContext()), type->naturalType, "", currentBlock); + Value* val = new AllocaInst(type->naturalType, "", currentBlock); Value* obj = pop(); if (obj->getType() != type->virtualType) { @@ -1924,7 +1924,7 @@ } case LOCALLOC : { - push(new AllocaInst(*(llvmFunction->getContext()), Type::Int8Ty, pop(), "", currentBlock)); + push(new AllocaInst(Type::Int8Ty, pop(), "", currentBlock)); break; } From nicolas.geoffray at lip6.fr Sun Jul 19 13:21:30 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Sun, 19 Jul 2009 20:21:30 -0000 Subject: [vmkit-commits] [vmkit] r76379 - /vmkit/trunk/tools/vmjc/vmjc.cpp Message-ID: <200907192021.n6JKLUlF015288@zion.cs.uiuc.edu> Author: geoffray Date: Sun Jul 19 15:21:30 2009 New Revision: 76379 URL: http://llvm.org/viewvc/llvm-project?rev=76379&view=rev Log: Move to new llvm API. Modified: vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=76379&r1=76378&r2=76379&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Sun Jul 19 15:21:30 2009 @@ -97,6 +97,9 @@ static cl::opt TargetTriple("mtriple", cl::desc("Override target triple for module")); +static cl::opt +MArch("march", cl::desc("Architecture to generate code for (see --version)")); + static cl::opt DisableExceptions("disable-exceptions", cl::desc("Disable Java exceptions")); @@ -121,10 +124,6 @@ WithClinit("with-clinit", cl::desc("Set a property"), cl::ZeroOrMore, cl::CommaSeparated); -static cl::opt > -MArch("march", cl::desc("Architecture to generate code for:")); - inline void addPass(FunctionPassManager *PM, Pass *P) { // Add the pass to the pass manager... @@ -192,36 +191,47 @@ TheModule->setTargetTriple(TargetTriple); else TheModule->setTargetTriple(mvm::MvmModule::getHostTriple()); - - - // Allocate target machine. First, check whether the user has + // explicitly specified an architecture to compile for. - const Target *TheTarget; - if (MArch) { - TheTarget = &MArch->TheTarget; + const Target *TheTarget = 0; + if (!MArch.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (MArch == it->getName()) { + TheTarget = &*it; + break; + } + } + + if (!TheTarget) { + errs() << argv[0] << ": error: invalid target '" << MArch << "'.\n"; + return 1; + } } else { std::string Err; - TheTarget = + TheTarget = TargetRegistry::getClosestStaticTargetForModule(*TheModule, Err); if (TheTarget == 0) { - std::cerr << argv[0] << ": error auto-selecting target for module '" - << Err << "'. Please use the -march option to explicitly " - << "pick a target.\n"; + errs() << argv[0] << ": error auto-selecting target for module '" + << Err << "'. Please use the -march option to explicitly " + << "pick a target.\n"; return 1; } } std::string FeaturesStr; - TargetMachine *Target = - TheTarget->createTargetMachine(*TheModule, FeaturesStr); + std::auto_ptr + target(TheTarget->createTargetMachine(*TheModule, FeaturesStr)); + assert(target.get() && "Could not allocate target machine!"); + TargetMachine &Target = *target.get(); // Install information about target datalayout stuff into the module for // optimizer use. - TheModule->setDataLayout(Target->getTargetData()-> + TheModule->setDataLayout(Target.getTargetData()-> getStringRepresentation()); - mvm::MvmModule::initialise(CodeGenOpt::Default, TheModule, Target); + mvm::MvmModule::initialise(CodeGenOpt::Default, TheModule, &Target); } else { mvm::MvmModule::initialise(); } From nicolas.geoffray at lip6.fr Mon Jul 20 03:17:27 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 10:17:27 -0000 Subject: [vmkit-commits] [vmkit] r76419 - /vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Message-ID: <200907201017.n6KAHUX4022961@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 05:17:16 2009 New Revision: 76419 URL: http://llvm.org/viewvc/llvm-project?rev=76419&view=rev Log: Initialize passes before running them. Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=76419&r1=76418&r2=76419&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 20 05:17:16 2009 @@ -329,7 +329,8 @@ addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores addPass(PM, createAggressiveDCEPass()); // Delete dead instructions addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs - + + PM->doInitialization(); } // We protect the creation of IR with the executionEngine lock because From nicolas.geoffray at lip6.fr Mon Jul 20 03:19:58 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 10:19:58 -0000 Subject: [vmkit-commits] [vmkit] r76420 - in /vmkit/trunk/lib/JnJVM: Classpath/ClasspathVMRuntime.inc Compiler/JavaJIT.cpp LLVMRuntime/runtime-default.ll VMCore/JavaRuntimeJIT.cpp VMCore/JavaThread.cpp VMCore/JavaThread.h Message-ID: <200907201019.n6KAJxba023059@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 05:19:51 2009 New Revision: 76420 URL: http://llvm.org/viewvc/llvm-project?rev=76420&view=rev Log: Use the thread stack to allocate jmp_buf buffers instead of a vector. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc?rev=76420&r1=76419&r2=76420&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Mon Jul 20 05:19:51 2009 @@ -76,8 +76,9 @@ #endif typedef int (*onLoad_t)(const void**, void*); -extern "C" void jnjvmJNIProceedPendingException(uint32** old); -extern "C" void* jnjvmGetSJLJBuffer(uint32* num, uint32** old); +extern "C" void jnjvmJNIProceedPendingException(uint32** old, void** oldBuf); +extern "C" void jnjvmGetSJLJBuffer(uint32* num, uint32** old, void* newBuf, + void** newBuf); // Calls the JNI_OnLoad function of a dynamic library. void callOnLoad(void* res, JnjvmClassLoader* loader, Jnjvm* vm) { @@ -87,13 +88,15 @@ if (onLoad) { uint32 num = 0; uint32* old = 0; - void* buf = jnjvmGetSJLJBuffer(&num, &old); + void* oldBuf = 0; + jmp_buf buf; + jnjvmGetSJLJBuffer(&num, &old, (void*)buf, &oldBuf); if (setjmp((jumpbuf_t)buf) == 0) { onLoad(&vm->javavmEnv, res); } - jnjvmJNIProceedPendingException(&old); + jnjvmJNIProceedPendingException(&old, &oldBuf); } } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76420&r1=76419&r2=76420&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Mon Jul 20 05:19:51 2009 @@ -273,11 +273,16 @@ compilingMethod->setCompiledPtr((void*)natPtr, functionName); return llvmFunction; } - + + currentExceptionBlock = endExceptionBlock = 0; currentBlock = createBasicBlock("start"); BasicBlock* executeBlock = createBasicBlock("execute"); endBlock = createBasicBlock("end block"); + + Constant* sizeB = llvmContext->getConstantInt(Type::Int32Ty, sizeof(jmp_buf)); + Value* oldJB = new AllocaInst(module->ptrType, "", currentBlock); + Value* newJB = new AllocaInst(Type::Int8Ty, sizeB, "", currentBlock); // Allocate currentLocalIndexNumber pointer Value* temp = new AllocaInst(Type::Int32Ty, "", @@ -288,11 +293,12 @@ Value* oldCLIN = new AllocaInst(PointerType::getUnqual(Type::Int32Ty), "", currentBlock); - Value* Args2[2] = { temp, oldCLIN }; + Value* Args4[4] = { temp, oldCLIN, newJB, oldJB }; + + CallInst::Create(module->GetSJLJBufferFunction, Args4, Args4 + 4, "", + currentBlock); - Value* buf = CallInst::Create(module->GetSJLJBufferFunction, - Args2, Args2 + 2, "", currentBlock); - Value* test = CallInst::Create(module->setjmpLLVM, buf, "", + Value* test = CallInst::Create(module->setjmpLLVM, newJB, "", currentBlock); test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, test, @@ -436,9 +442,11 @@ currentBlock = endBlock; if (isSynchro(compilingMethod->access)) endSynchronize(); - - CallInst::Create(module->JniProceedPendingExceptionFunction, oldCLIN, "", - currentBlock); + + Value* Args2[2] = { oldCLIN, oldJB }; + + CallInst::Create(module->JniProceedPendingExceptionFunction, Args2, Args2 + 2, + "", currentBlock); if (returnType != Type::VoidTy) ReturnInst::Create(endNode, currentBlock); Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=76420&r1=76419&r2=76420&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Mon Jul 20 05:19:51 2009 @@ -221,8 +221,8 @@ declare void @jnjvmThrowException(%JavaObject*) declare void @jnjvmThrowExceptionFromJIT() -declare void @jnjvmJNIProceedPendingException(i32**) -declare i8* @jnjvmGetSJLJBuffer(i32*, i32**) +declare void @jnjvmJNIProceedPendingException(i32**, i8**) +declare void @jnjvmGetSJLJBuffer(i32*, i32**, i8*, i8**) declare %JavaObject* @gcmalloc(i32, %VT*) Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=76420&r1=76419&r2=76420&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Mon Jul 20 05:19:51 2009 @@ -369,20 +369,19 @@ } // Does not call Java code. -extern "C" void jnjvmJNIProceedPendingException(uint32** oldLRN) { +extern "C" void jnjvmJNIProceedPendingException(uint32** oldLRN, void** oldBuffer) { JavaThread* th = JavaThread::get(); - jmp_buf* buf = th->sjlj_buffers.back(); - // Remove the buffer. - th->sjlj_buffers.pop_back(); - mvm::Allocator& allocator = th->getJVM()->gcAllocator; - allocator.freeTemporaryMemory(buf); - // We're going back to Java th->endJNI(); - + + // Update the buffer. + th->currentSjljBuffer = *oldBuffer; + + // Update the number of references. th->currentAddedReferences = *oldLRN; + #ifdef DWARF_EXCEPTIONS // If there's an exception, throw it now. if (JavaThread::get()->pendingException) { @@ -392,12 +391,16 @@ } // Never throws. -extern "C" void* jnjvmGetSJLJBuffer(uint32* localReferencesNumber, - uint32** oldLocalReferencesNumber) { +extern "C" void jnjvmGetSJLJBuffer(uint32* localReferencesNumber, + uint32** oldLocalReferencesNumber, + void* newBuffer, void** oldBuffer) { JavaThread* th = JavaThread::get(); - mvm::Allocator& allocator = th->getJVM()->gcAllocator; - void** buf = (void**)allocator.allocateTemporaryMemory(sizeof(jmp_buf)); - th->sjlj_buffers.push_back((jmp_buf*)buf); + + *oldBuffer = th->currentSjljBuffer; + th->currentSjljBuffer = newBuffer; + + memset(newBuffer, 0, sizeof(jmp_buf)); + *oldLocalReferencesNumber = th->currentAddedReferences; th->currentAddedReferences = localReferencesNumber; @@ -405,8 +408,7 @@ // JNI function. th->startJNI(2); - // Finally, return the buffer that the Java code will use to do the setjmp. - return (void*)buf; + return; } // Never throws. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp?rev=76420&r1=76419&r2=76420&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Mon Jul 20 05:19:51 2009 @@ -33,6 +33,7 @@ jniEnv = isolate->jniEnv; localJNIRefs = new JNILocalReferences(); currentAddedReferences = 0; + currentSjljBuffer = 0; #ifdef SERVICE eipIndex = 0; @@ -298,6 +299,7 @@ JavaObject** JNILocalReferences::addJNIReference(JavaThread* th, JavaObject* obj) { if (length == MAXIMUM_REFERENCES) { + fprintf(stderr, "CREATE\n"); JNILocalReferences* next = new JNILocalReferences(); th->localJNIRefs = next; next->prev = this; @@ -317,9 +319,6 @@ if (num > length) { fprintf(stderr, "num = %d et length = %d\n", num, length); - if (!prev) { - JavaThread::get()->printBacktrace(); - } assert(prev && "No prev and deleting too much local references"); prev->removeJNIReferences(th, num - length); } else { Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h?rev=76420&r1=76419&r2=76420&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Mon Jul 20 05:19:51 2009 @@ -108,11 +108,11 @@ /// state - The current state of this thread: Running, Waiting or Interrupted. uint32 state; - /// sjlj_buffers - Setjmp buffers pushed when entering a non-JVM native + /// currentSjljBuffers - Current buffer pushed when entering a non-JVM native /// function and popped when leaving the function. The buffer is used when /// the native function throws an exception through a JNI throwException call. /// - std::vector sjlj_buffers; + void* currentSjljBuffer; /// addresses - The list of return addresses which represent native/Java cross /// calls. @@ -130,7 +130,7 @@ JavaObject** pushJNIRef(JavaObject* obj) { if (!obj) return 0; - + ++(*currentAddedReferences); return localJNIRefs->addJNIReference(this, obj); @@ -191,12 +191,12 @@ /// throwFromJNI - Throw an exception after executing JNI code. /// void throwFromJNI() { - assert(sjlj_buffers.size()); + assert(currentSjljBuffer); internalPendingException = 0; #if defined(__MACH__) - longjmp((int*)sjlj_buffers.back(), 1); + longjmp((int*)currentSjljBuffer, 1); #else - longjmp((__jmp_buf_tag*)sjlj_buffers.back(), 1); + longjmp((__jmp_buf_tag*)currentSjljBuffer, 1); #endif } From nicolas.geoffray at lip6.fr Mon Jul 20 10:02:20 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 17:02:20 -0000 Subject: [vmkit-commits] [vmkit] r76428 - /vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Message-ID: <200907201702.n6KH2LUe004408@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 12:02:20 2009 New Revision: 76428 URL: http://llvm.org/viewvc/llvm-project?rev=76428&view=rev Log: Remove accidental printf. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp?rev=76428&r1=76427&r2=76428&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Mon Jul 20 12:02:20 2009 @@ -299,7 +299,6 @@ JavaObject** JNILocalReferences::addJNIReference(JavaThread* th, JavaObject* obj) { if (length == MAXIMUM_REFERENCES) { - fprintf(stderr, "CREATE\n"); JNILocalReferences* next = new JNILocalReferences(); th->localJNIRefs = next; next->prev = this; @@ -318,7 +317,6 @@ } if (num > length) { - fprintf(stderr, "num = %d et length = %d\n", num, length); assert(prev && "No prev and deleting too much local references"); prev->removeJNIReferences(th, num - length); } else { From nicolas.geoffray at lip6.fr Mon Jul 20 10:03:29 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 17:03:29 -0000 Subject: [vmkit-commits] [vmkit] r76429 - /vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Message-ID: <200907201703.n6KH3UqB004446@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 12:03:29 2009 New Revision: 76429 URL: http://llvm.org/viewvc/llvm-project?rev=76429&view=rev Log: Be consistent. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=76429&r1=76428&r2=76429&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Mon Jul 20 12:03:29 2009 @@ -1021,7 +1021,7 @@ JavaObject* clazz, bool doClinit) { UserCommonClass* cl = ((JavaObjectClass*)clazz)->getClass(); - if (cl->asClass()) { + if (cl->isClass()) { cl->asClass()->resolveClass(); if (doClinit) cl->asClass()->initialiseClass(vm); } From nicolas.geoffray at lip6.fr Mon Jul 20 10:07:01 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 17:07:01 -0000 Subject: [vmkit-commits] [vmkit] r76430 - in /vmkit/trunk: include/mvm/ lib/JnJVM/Classpath/ Message-ID: <200907201707.n6KH72vQ004562@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 12:07:01 2009 New Revision: 76430 URL: http://llvm.org/viewvc/llvm-project?rev=76430&view=rev Log: Add llvm.gcroot intrinsic to references on stack. Modified: vmkit/trunk/include/mvm/Allocator.h vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathField.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMObject.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMStackWalker.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystem.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThread.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc vmkit/trunk/lib/JnJVM/Classpath/JavaUpcalls.cpp Modified: vmkit/trunk/include/mvm/Allocator.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Allocator.h?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Allocator.h (original) +++ vmkit/trunk/include/mvm/Allocator.h Mon Jul 20 12:07:01 2009 @@ -20,8 +20,13 @@ class VirtualTable; -namespace mvm { +#ifdef LLVM_GCC +extern "C" void llvm_gcroot(const void*, void*) asm("llvm.gcroot"); +#else +#define llvm_gcroot +#endif +namespace mvm { class Allocator { public: Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.inc Mon Jul 20 12:07:01 2009 @@ -31,7 +31,10 @@ #endif JavaObjectConstructor* cons) { - jobject res = 0; + JavaObject* res = 0; + + llvm_gcroot(cons, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -40,10 +43,10 @@ JavaMethod* meth = cons->getInternalMethod(); JnjvmClassLoader* loader = cl->classLoader; - res = (jobject)meth->getParameterTypes(loader); + res = meth->getParameterTypes(loader); END_NATIVE_EXCEPTION - return res; + return (jobject)res; } JNIEXPORT jint JNICALL Java_java_lang_reflect_Constructor_getModifiersInternal( @@ -52,6 +55,7 @@ #endif JavaObjectConstructor* cons) { + llvm_gcroot(cons, 0); jint res = 0; BEGIN_NATIVE_EXCEPTION(0) @@ -65,17 +69,26 @@ return res; } -static jobject proceedConstructor(JavaObjectConstructor* cons, jobject _args, - jclass Clazz, jint index) +static JavaObject* proceedConstructor(JavaObjectConstructor* cons, + JavaArray* args, + JavaObject* Clazz, jint index) __attribute__ ((noinline)); -static jobject proceedConstructor(JavaObjectConstructor* cons, jobject _args, - jclass Clazz, jint index) { - jobject res = 0; +static JavaObject* proceedConstructor(JavaObjectConstructor* cons, + JavaArray* args, + JavaObject* Clazz, jint index) { + JavaObject* res = 0; + JavaObject* excp = 0; + + llvm_gcroot(cons, 0); + llvm_gcroot(args, 0); + llvm_gcroot(Clazz, 0); + llvm_gcroot(res, 0); + llvm_gcroot(excp, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); JavaMethod* meth = cons->getInternalMethod(); UserClass* cl = cons->getClass(); - JavaArray* args = (JavaArray*)_args; sint32 nbArgs = args ? args->size : 0; Signdef* sign = meth->getSignature(); sint32 size = sign->nbArguments; @@ -90,13 +103,11 @@ // Do it after alloca if (nbArgs == size) { - UserCommonClass* _cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Clazz, false); + UserCommonClass* _cl = UserCommonClass::resolvedImplClass(vm, Clazz, false); UserClass* cl = _cl->asClass(); if (cl) { cl->initialiseClass(vm); - JavaObject* obj = cl->doNew(vm); - res = (jobject) obj; + res = cl->doNew(vm); JavaObject** ptr = (JavaObject**)(void*)(args->elements); Typedef* const* arguments = sign->getArgumentsType(); @@ -105,10 +116,9 @@ ptr[i]->decapsulePrimitive(vm, buf, arguments[i]); } - JavaObject* excp = 0; JavaThread* th = JavaThread::get(); try { - meth->invokeIntSpecialBuf(vm, cl, obj, startBuf); + meth->invokeIntSpecialBuf(vm, cl, res, startBuf); } catch(...) { excp = th->getJavaException(); if (excp->getClass()->isAssignableFrom(vm->upcalls->newException)) { @@ -132,18 +142,23 @@ return res; } -JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_constructNative( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Constructor_constructNative( #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectConstructor* cons, jobject _args, jclass Clazz, jint index) { +JavaObjectConstructor* cons, JavaArray* args, JavaObject* Clazz, jint index) { - jobject res = 0; + JavaObject* res = 0; + + llvm_gcroot(res, 0); + llvm_gcroot(cons, 0); + llvm_gcroot(args, 0); + llvm_gcroot(Clazz, 0); BEGIN_NATIVE_EXCEPTION(0) // Proceed in another function because we are using alloca. - res = proceedConstructor(cons, _args, Clazz, index); + res = proceedConstructor(cons, args, Clazz, index); END_NATIVE_EXCEPTION @@ -151,13 +166,16 @@ } JNIEXPORT -jobjectArray JNICALL Java_java_lang_reflect_Constructor_getExceptionTypes( +ArrayObject* JNICALL Java_java_lang_reflect_Constructor_getExceptionTypes( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectConstructor* cons) { - jobjectArray res = 0; + ArrayObject* res = 0; + + llvm_gcroot(res, 0); + llvm_gcroot(cons, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -166,27 +184,30 @@ JavaMethod* meth = cons->getInternalMethod(); JnjvmClassLoader* loader = cl->classLoader; - res = (jobjectArray)meth->getExceptionTypes(loader); + res = (ArrayObject*)meth->getExceptionTypes(loader); END_NATIVE_EXCEPTION return res; } -JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_getSignature( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Constructor_getSignature( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectConstructor* Meth) { - jobject result = 0; + JavaObject* result = 0; + + llvm_gcroot(result, 0); + llvm_gcroot(Meth, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Meth); JavaMethod* meth = Meth->getInternalMethod(); Jnjvm* vm = JavaThread::get()->getJVM(); - result = (jobject)(vm->internalUTF8ToStr(meth->type)); + result = vm->internalUTF8ToStr(meth->type); END_NATIVE_EXCEPTION Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathField.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathField.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathField.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathField.inc Mon Jul 20 12:07:01 2009 @@ -27,6 +27,8 @@ JavaObjectField* Field) { jint res = 0; + llvm_gcroot(Field, 0); + BEGIN_NATIVE_EXCEPTION(0) JavaField* field = Field->getInternalField(); @@ -37,13 +39,16 @@ return res; } -JNIEXPORT jclass JNICALL Java_java_lang_reflect_Field_getType( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Field_getType( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectField* Field) { - jclass res = 0; + JavaObject* res = 0; + + llvm_gcroot(Field, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -52,7 +57,7 @@ JavaField* field = Field->getInternalField(); JnjvmClassLoader* loader = cl->classLoader; UserCommonClass* fieldCl = field->getSignature()->assocClass(loader); - res = (jclass)fieldCl->getClassDelegatee(vm); + res = fieldCl->getClassDelegatee(vm); END_NATIVE_EXCEPTION @@ -63,37 +68,40 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jint res = 0; + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); + BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); const Typedef* type = field->getSignature(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isInt()) - res = (sint32)field->getInt32Field(Obj); + res = (sint32)field->getInt32Field(stat ? StatPtr : obj); else if (prim->isChar()) - res = (uint32)field->getInt16Field(Obj); + res = (uint32)field->getInt16Field(stat ? StatPtr : obj); else if (prim->isByte()) - res = (sint32)field->getInt8Field(Obj); + res = (sint32)field->getInt8Field(stat ? StatPtr : obj); else if (prim->isShort()) - res = (sint32)field->getInt16Field(Obj); + res = (sint32)field->getInt16Field(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -110,23 +118,26 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jlong res = 0; + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); @@ -134,15 +145,15 @@ const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isInt()) - res = (sint64)field->getInt32Field(Obj); + res = (sint64)field->getInt32Field(stat ? StatPtr : obj); else if (prim->isChar()) - res = (uint64)field->getInt16Field(Obj); + res = (uint64)field->getInt16Field(stat ? StatPtr : obj); else if (prim->isByte()) - res = (sint64)field->getInt8Field(Obj); + res = (sint64)field->getInt8Field(stat ? StatPtr : obj); else if (prim->isShort()) - res = (sint64)field->getInt16Field(Obj); + res = (sint64)field->getInt16Field(stat ? StatPtr : obj); else if (prim->isLong()) - res = (sint64)field->getLongField(Obj); + res = (sint64)field->getLongField(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -158,30 +169,33 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jboolean res = 0; + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); - - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + bool stat = isStatic(field->access); + void* StatPtr = 0; + + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool()) - res = (uint8)field->getInt8Field(Obj); + res = (uint8)field->getInt8Field(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -198,41 +212,43 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jfloat res = 0; + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isByte()) - res = (jfloat)field->getInt8Field(Obj); + res = (jfloat)field->getInt8Field(stat ? StatPtr : obj); else if (prim->isInt()) - res = (jfloat)field->getInt32Field(Obj); + res = (jfloat)field->getInt32Field(stat ? StatPtr : obj); else if (prim->isShort()) - res = (jfloat)field->getInt16Field(Obj); + res = (jfloat)field->getInt16Field(stat ? StatPtr : obj); else if (prim->isLong()) - res = (jfloat)field->getLongField(Obj); + res = (jfloat)field->getLongField(stat ? StatPtr : obj); else if (prim->isChar()) // Cast to uint32 because char is unsigned. - res = (jfloat)(uint32)field->getInt16Field(Obj); + res = (jfloat)(uint32)field->getInt16Field(stat ? StatPtr : obj); else if (prim->isFloat()) - res = (jfloat)field->getFloatField(Obj); + res = (jfloat)field->getFloatField(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -248,30 +264,32 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jbyte res = 0; + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isByte()) - res = (sint8)field->getInt8Field(Obj); + res = (sint8)field->getInt8Field(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -287,31 +305,32 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jchar res = 0; + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) - Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isChar()) - res = (uint16)field->getInt16Field(Obj); + res = (uint16)field->getInt16Field(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -328,33 +347,35 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jshort res = 0; + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isShort()) - res = (sint16)field->getInt16Field(Obj); + res = (sint16)field->getInt16Field(stat ? StatPtr : obj); else if (prim->isByte()) - res = (sint16)field->getInt8Field(Obj); + res = (sint16)field->getInt8Field(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -370,42 +391,44 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj) { +JavaObjectField* Field, JavaObject* obj) { jdouble res = 0; + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isByte()) - res = (jdouble)(sint64)field->getInt8Field(Obj); + res = (jdouble)(sint64)field->getInt8Field(stat ? StatPtr : obj); else if (prim->isInt()) - res = (jdouble)(sint64)field->getInt32Field(Obj); + res = (jdouble)(sint64)field->getInt32Field(stat ? StatPtr : obj); else if (prim->isShort()) - res = (jdouble)(sint64)field->getInt16Field(Obj); + res = (jdouble)(sint64)field->getInt16Field(stat? StatPtr : obj); else if (prim->isLong()) - res = (jdouble)(sint64)field->getLongField(Obj); + res = (jdouble)(sint64)field->getLongField(stat? StatPtr : obj); else if (prim->isChar()) - res = (jdouble)(uint64)field->getInt16Field(Obj); + res = (jdouble)(uint64)field->getInt16Field(stat ? StatPtr : obj); else if (prim->isFloat()) - res = (jdouble)field->getFloatField(Obj); + res = (jdouble)field->getFloatField(stat ? StatPtr : obj); else if (prim->isDouble()) - res = (jdouble)field->getDoubleField(Obj); + res = (jdouble)field->getDoubleField(stat ? StatPtr : obj); else vm->illegalArgumentException("wrong type"); } else { @@ -417,135 +440,138 @@ return res; } -JNIEXPORT jobject JNICALL Java_java_lang_reflect_Field_get( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Field_get( #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject _obj) { +JavaObjectField* Field, JavaObject* obj) { - jobject result = 0; + JavaObject* res = 0; + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)_obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } - JavaObject* res = 0; const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool()) { - uint8 val = field->getInt8Field(Obj); + uint8 val = field->getInt8Field(stat ? StatPtr : obj); res = vm->upcalls->boolClass->doNew(vm); vm->upcalls->boolValue->setInt8Field(res, val); } else if (prim->isByte()) { - sint8 val = field->getInt8Field(Obj); + sint8 val = field->getInt8Field(stat ? StatPtr : obj); res = vm->upcalls->byteClass->doNew(vm); vm->upcalls->byteValue->setInt8Field(res, val); } else if (prim->isChar()) { - uint16 val = field->getInt16Field(Obj); + uint16 val = field->getInt16Field(stat ? StatPtr : obj); res = vm->upcalls->charClass->doNew(vm); vm->upcalls->charValue->setInt16Field(res, val); } else if (prim->isShort()) { - sint16 val = field->getInt16Field(Obj); + sint16 val = field->getInt16Field(stat ? StatPtr : obj); res = vm->upcalls->shortClass->doNew(vm); vm->upcalls->shortValue->setInt16Field(res, val); } else if (prim->isInt()) { - sint32 val = field->getInt32Field(Obj); + sint32 val = field->getInt32Field(stat ? StatPtr : obj); res = vm->upcalls->intClass->doNew(vm); vm->upcalls->intValue->setInt32Field(res, val); } else if (prim->isLong()) { - sint64 val = field->getLongField(Obj); + sint64 val = field->getLongField(stat ? StatPtr : obj); res = vm->upcalls->longClass->doNew(vm); vm->upcalls->longValue->setLongField(res, val); } else if (prim->isFloat()) { - float val = field->getFloatField(Obj); + float val = field->getFloatField(stat ? StatPtr : obj); res = vm->upcalls->floatClass->doNew(vm); vm->upcalls->floatValue->setFloatField(res, val); } else if (prim->isDouble()) { - double val = field->getDoubleField(Obj); + double val = field->getDoubleField(stat ? StatPtr : obj); res = vm->upcalls->doubleClass->doNew(vm); vm->upcalls->doubleValue->setDoubleField(res, val); } } else { - res = field->getObjectField(Obj); + res = field->getObjectField(stat ? StatPtr : obj); } - result = (jobject) res; - END_NATIVE_EXCEPTION - return (jobject)result; + return res; } JNIEXPORT void JNICALL Java_java_lang_reflect_Field_set( #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jobject val) { +JavaObjectField* Field, JavaObject* obj, JavaObject* val) { + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); + llvm_gcroot(val, 0); + + BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); - uintptr_t buf = (uintptr_t)alloca(sizeof(uint64)); + uint64_t buf = 0; + bool stat = isStatic(field->access); + void* StatPtr = 0; - // Do it after alloca - BEGIN_NATIVE_EXCEPTION(0) - void* _buf = (void*)buf; - const Typedef* type = field->getSignature(); - ((JavaObject*)val)->decapsulePrimitive(vm, buf, type); - - - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } + + void* _buf = (void*)(&buf); + uintptr_t __buf = (uintptr_t)&buf; + const Typedef* type = field->getSignature(); + val->decapsulePrimitive(vm, __buf, type); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool()) - field->setInt8Field(Obj, ((uint8*)_buf)[0]); + field->setInt8Field(stat ? StatPtr : obj, ((uint8*)_buf)[0]); else if (prim->isByte()) - field->setInt8Field(Obj, ((sint8*)_buf)[0]); + field->setInt8Field(stat ? StatPtr : obj, ((sint8*)_buf)[0]); else if (prim->isChar()) - field->setInt16Field(Obj, ((uint16*)_buf)[0]); + field->setInt16Field(stat ? StatPtr : obj, ((uint16*)_buf)[0]); else if (prim->isShort()) - field->setInt16Field(Obj, ((sint16*)_buf)[0]); + field->setInt16Field(stat ? StatPtr : obj, ((sint16*)_buf)[0]); else if (prim->isInt()) - field->setInt32Field(Obj, ((sint32*)_buf)[0]); + field->setInt32Field(stat ? StatPtr : obj, ((sint32*)_buf)[0]); else if (prim->isLong()) - field->setLongField(Obj, ((sint64*)_buf)[0]); + field->setLongField(stat ? StatPtr : obj, ((sint64*)_buf)[0]); else if (prim->isFloat()) - field->setFloatField(Obj, ((float*)_buf)[0]); + field->setFloatField(stat ? StatPtr : obj, ((float*)_buf)[0]); else if (prim->isDouble()) - field->setDoubleField(Obj, ((double*)_buf)[0]); + field->setDoubleField(stat ? StatPtr : obj, ((double*)_buf)[0]); } else { - field->setObjectField(Obj, ((JavaObject**)_buf)[0]); + field->setObjectField(stat ? StatPtr : obj, val); } END_NATIVE_EXCEPTION @@ -555,28 +581,31 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jboolean val) { +JavaObjectField* Field, JavaObject* obj, jboolean val) { + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool()) - field->setInt8Field(Obj, (uint8)val); + field->setInt8Field(stat ? StatPtr : obj, (uint8)val); else vm->illegalArgumentException("wrong type"); } else { @@ -591,38 +620,41 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jbyte val) { +JavaObjectField* Field, JavaObject* obj, jbyte val) { + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isByte()) - field->setInt8Field(Obj, (sint8)val); + field->setInt8Field(stat ? StatPtr : obj, (sint8)val); else if (prim->isShort()) - field->setInt16Field(Obj, (sint16)val); + field->setInt16Field(stat ? StatPtr : obj, (sint16)val); else if (prim->isInt()) - field->setInt32Field(Obj, (sint32)val); + field->setInt32Field(stat ? StatPtr : obj, (sint32)val); else if (prim->isLong()) - field->setLongField(Obj, (sint64)val); + field->setLongField(stat ? StatPtr : obj, (sint64)val); else if (prim->isFloat()) - field->setFloatField(Obj, (float)val); + field->setFloatField(stat ? StatPtr : obj, (float)val); else if (prim->isDouble()) - field->setDoubleField(Obj, (double)val); + field->setDoubleField(stat ? StatPtr : obj, (double)val); else vm->illegalArgumentException("wrong type"); } else { @@ -636,35 +668,38 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jchar val) { +JavaObjectField* Field, JavaObject* obj, jchar val) { + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isChar()) - field->setInt16Field(Obj, (uint16)val); + field->setInt16Field(stat ? StatPtr : obj, (uint16)val); else if (prim->isInt()) - field->setInt32Field(Obj, (uint32)val); + field->setInt32Field(stat ? StatPtr : obj, (uint32)val); else if (prim->isLong()) - field->setLongField(Obj, (uint64)val); + field->setLongField(stat ? StatPtr : obj, (uint64)val); else if (prim->isFloat()) - field->setFloatField(Obj, (float)(uint32)val); + field->setFloatField(stat ? StatPtr : obj, (float)(uint32)val); else if (prim->isDouble()) - field->setDoubleField(Obj, (double)(uint64)val); + field->setDoubleField(stat ? StatPtr : obj, (double)(uint64)val); else vm->illegalArgumentException("wrong type"); } else { @@ -678,36 +713,39 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jshort val) { +JavaObjectField* Field, JavaObject* obj, jshort val) { + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isShort()) - field->setInt16Field(Obj, (sint16)val); + field->setInt16Field(stat ? StatPtr : obj, (sint16)val); else if (prim->isInt()) - field->setInt32Field(Obj, (sint32)val); + field->setInt32Field(stat ? StatPtr : obj, (sint32)val); else if (prim->isLong()) - field->setLongField(Obj, (sint64)val); + field->setLongField(stat ? StatPtr : obj, (sint64)val); else if (prim->isFloat()) - field->setFloatField(Obj, (float)val); + field->setFloatField(stat ? StatPtr : obj, (float)val); else if (prim->isDouble()) - field->setDoubleField(Obj, (double)val); + field->setDoubleField(stat ? StatPtr : obj, (double)val); else vm->illegalArgumentException("wrong type"); } else { @@ -721,34 +759,37 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jint val) { +JavaObjectField* Field, JavaObject* obj, jint val) { + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isInt()) - field->setInt32Field(Obj, (sint32)val); + field->setInt32Field(stat ? StatPtr : obj, (sint32)val); else if (prim->isLong()) - field->setLongField(Obj, (sint64)val); + field->setLongField(stat ? StatPtr : obj, (sint64)val); else if (prim->isFloat()) - field->setFloatField(Obj, (float)val); + field->setFloatField(stat ? StatPtr : obj, (float)val); else if (prim->isDouble()) - field->setDoubleField(Obj, (double)val); + field->setDoubleField(stat ? StatPtr : obj, (double)val); else vm->illegalArgumentException("wrong type"); } else { @@ -762,32 +803,35 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jlong val) { +JavaObjectField* Field, JavaObject* obj, jlong val) { + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isLong()) - field->setLongField(Obj, (sint64)val); + field->setLongField(stat ? StatPtr : obj, (sint64)val); else if (prim->isFloat()) - field->setFloatField(Obj, (float)val); + field->setFloatField(stat ? StatPtr : obj, (float)val); else if (prim->isDouble()) - field->setDoubleField(Obj, (double)val); + field->setDoubleField(stat ? StatPtr : obj, (double)val); else vm->illegalArgumentException("wrong type"); } else { @@ -801,31 +845,33 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectField* Field, jobject obj, jfloat val) { +JavaObjectField* Field, JavaObject* obj, jfloat val) { + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isFloat()) - field->setFloatField(Obj, (float)val); + field->setFloatField(stat ? StatPtr : obj, (float)val); else if (prim->isDouble()) - field->setDoubleField(Obj, (double)val); + field->setDoubleField(stat ? StatPtr : obj, (double)val); else vm->illegalArgumentException("wrong type"); } else { @@ -840,27 +886,30 @@ JNIEnv *env, #endif JavaObjectField* Field, JavaObject* obj, jdouble val) { + + llvm_gcroot(Field, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = Field->getClass(); JavaField* field = Field->getInternalField(); + bool stat = isStatic(field->access); + void* StatPtr = 0; - void* Obj = (void*)obj; - - if (isStatic(field->access)) { + if (stat) { cl->initialiseClass(vm); - Obj = cl->getStaticInstance(); + StatPtr = cl->getStaticInstance(); } else { - verifyNull(Obj); + verifyNull(obj); } const Typedef* type = field->getSignature(); if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isDouble()) - field->setDoubleField(Obj, (double)val); + field->setDoubleField(stat ? StatPtr : obj, (double)val); else vm->illegalArgumentException("wrong type"); } else { @@ -876,6 +925,10 @@ JNIEnv *env, #endif JavaObject* Unsafe, JavaObjectField* Field) { + + llvm_gcroot(Field, 0); + llvm_gcroot(Unsafe, 0); + JavaField* field = Field->getInternalField(); return (jlong)field->ptrOffset; } Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.inc Mon Jul 20 12:07:01 2009 @@ -32,6 +32,7 @@ JavaObjectMethod* Meth) { jint res = 0; + llvm_gcroot(Meth, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -43,20 +44,22 @@ return res; } -JNIEXPORT jclass JNICALL Java_java_lang_reflect_Method_getReturnType( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Method_getReturnType( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectMethod* Meth) { - jclass res = 0; + JavaObject* res = 0; + llvm_gcroot(Meth, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) UserClass* cl = Meth->getClass(); JavaMethod* meth = Meth->getInternalMethod(); JnjvmClassLoader* loader = cl->classLoader; - res = (jclass)meth->getReturnType(loader); + res = meth->getReturnType(loader); END_NATIVE_EXCEPTION @@ -64,13 +67,15 @@ } -JNIEXPORT jobject JNICALL Java_java_lang_reflect_Method_getParameterTypes( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Method_getParameterTypes( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectMethod* Meth) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(Meth, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -78,38 +83,44 @@ JavaMethod* meth = Meth->getInternalMethod(); JnjvmClassLoader* loader = cl->classLoader; - res = (jobject)(meth->getParameterTypes(loader)); + res = (meth->getParameterTypes(loader)); END_NATIVE_EXCEPTION return res; } -static jobject proceedMethod(JavaObjectMethod* Meth, jobject _obj, - jobject _args, jclass Cl, jint index) +static JavaObject* proceedMethod(JavaObjectMethod* Meth, JavaObject* obj, + JavaArray* args, JavaObject* Cl, jint index) __attribute__((noinline)); -static jobject proceedMethod(JavaObjectMethod* Meth, jobject _obj, - jobject _args, jclass Cl, jint index) { +static JavaObject* proceedMethod(JavaObjectMethod* Meth, JavaObject* obj, + JavaArray* args, JavaObject* Cl, jint index) { JavaObject* res = 0; + JavaObject* exc = 0; + + llvm_gcroot(res, 0); + llvm_gcroot(Meth, 0); + llvm_gcroot(obj, 0); + llvm_gcroot(args, 0); + llvm_gcroot(Cl, 0); + llvm_gcroot(exc, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); JavaMethod* meth = Meth->getInternalMethod(); - JavaArray* args = (JavaArray*)_args; sint32 nbArgs = args ? args->size : 0; Signdef* sign = meth->getSignature(); sint32 size = sign->nbArguments; - JavaObject* obj = (JavaObject*)_obj; uintptr_t buf = size ? (uintptr_t)alloca(size * sizeof(uint64)) : 0; void* _buf = (void*)buf; if (nbArgs == size) { - UserCommonClass* _cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false); + UserCommonClass* _cl = UserCommonClass::resolvedImplClass(vm, Cl, false); UserClass* cl = (UserClass*)_cl; if (isVirtual(meth->access)) { @@ -136,20 +147,19 @@ ptr[i]->decapsulePrimitive(vm, buf, arguments[i]); } - JavaObject* exc = 0; JavaThread* th = JavaThread::get(); -#define RUN_METH(TYPE) \ +#define RUN_METH(TYPE, VAR) \ try{ \ if (isVirtual(meth->access)) { \ if (isPublic(meth->access) && !isFinal(meth->access) && \ !isFinal(meth->classDef->access)) { \ - val = meth->invoke##TYPE##VirtualBuf(vm, cl, obj, _buf); \ + VAR = meth->invoke##TYPE##VirtualBuf(vm, cl, obj, _buf); \ } else { \ - val = meth->invoke##TYPE##SpecialBuf(vm, cl, obj, _buf); \ + VAR = meth->invoke##TYPE##SpecialBuf(vm, cl, obj, _buf); \ } \ } else { \ - val = meth->invoke##TYPE##StaticBuf(vm, cl, _buf); \ + VAR = meth->invoke##TYPE##StaticBuf(vm, cl, _buf); \ } \ } catch(...) { \ exc = th->getJavaException(); \ @@ -167,87 +177,92 @@ if (prim->isVoid()) { res = 0; uint32 val = 0; - RUN_METH(Int); + RUN_METH(Int, val); } else if (prim->isBool()) { uint32 val = 0; - RUN_METH(Int); + RUN_METH(Int, val); res = vm->upcalls->boolClass->doNew(vm); vm->upcalls->boolValue->setInt8Field(res, val); } else if (prim->isByte()) { uint32 val = 0; - RUN_METH(Int); + RUN_METH(Int, val); res = vm->upcalls->byteClass->doNew(vm); vm->upcalls->byteValue->setInt8Field(res, val); } else if (prim->isChar()) { uint32 val = 0; - RUN_METH(Int); + RUN_METH(Int, val); res = vm->upcalls->charClass->doNew(vm); vm->upcalls->charValue->setInt16Field(res, val); } else if (prim->isShort()) { uint32 val = 0; - RUN_METH(Int); + RUN_METH(Int, val); res = vm->upcalls->shortClass->doNew(vm); vm->upcalls->shortValue->setInt16Field(res, val); } else if (prim->isInt()) { uint32 val = 0; - RUN_METH(Int); + RUN_METH(Int, val); res = vm->upcalls->intClass->doNew(vm); vm->upcalls->intValue->setInt32Field(res, val); } else if (prim->isLong()) { sint64 val = 0; - RUN_METH(Long); + RUN_METH(Long, val); res = vm->upcalls->longClass->doNew(vm); vm->upcalls->longValue->setLongField(res, val); } else if (prim->isFloat()) { float val = 0; - RUN_METH(Float); + RUN_METH(Float, val); res = vm->upcalls->floatClass->doNew(vm); vm->upcalls->floatValue->setFloatField(res, val); } else if (prim->isDouble()) { double val = 0; - RUN_METH(Double); + RUN_METH(Double, val); res = vm->upcalls->doubleClass->doNew(vm); vm->upcalls->doubleValue->setDoubleField(res, val); } } else { - JavaObject* val = 0; - RUN_METH(JavaObject); - res = val; + RUN_METH(JavaObject, res); } } else { vm->illegalArgumentException("wrong number of arguments"); } - return (jobject)res; + return res; } #undef RUN_METH -JNIEXPORT jobject JNICALL Java_java_lang_reflect_Method_invokeNative( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Method_invokeNative( #ifdef NATIVE_JNI JNIEnv *env, #endif -JavaObjectMethod* Meth, jobject _obj, jobject _args, jclass Cl, jint index) { +JavaObjectMethod* Meth, JavaObject* obj, JavaArray* args, JavaObject* Cl, jint index) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(Meth, 0); + llvm_gcroot(obj, 0); + llvm_gcroot(args, 0); + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) // Create a new function because we use alloca. - res = proceedMethod(Meth, _obj, _args, Cl, index); + res = proceedMethod(Meth, obj, args, Cl, index); END_NATIVE_EXCEPTION - return (jobject) res; + return res; } -JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_Method_getExceptionTypes( +JNIEXPORT ArrayObject* JNICALL Java_java_lang_reflect_Method_getExceptionTypes( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectMethod* Meth) { - jobjectArray res = 0; + ArrayObject* res = 0; + llvm_gcroot(Meth, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -255,27 +270,29 @@ UserClass* cl = Meth->getClass(); JavaMethod* meth = Meth->getInternalMethod(); JnjvmClassLoader* loader = cl->classLoader; - res = (jobjectArray)meth->getExceptionTypes(loader); + res = meth->getExceptionTypes(loader); END_NATIVE_EXCEPTION return res; } -JNIEXPORT jobject JNICALL Java_java_lang_reflect_Method_getSignature( +JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_Method_getSignature( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectMethod* Meth) { - jobject result = 0; + JavaObject* result = 0; + llvm_gcroot(Meth, 0); + llvm_gcroot(result, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Meth); JavaMethod* meth = Meth->getInternalMethod(); Jnjvm* vm = JavaThread::get()->getJVM(); - result = (jobject)(vm->internalUTF8ToStr(meth->type)); + result = vm->internalUTF8ToStr(meth->type); END_NATIVE_EXCEPTION Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.inc Mon Jul 20 12:07:01 2009 @@ -31,15 +31,17 @@ JNIEnv *env, jclass clazz, #endif -jobject klass) { +JavaObjectClass* klass) { - UserCommonClass* cl = ((JavaObjectClass*)klass)->getClass(); + llvm_gcroot(klass, 0); + + UserCommonClass* cl = klass->getClass(); return cl->isArray(); } -JNIEXPORT jclass JNICALL Java_java_lang_VMClass_forName( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_forName( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, @@ -48,7 +50,10 @@ jboolean clinit, JavaObject* loader) { - jclass res = 0; + JavaObject* res = 0; + llvm_gcroot(loader, 0); + llvm_gcroot(str, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -62,7 +67,7 @@ if (clinit && cl->asClass()) { cl->asClass()->initialiseClass(vm); } - res =(jclass)(cl->getClassDelegatee(vm)); + res =cl->getClassDelegatee(vm); } else { vm->classNotFoundException(str); } @@ -72,26 +77,29 @@ return res; } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredConstructors( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredConstructors( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl, +JavaObject* Cl, jboolean publicOnly) { - jobject result = 0; + ArrayObject* ret = 0; + JavaObject* tmp = 0; + llvm_gcroot(Cl, 0); + llvm_gcroot(ret, 0); + llvm_gcroot(tmp, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); if (cl->isArray() || cl->isInterface() || cl->isPrimitive()) { - result = (jobject)vm->upcalls->constructorArrayClass->doNew(0, vm); + ret = (ArrayObject*)vm->upcalls->constructorArrayClass->doNew(0, vm); } else { - UserClass* realCl = (Class*)cl; + UserClass* realCl = cl->asClass();; JnjvmClassLoader* classLoader = cl->classLoader; uint32 size = 0; @@ -104,9 +112,8 @@ } } + ret = (ArrayObject*)vm->upcalls->constructorArrayClass->doNew(size, vm); - ArrayObject* ret = - (ArrayObject*)vm->upcalls->constructorArrayClass->doNew(size, vm); sint32 index = 0; for (uint32 i = 0; i < realCl->nbVirtualMethods; ++i) { JavaMethod* meth = &realCl->virtualMethods[i]; @@ -114,40 +121,44 @@ if (meth->name->equals(classLoader->bootstrapLoader->initName) && (!publicOnly || pub)) { UserClass* Cons = vm->upcalls->newConstructor; - JavaObject* tmp = Cons->doNew(vm); + tmp = Cons->doNew(vm); vm->upcalls->initConstructor->invokeIntSpecial(vm, Cons, tmp, Cl, i); ret->elements[index++] = tmp; } } - result = (jobject)ret; } END_NATIVE_EXCEPTION - return result; + return ret; } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredMethods( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredMethods( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl, +JavaObject* Cl, jboolean publicOnly) { - jobject result = 0; + ArrayObject* ret = 0; + JavaObject* tmp = 0; + JavaString* str = 0; + llvm_gcroot(Cl, 0); + llvm_gcroot(ret, 0); + llvm_gcroot(tmp, 0); + llvm_gcroot(str, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); Classpath* upcalls = vm->upcalls; if (cl->isArray() || cl->isPrimitive()) { - result = (jobject)upcalls->methodArrayClass->doNew(0, vm); + ret = (ArrayObject*)upcalls->methodArrayClass->doNew(0, vm); } else { - UserClass* realCl = (Class*)cl; + UserClass* realCl = cl->asClass(); JnjvmClassLoader* classLoader = cl->classLoader; uint32 size = 0; @@ -162,7 +173,7 @@ } - ArrayObject* ret = (ArrayObject*)upcalls->methodArrayClass->doNew(size, vm); + ret = (ArrayObject*)upcalls->methodArrayClass->doNew(size, vm); sint32 index = 0; for (uint32 i = 0; i < realCl->nbVirtualMethods + realCl->nbStaticMethods; @@ -173,18 +184,17 @@ (!publicOnly || pub)) { // TODO: check parameter types UserClass* Meth = vm->upcalls->newMethod; - JavaObject* tmp = Meth->doNew(vm); - JavaString* str = vm->internalUTF8ToStr(meth->name); + tmp = Meth->doNew(vm); + str = vm->internalUTF8ToStr(meth->name); upcalls->initMethod->invokeIntSpecial(vm, Meth, tmp, Cl, str, i); ret->elements[index++] = tmp; } } - result = (jobject)ret; } END_NATIVE_EXCEPTION - return result; + return ret; } JNIEXPORT jint JNICALL Java_java_lang_VMClass_getModifiers( @@ -192,38 +202,40 @@ JNIEnv *env, jclass clazz, #endif -jclass Cl, +JavaObject* Cl, jboolean ignore) { jint res = 0; + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); res = cl->getAccess(); END_NATIVE_EXCEPTION return res; } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getName( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getName( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject Cl) { +JavaObject* Cl) { - jobject result = 0; + JavaObject* result = 0; + llvm_gcroot(Cl, 0); + llvm_gcroot(result, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = ((JavaObjectClass*)Cl)->getClass(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); const UTF8* iname = cl->getName(); - result = (jobject)JavaString::internalToJava(iname, vm); + result = JavaString::internalToJava(iname, vm); END_NATIVE_EXCEPTION @@ -235,12 +247,15 @@ JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { jboolean res = 0; + llvm_gcroot(Cl, 0); + BEGIN_NATIVE_EXCEPTION(0) - UserCommonClass* cl = ((JavaObjectClass*)Cl)->getClass(); + Jnjvm* vm = JavaThread::get()->getJVM(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); res = cl->isPrimitive(); @@ -254,15 +269,15 @@ JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { jboolean res = 0; + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); res = cl->isInterface(); @@ -271,23 +286,26 @@ return res; } -JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getComponentType( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getComponentType( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { - jclass res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(Cl, 0); + BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = ((JavaObjectClass*)Cl)->getClass(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); if (cl->isArray()) { - UserCommonClass* bc = ((UserClassArray*)cl)->baseClass(); - res = (jclass)(bc->getClassDelegatee(vm)); + UserCommonClass* bc = cl->asArrayClass()->baseClass(); + res = bc->getClassDelegatee(vm); } else { res = 0; } @@ -296,19 +314,22 @@ return res; } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getClassLoader( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getClassLoader( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) - UserCommonClass* cl = ((JavaObjectClass*)Cl)->getClass(); - res = (jobject)cl->classLoader->getJavaClassLoader(); + Jnjvm* vm = JavaThread::get()->getJVM(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); + res = cl->classLoader->getJavaClassLoader(); END_NATIVE_EXCEPTION @@ -320,19 +341,20 @@ JNIEnv *env, jclass clazz, #endif -jclass Cl1, jclass Cl2) { +JavaObject* Cl1, JavaObject* Cl2) { jboolean res = 0; + llvm_gcroot(Cl1, 0); + llvm_gcroot(Cl2, 0); BEGIN_NATIVE_EXCEPTION(0) - if (!Cl2) JavaThread::get()->getJVM()->nullPointerException(); + Jnjvm* vm = JavaThread::get()->getJVM(); + if (!Cl2) vm->nullPointerException(); - UserCommonClass* cl1 = ((JavaObjectClass*)Cl1)->getClass(); - UserCommonClass* cl2 = ((JavaObjectClass*)Cl2)->getClass(); + UserCommonClass* cl1 = UserCommonClass::resolvedImplClass(vm, Cl1, false); + UserCommonClass* cl2 = UserCommonClass::resolvedImplClass(vm, Cl2, false); - if (cl1->isClass()) cl1->asClass()->resolveClass(); - if (cl2->asClass()) cl2->asClass()->resolveClass(); res = cl2->isAssignableFrom(cl1); END_NATIVE_EXCEPTION @@ -341,23 +363,24 @@ } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getSuperclass( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getSuperclass( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(Cl, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = ((JavaObjectClass*)Cl)->getClass(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); if (cl->isInterface()) res = 0; else { - if (cl->asClass()) cl->asClass()->resolveClass(); - if (cl->getSuper()) res = (jobject)cl->getSuper()->getClassDelegatee(vm); + if (cl->getSuper()) res = cl->getSuper()->getClassDelegatee(vm); else res = 0; } @@ -371,91 +394,100 @@ JNIEnv *env, jclass clazz, #endif -jclass Cl, jobject obj) { +JavaObject* Cl, JavaObject* obj) { bool res = false; + llvm_gcroot(Cl, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) - UserCommonClass* cl = ((JavaObjectClass*)Cl)->getClass(); - res = ((JavaObject*)obj)->instanceOf(cl); + Jnjvm* vm = JavaThread::get()->getJVM(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); + res = obj->instanceOf(cl); END_NATIVE_EXCEPTION return res; } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredFields( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredFields( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl, jboolean publicOnly) { +JavaObject* Cl, jboolean publicOnly) { - jobject result = 0; + ArrayObject* ret = 0; + JavaObject* tmp = 0; + JavaString* name = 0; + llvm_gcroot(Cl, 0); + llvm_gcroot(ret, 0); + llvm_gcroot(tmp, 0); + llvm_gcroot(name, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false)->asClass(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); - if (!cl) { - result = (jobject)vm->upcalls->fieldArrayClass->doNew(0, vm); + if (!cl->isClass()) { + ret = (ArrayObject*)vm->upcalls->fieldArrayClass->doNew(0, vm); } else { - + UserClass* realCl = cl->asClass(); uint32 size = 0; - for (uint32 i = 0; i < cl->nbVirtualFields + cl->nbStaticFields; ++i) { - JavaField* field = &cl->virtualFields[i]; + for (uint32 i = 0; i < realCl->nbVirtualFields + realCl->nbStaticFields; + ++i) { + JavaField* field = &realCl->virtualFields[i]; if (!publicOnly || isPublic(field->access)) { ++size; } } - ArrayObject* ret = - (ArrayObject*)vm->upcalls->fieldArrayClass->doNew(size, vm); + ret = (ArrayObject*)vm->upcalls->fieldArrayClass->doNew(size, vm); + sint32 index = 0; - for (uint32 i = 0; i < cl->nbVirtualFields + cl->nbStaticFields; ++i) { - JavaField* field = &cl->virtualFields[i]; + for (uint32 i = 0; i < realCl->nbVirtualFields + realCl->nbStaticFields; + ++i) { + JavaField* field = &realCl->virtualFields[i]; if (!publicOnly || isPublic(field->access)) { // TODO: check parameter types UserClass* Field = vm->upcalls->newField; - JavaObject* tmp = Field->doNew(vm); - JavaString* name = vm->internalUTF8ToStr(field->name); + tmp = Field->doNew(vm); + name = vm->internalUTF8ToStr(field->name); vm->upcalls->initField->invokeIntSpecial(vm, Field, tmp, Cl, name, i); ret->elements[index++] = tmp; } } - result = (jobject)ret; } END_NATIVE_EXCEPTION - return result; + return ret; } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getInterfaces( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getInterfaces( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { - jobject res = 0; + ArrayObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false); - ArrayObject* ret = - (ArrayObject*)vm->upcalls->classArrayClass->doNew(cl->nbInterfaces, vm); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); + res = (ArrayObject*)vm->upcalls->classArrayClass->doNew(cl->nbInterfaces, vm); + for (uint16 i = 0; i < cl->nbInterfaces; ++i) { UserClass* klass = cl->interfaces[i]; - ret->elements[i] = klass->getClassDelegatee(vm); + res->elements[i] = klass->getClassDelegatee(vm); } - res = (jobject)ret; END_NATIVE_EXCEPTION @@ -463,24 +495,27 @@ } -JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getDeclaringClass( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaringClass( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl) { - jclass res = 0; +JavaObject* Cl) { + JavaObject* res = 0; + + llvm_gcroot(res, 0); + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false)->asClass(); + UserClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false)->asClass(); + if (cl) { cl->resolveInnerOuterClasses(); UserClass* outer = cl->getOuterClass(); if (outer) { - res = (jclass)outer->getClassDelegatee(vm); + res = outer->getClassDelegatee(vm); } } @@ -490,21 +525,22 @@ } -JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredClasses( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredClasses( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl, bool publicOnly) { +JavaObject* Cl, bool publicOnly) { - jobject result = 0; + ArrayObject* result = 0; + llvm_gcroot(result, 0); + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false)->asClass(); + UserClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false)->asClass(); if (cl) { cl->resolveInnerOuterClasses(); UserClassArray* array = vm->upcalls->constructorArrayClass; @@ -520,13 +556,12 @@ sizeArray = cl->nbInnerClasses; } - ArrayObject* res = (ArrayObject*)array->doNew(sizeArray, vm); + result = (ArrayObject*)array->doNew(sizeArray, vm); for (uint16 i = 0; i < cl->nbInnerClasses; ++i) { UserClass* klass = cl->innerClasses[i]; if (!publicOnly || isPublic(klass->innerAccess)) - res->elements[i] = klass->getClassDelegatee(vm); + result->elements[i] = klass->getClassDelegatee(vm); } - result = (jobject)res; } @@ -542,26 +577,31 @@ JNIEnv *env, jclass clazz, #endif -jobject throwable) { +JavaObject* throwable) { + + llvm_gcroot(throwable, 0); + assert(throwable && "Using internal VM throw exception without exception"); JavaThread::get()->pendingException = (JavaObject*)throwable; } -JNIEXPORT jobjectArray Java_java_lang_VMClass_getDeclaredAnnotations( +JNIEXPORT ArrayObject* Java_java_lang_VMClass_getDeclaredAnnotations( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { // TODO implement me - jobjectArray res = 0; + ArrayObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClassArray* array = vm->upcalls->constructorArrayAnnotation; - res = (jobjectArray) array->doNew(0, vm); + res = (ArrayObject*)array->doNew(0, vm); END_NATIVE_EXCEPTION @@ -573,15 +613,15 @@ JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { jboolean res = false; + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - UserClass* cl = - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false)->asClass(); + UserClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false)->asClass(); if (cl) res = cl->isAnonymous; Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc Mon Jul 20 12:07:01 2009 @@ -23,26 +23,28 @@ extern "C" { -JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif jchar byteId) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); UserClassPrimitive* prim = UserClassPrimitive::byteIdToPrimitive(byteId, vm->upcalls); + if (!prim) { fprintf(stderr, "unknown byte primitive %c", byteId); abort(); } - res = (jobject)prim->getClassDelegatee(vm); + res = prim->getClassDelegatee(vm); END_NATIVE_EXCEPTION @@ -50,25 +52,27 @@ } -JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_findLoadedClass( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClassLoader_findLoadedClass( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject loader, -jobject _name) { +JavaObject* loader, +JavaString* name) { - jclass res = 0; + JavaObject* res = 0; + llvm_gcroot(loader, 0); + llvm_gcroot(name, 0); + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - JavaString* name = (JavaString*)_name; JnjvmClassLoader* JCL = - JnjvmClassLoader::getJnjvmLoaderFromJavaObject((JavaObject*)loader, vm); + JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm); UserCommonClass* cl = JCL->lookupClassFromJavaString(name); - if (cl) res = (jclass)(cl->getClassDelegatee(vm)); + if (cl) res = cl->getClassDelegatee(vm); END_NATIVE_EXCEPTION @@ -77,69 +81,72 @@ return 0; } -JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_loadClass( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClassLoader_loadClass( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject _str, +JavaString* str, jboolean doResolve) { - jclass res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(str, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - JavaString* str = (JavaString*)_str; JnjvmClassLoader* JCL = vm->bootstrapLoader; UserCommonClass* cl = JCL->loadClassFromJavaString(str, doResolve, false); - if (cl != 0) - res = (jclass)cl->getClassDelegatee(vm); + if (cl != 0) res = cl->getClassDelegatee(vm); END_NATIVE_EXCEPTION return res; } -JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClassLoader_defineClass( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject loader, -jobject _str, -jobject bytes, +JavaObject* loader, +JavaString* str, +ArrayUInt8* bytes, jint off, jint len, -jobject pd) { +JavaObject* pd) { - jclass res = 0; + JavaObject* res = 0; + llvm_gcroot(loader, 0); + llvm_gcroot(str, 0); + llvm_gcroot(bytes, 0); + llvm_gcroot(pd, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); // Before creating a class, do a check on the bytes. - Reader reader((ArrayUInt8*)bytes); + Reader reader(bytes); uint32 magic = reader.readU4(); if (magic != Jnjvm::Magic) { JavaThread::get()->getJVM()->classFormatError("bad magic number"); } JnjvmClassLoader* JCL = - JnjvmClassLoader::getJnjvmLoaderFromJavaObject((JavaObject*)loader, vm); + JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm); - JavaString* str = (JavaString*)_str; const UTF8* name = str->javaToInternal(JCL->hashUTF8); UserCommonClass* cl = JCL->lookupClass(name); if (!cl) { - UserClass* cl = JCL->constructClass(name, (ArrayUInt8*)bytes); + UserClass* cl = JCL->constructClass(name, bytes); cl->resolveClass(); - res = (jclass)(cl->getClassDelegatee(vm, (JavaObject*)pd)); + res = cl->getClassDelegatee(vm, pd); } else { JavaObject* obj = vm->CreateLinkageError("duplicate class definition"); JavaThread::get()->throwException(obj); @@ -155,13 +162,15 @@ JNIEnv *env, jclass clazz, #endif -jclass Cl) { +JavaObject* Cl) { + + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Cl); Jnjvm* vm = JavaThread::get()->getJVM(); - UserCommonClass::resolvedImplClass(vm, (JavaObject*)Cl, false); + UserCommonClass::resolvedImplClass(vm, Cl, false); END_NATIVE_EXCEPTION } @@ -340,9 +349,11 @@ }; extern "C" ArrayObject* nativeGetBootPackages() { + ArrayObject* obj = 0; + llvm_gcroot(obj, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); - ArrayObject* obj = - (ArrayObject*)vm->upcalls->ArrayOfString->doNew(NUM_BOOT_PACKAGES, vm); + obj = (ArrayObject*)vm->upcalls->ArrayOfString->doNew(NUM_BOOT_PACKAGES, vm); for (uint32 i = 0; i < NUM_BOOT_PACKAGES; ++i) { obj->elements[i] = vm->asciizToStr(bootPackages[i]); } Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMObject.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMObject.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMObject.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMObject.inc Mon Jul 20 12:07:01 2009 @@ -20,18 +20,19 @@ extern "C" { -JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMObject_clone( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject _src) { +JavaObject* src) { JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(src, 0); BEGIN_NATIVE_EXCEPTION(0) - JavaObject* src = (JavaObject*)_src; UserCommonClass* cl = src->getClass(); Jnjvm* vm = JavaThread::get()->getJVM(); uint64 size = 0; @@ -54,23 +55,24 @@ END_NATIVE_EXCEPTION - return (jobject)res; + return res; } -JNIEXPORT jobject JNICALL Java_java_lang_VMObject_getClass( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMObject_getClass( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject _obj) { +JavaObject* obj) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) - JavaObject* obj = (JavaObject*)_obj; Jnjvm* vm = JavaThread::get()->getJVM(); - res = (jobject)(obj->getClass()->getClassDelegatee(vm)); + res = obj->getClass()->getClassDelegatee(vm); END_NATIVE_EXCEPTION @@ -82,11 +84,12 @@ JNIEnv *env, jclass clazz, #endif -jobject _obj) { +JavaObject* obj) { + + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) - JavaObject* obj = (JavaObject*)_obj; obj->notifyAll(); END_NATIVE_EXCEPTION @@ -98,14 +101,15 @@ JNIEnv *env, jclass clazz, #endif -jobject _object, jlong ms, jint ns) { +JavaObject* obj, jlong ms, jint ns) { + + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) uint32 sec = (uint32) (ms / 1000); uint32 usec = (ns / 1000) + 1000 * (ms % 1000); if (ns && !usec) usec = 1; - JavaObject* obj = (JavaObject*)_object; if (sec || usec) { struct timeval t; t.tv_sec = sec; @@ -123,11 +127,13 @@ JNIEnv *env, jclass clazz, #endif -jobject obj) { +JavaObject* obj) { + + llvm_gcroot(obj, 0); BEGIN_NATIVE_EXCEPTION(0) - ((JavaObject*)obj)->notify(); + obj->notify(); END_NATIVE_EXCEPTION } Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Mon Jul 20 12:07:01 2009 @@ -30,28 +30,33 @@ extern "C" { -JNIEXPORT jobject JNICALL Java_java_lang_VMRuntime_mapLibraryName( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMRuntime_mapLibraryName( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject _strLib) { +JavaString* strLib) { - jobject res = 0; + JavaObject* res = 0; + ArrayUInt16* array = 0; + const ArrayUInt16* utf8Lib = 0; + llvm_gcroot(res, 0); + llvm_gcroot(array, 0); + llvm_gcroot(utf8Lib, 0); + llvm_gcroot(strLib, 0); BEGIN_NATIVE_EXCEPTION(0) - JavaString* strLib = (JavaString*)_strLib; Jnjvm* vm = JavaThread::get()->getJVM(); - const ArrayUInt16* utf8Lib = strLib->value; + utf8Lib = strLib->value; uint32 stLib = strLib->offset; sint32 lgLib = strLib->count; sint32 lgPre = vm->bootstrapLoader->prelib->size; sint32 lgPost = vm->bootstrapLoader->postlib->size; uint32 size = (uint32)(lgPre + lgLib + lgPost); - ArrayUInt16* array = (ArrayUInt16*)vm->upcalls->ArrayOfChar->doNew(size, vm); + array = (ArrayUInt16*)vm->upcalls->ArrayOfChar->doNew(size, vm); uint16* elements = array->elements; memmove(elements, vm->bootstrapLoader->prelib->elements, @@ -61,7 +66,7 @@ memmove(&(elements[lgPre + lgLib]), vm->bootstrapLoader->postlib->elements, lgPost * sizeof(uint16)); - res = (jobject)(vm->constructString(array)); + res = vm->constructString(array); END_NATIVE_EXCEPTION @@ -106,15 +111,17 @@ JNIEnv *env, jclass clazz, #endif -jobject _str, -jobject _loader) { +JavaString* str, +JavaObject* javaLoader) { + llvm_gcroot(str, 0); + llvm_gcroot(javaLoader, 0); + void* res = 0; - JavaString* str = (JavaString*)_str; Jnjvm* vm = JavaThread::get()->getJVM(); JnjvmClassLoader* loader = - JnjvmClassLoader::getJnjvmLoaderFromJavaObject((JavaObject*)_loader, vm); + JnjvmClassLoader::getJnjvmLoaderFromJavaObject(javaLoader, vm); char* buf = str->strToAsciiz(); Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMStackWalker.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMStackWalker.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMStackWalker.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMStackWalker.inc Mon Jul 20 12:07:01 2009 @@ -23,14 +23,15 @@ extern "C" { -JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getClassContext( +JNIEXPORT JavaObject* JNICALL Java_gnu_classpath_VMStackWalker_getClassContext( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif ) { - jobject result = 0; + ArrayObject* result = 0; + llvm_gcroot(result, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -40,7 +41,7 @@ th->getJavaFrameContext(stack); - ArrayObject* res = (ArrayObject*) + result = (ArrayObject*) vm->upcalls->stackTraceArray->doNew(stack.size(), vm); std::vector::iterator i = stack.begin(), e = stack.end(); @@ -49,30 +50,30 @@ for (; i != e; ++i) { JavaMethod* meth = vm->IPToMethod(*i); assert(meth && "Wrong stack trace"); - res->elements[index++] = meth->classDef->getClassDelegatee(vm); + result->elements[index++] = meth->classDef->getClassDelegatee(vm); } - result = (jobject)res; - END_NATIVE_EXCEPTION return result; } -JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getClassLoader( +JNIEXPORT JavaObject* JNICALL Java_gnu_classpath_VMStackWalker_getClassLoader( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jclass _Cl) { +JavaObject* Cl) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(Cl, 0); BEGIN_NATIVE_EXCEPTION(0) - JavaObject* Cl = (JavaObject*)_Cl; - UserCommonClass* cl = ((JavaObjectClass*)Cl)->getClass(); - res = (jobject)cl->classLoader->getJavaClassLoader(); + Jnjvm* vm = JavaThread::get()->getJVM(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); + res = cl->classLoader->getJavaClassLoader(); END_NATIVE_EXCEPTION Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystem.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystem.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystem.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystem.inc Mon Jul 20 12:07:01 2009 @@ -25,17 +25,20 @@ JNIEnv *env, jclass _cl, #endif -jobject _src, +JavaArray* src, jint sstart, -jobject _dst, +JavaArray* dst, jint dstart, jint len) { - + + JavaObject* cur = 0; + llvm_gcroot(src, 0); + llvm_gcroot(dst, 0); + llvm_gcroot(cur, 0); + BEGIN_NATIVE_EXCEPTION(0) jnjvm::Jnjvm *vm = JavaThread::get()->getJVM(); - JavaArray* src = (JavaArray*)_src; - JavaArray* dst = (JavaArray*)_dst; verifyNull(src); verifyNull(dst); @@ -72,7 +75,7 @@ bool doThrow = false; if (!(dstType->isPrimitive())) { while (i < sstart + len && !doThrow) { - JavaObject* cur = ((ArrayObject*)src)->elements[i]; + cur = ((ArrayObject*)src)->elements[i]; if (cur) { if (!(cur->getClass()->isAssignableFrom(dstType))) { doThrow = true; @@ -103,7 +106,9 @@ JNIEnv *env, jclass clazz, #endif -jobject obj) { +JavaObject* obj) { + + llvm_gcroot(obj, 0); return (jint)(intptr_t)obj; } Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.inc Mon Jul 20 12:07:01 2009 @@ -26,6 +26,9 @@ static void setProperty(Jnjvm* vm, JavaObject* prop, const char* key, const char* val) { + + llvm_gcroot(prop, 0); + vm->upcalls->setProperty->invokeIntSpecial(vm, (UserClass*)prop->getClass(), prop, vm->asciizToStr(key), @@ -33,6 +36,9 @@ } static void setUnameProp(Jnjvm* vm, JavaObject* prop) { + + llvm_gcroot(prop, 0); + struct utsname infos; uname(&infos); setProperty(vm, prop, "os.name", infos.sysname); @@ -50,11 +56,12 @@ JNIEnv *env, jclass clazz, #endif -jobject _prop) { +JavaObject* prop) { + + llvm_gcroot(prop, 0); BEGIN_NATIVE_EXCEPTION(0) - JavaObject* prop = (JavaObject*)_prop; Jnjvm* vm = JavaThread::get()->getJVM(); const char* tmp; setProperty(vm, prop, "java.vm.specification.version", "1.0"); @@ -126,6 +133,8 @@ extern "C" void nativePropertiesPostInit(JavaObject* prop) { + llvm_gcroot(prop, 0); + BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThread.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThread.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThread.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThread.inc Mon Jul 20 12:07:01 2009 @@ -23,23 +23,26 @@ // Never throws. // Never calls Java code. -JNIEXPORT jobject JNICALL Java_java_lang_VMThread_currentThread( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMThread_currentThread( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz #endif ) { - return (jobject)(JavaThread::get()->currentThread()); + return JavaThread::get()->currentThread(); } static void start(JavaThread* thread) { + JavaObject* vmThread = 0; + llvm_gcroot(vmThread, 0); + Jnjvm* vm = thread->getJVM(); // Ok, now that the thread is created we can set the the value of vmdata, // which is the JavaThread object. JavaField* field = vm->upcalls->vmdataVMThread; - JavaObject* vmThread = thread->vmThread; + vmThread = thread->vmThread; assert(vmThread && "Didn't fix the vmThread of a jnjvm thread"); JavaObject* javaThread = thread->javaThread; assert(javaThread && "Didn't fix the javaThread of a jnjvm thread"); @@ -76,15 +79,18 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -jobject _vmThread, sint64 stackSize) { +JavaObject* vmThread, sint64 stackSize) { + + JavaObject* javaThread = 0; + llvm_gcroot(vmThread, 0); + llvm_gcroot(javaThread, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - JavaObject* vmThread = (JavaObject*)_vmThread; // Classpath has set this field. - JavaObject* javaThread = vm->upcalls->assocThread->getObjectField(vmThread); + javaThread = vm->upcalls->assocThread->getObjectField(vmThread); assert(javaThread && "VMThread with no Java equivalent"); JavaThread* th = new JavaThread(javaThread, vmThread, vm); @@ -98,12 +104,13 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -jobject _vmthread) { +JavaObject* vmthread) { + + llvm_gcroot(vmthread, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); - JavaObject* vmthread = (JavaObject*)_vmthread; JavaField* field = vm->upcalls->vmdataVMThread; // It's possible that the thread to be interrupted has not finished @@ -161,9 +168,11 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -jobject _vmthread) { +JavaObject* vmthread) { + + llvm_gcroot(vmthread, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); - JavaObject* vmthread = (JavaObject*)_vmthread; JavaField* field = vm->upcalls->vmdataVMThread; JavaThread* th = (JavaThread*)field->getObjectField(vmthread); return (jboolean)th->interruptFlag; @@ -175,8 +184,9 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -jobject vmthread, jint prio) { +JavaObject* vmthread, jint prio) { // Currently not implemented + llvm_gcroot(vmthread, 0); } // Never throws. @@ -185,8 +195,9 @@ #ifdef NATIVE_JNI JNIEnv *env, #endif -jobject vmthread, jobject exc) { +JavaObject* vmthread, jobject exc) { // Currently not implemented + llvm_gcroot(vmthread, 0); } // Never throws. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc Mon Jul 20 12:07:01 2009 @@ -28,6 +28,11 @@ extern "C" { JavaObject* internalFillInStackTrace(JavaObject* throwable) { + + JavaObject* vmThrowable = 0; + llvm_gcroot(throwable, 0); + llvm_gcroot(vmThrowable, 0); + JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); @@ -38,24 +43,26 @@ th->getJavaFrameContext(*stack); // Set the tempory data in the new VMThrowable object. - JavaObject* vmThrowable = vm->upcalls->newVMThrowable->doNew(vm); + vmThrowable = vm->upcalls->newVMThrowable->doNew(vm); uint64 ptr = (uint64)vmThrowable + vm->upcalls->vmDataVMThrowable->ptrOffset; ((JavaObject**)ptr)[0] = (JavaObject*)stack; return vmThrowable; } -JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_fillInStackTrace( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMThrowable_fillInStackTrace( #ifdef NATIVE_JNI JNIEnv *env, jclass clazz, #endif -jobject throwable) { +JavaObject* throwable) { - jobject res = 0; + JavaObject* res = 0; + llvm_gcroot(res, 0); + llvm_gcroot(throwable, 0); BEGIN_NATIVE_EXCEPTION(0) - res = (jobject)internalFillInStackTrace((JavaObject*)throwable); + res = internalFillInStackTrace(throwable); END_NATIVE_EXCEPTION @@ -64,11 +71,20 @@ static JavaObject* consStackElement(JavaMethod* meth, void* ip) { + + JavaString* methodName = 0; + JavaString* className = 0; + JavaString* sourceName = 0; + JavaObject* res = 0; + llvm_gcroot(methodName, 0); + llvm_gcroot(className, 0); + llvm_gcroot(sourceName, 0); + llvm_gcroot(res, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); - JavaObject* methodName = vm->internalUTF8ToStr(meth->name); + methodName = vm->internalUTF8ToStr(meth->name); Class* cl = meth->classDef; - JavaObject* className = JavaString::internalToJava(cl->name, vm); - JavaObject* sourceName = 0; + className = JavaString::internalToJava(cl->name, vm); Attribut* sourceAtt = cl->lookupAttribut(Attribut::sourceFileAttribut); @@ -82,7 +98,7 @@ bool native = isNative(meth->access); UserClass* newS = vm->upcalls->newStackTraceElement; - JavaObject* res = newS->doNew(vm); + res = newS->doNew(vm); vm->upcalls->initStackTraceElement->invokeIntSpecial(vm, newS, res, sourceName, 0, // source line @@ -91,19 +107,22 @@ return res; } -JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_getStackTrace( +JNIEXPORT JavaObject* JNICALL Java_java_lang_VMThrowable_getStackTrace( #ifdef NATIVE_JNI JNIEnv *env, #endif -jobject vmthrow, jobject throwable) { +JavaObject* vmthrow, JavaObject* throwable) { - jobject result = 0; + ArrayObject* result = 0; + llvm_gcroot(vmthrow, 0); + llvm_gcroot(throwable, 0); + llvm_gcroot(result, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = vm->upcalls->vmDataVMThrowable; std::vector* stack = (std::vector*) - field->getObjectField((JavaObject*)vmthrow); + field->getObjectField(vmthrow); std::vector::iterator i = stack->begin(), e = stack->end(); // remove the VMThrowable.fillInStackTrace method @@ -118,18 +137,17 @@ } else break; } - ArrayObject* res = (ArrayObject*) + result = (ArrayObject*) vm->upcalls->stackTraceArray->doNew(stack->size() - index, vm); index = 0; for (; i != e; ++i) { JavaMethod* meth = vm->IPToMethod(*i); assert(meth && "Wrong stack trace"); - res->elements[index++] = consStackElement(meth, *i); + result->elements[index++] = consStackElement(meth, *i); } delete stack; - result = (jobject)res; END_NATIVE_EXCEPTION Modified: vmkit/trunk/lib/JnJVM/Classpath/JavaUpcalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/JavaUpcalls.cpp?rev=76430&r1=76429&r2=76430&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/JavaUpcalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Classpath/JavaUpcalls.cpp Mon Jul 20 12:07:01 2009 @@ -223,12 +223,17 @@ void Classpath::CreateJavaThread(Jnjvm* vm, JavaThread* myth, const char* thName, JavaObject* Group) { + JavaObject* vmth = 0; + JavaObject* th = 0; + llvm_gcroot(Group, 0); + llvm_gcroot(vmth, 0); + llvm_gcroot(th, 0); - JavaObject* th = newThread->doNew(vm); + th = newThread->doNew(vm); myth->javaThread = th; - JavaObject* vmth = newVMThread->doNew(vm); + vmth = newVMThread->doNew(vm); - threadName->setObjectField(th, (JavaObject*)vm->asciizToStr(thName)); + threadName->setObjectField(th, vm->asciizToStr(thName)); priority->setInt32Field(th, (uint32)1); daemon->setInt8Field(th, (uint32)0); vmThread->setObjectField(th, vmth); @@ -243,6 +248,14 @@ } void Classpath::InitializeThreading(Jnjvm* vm) { + + JavaObject* RG = 0; + JavaObject* SystemGroup = 0; + JavaObject* systemName = 0; + llvm_gcroot(RG, 0); + llvm_gcroot(SystemGroup, 0); + llvm_gcroot(systemName, 0); + // Resolve and initialize classes first. newThread->resolveClass(); newThread->initialiseClass(vm); @@ -255,14 +268,14 @@ // Create the main thread void* Stat = threadGroup->getStaticInstance(); - JavaObject* RG = rootGroup->getObjectField(Stat); + RG = rootGroup->getObjectField(Stat); assert(vm->getMainThread() && "VM did not set its main thread"); CreateJavaThread(vm, vm->getMainThread(), "main", RG); // Create the "system" group. - JavaObject* SystemGroup = threadGroup->doNew(vm); + SystemGroup = threadGroup->doNew(vm); initGroup->invokeIntSpecial(vm, threadGroup, SystemGroup); - JavaObject* systemName = (JavaObject*)vm->asciizToStr("system"); + systemName = vm->asciizToStr("system"); groupName->setObjectField(SystemGroup, systemName); // Create the finalizer thread. @@ -276,6 +289,10 @@ extern "C" void nativeInitWeakReference(JavaObjectReference* reference, JavaObject* referent) { + + llvm_gcroot(reference, 0); + llvm_gcroot(referent, 0); + reference->init(referent, 0); JavaThread::get()->getJVM()->addWeakReference(reference); @@ -284,6 +301,10 @@ extern "C" void nativeInitWeakReferenceQ(JavaObjectReference* reference, JavaObject* referent, JavaObject* queue) { + llvm_gcroot(reference, 0); + llvm_gcroot(referent, 0); + llvm_gcroot(queue, 0); + reference->init(referent, queue); JavaThread::get()->getJVM()->addWeakReference(reference); @@ -291,6 +312,9 @@ extern "C" void nativeInitSoftReference(JavaObjectReference* reference, JavaObject* referent) { + llvm_gcroot(reference, 0); + llvm_gcroot(referent, 0); + reference->init(referent, 0); JavaThread::get()->getJVM()->addSoftReference(reference); @@ -299,6 +323,10 @@ extern "C" void nativeInitSoftReferenceQ(JavaObjectReference* reference, JavaObject* referent, JavaObject* queue) { + llvm_gcroot(reference, 0); + llvm_gcroot(referent, 0); + llvm_gcroot(queue, 0); + reference->init(referent, queue); JavaThread::get()->getJVM()->addSoftReference(reference); @@ -307,25 +335,36 @@ extern "C" void nativeInitPhantomReferenceQ(JavaObjectReference* reference, JavaObject* referent, JavaObject* queue) { + llvm_gcroot(reference, 0); + llvm_gcroot(referent, 0); + llvm_gcroot(queue, 0); + reference->init(referent, queue); JavaThread::get()->getJVM()->addPhantomReference(reference); } extern "C" JavaString* nativeInternString(JavaString* obj) { + const ArrayUInt16* array = 0; + llvm_gcroot(obj, 0); + llvm_gcroot(array, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); - const ArrayUInt16* array = obj->strToArray(vm); + array = obj->strToArray(vm); return vm->constructString(array); } -extern "C" uint8 nativeIsArray(JavaObject* klass) { - UserCommonClass* cl = ((JavaObjectClass*)klass)->getClass(); +extern "C" uint8 nativeIsArray(JavaObjectClass* klass) { + llvm_gcroot(klass, 0); + + UserCommonClass* cl = klass->getClass(); return (uint8)cl->isArray(); } extern "C" JavaObject* nativeGetCallingClass() { JavaObject* res = 0; + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) @@ -340,6 +379,7 @@ extern "C" JavaObject* nativeGetCallingClassLoader() { JavaObject *res = 0; + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) JavaThread* th = JavaThread::get(); @@ -352,6 +392,7 @@ extern "C" JavaObject* nativeFirstNonNullClassLoader() { JavaObject *res = 0; + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) JavaThread* th = JavaThread::get(); @@ -364,6 +405,7 @@ extern "C" JavaObject* nativeGetCallerClass(uint32 index) { JavaObject *res = 0; + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) JavaThread* th = JavaThread::get(); @@ -376,6 +418,7 @@ } extern "C" JavaObject* nativeGetAnnotation(JavaObject* obj) { + llvm_gcroot(obj, 0); return 0; } @@ -416,6 +459,8 @@ extern "C" ArrayObject* nativeGetBootPackages(); extern "C" JavaString* nativeGetenv(JavaString* str) { + llvm_gcroot(str, 0); + char* buf = str->strToAsciiz(); char* res = getenv(buf); delete[] buf; From nicolas.geoffray at lip6.fr Mon Jul 20 10:33:37 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 17:33:37 -0000 Subject: [vmkit-commits] [vmkit] r76435 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JITInfo.cpp lib/JnJVM/Compiler/JavaJITOpcodes.cpp Message-ID: <200907201733.n6KHXbOX005394@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 12:33:37 2009 New Revision: 76435 URL: http://llvm.org/viewvc/llvm-project?rev=76435&view=rev Log: Change the LLVMAssessorInfo to take into account LLVMContext. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=76435&r1=76434&r2=76435&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Mon Jul 20 12:33:37 2009 @@ -59,8 +59,7 @@ public: const llvm::Type* llvmType; const llvm::Type* llvmTypePtr; - llvm::Constant* llvmNullConstant; - llvm::Constant* logSizeInBytesConstant; + uint8_t logSizeInBytesConstant; static void initialise(); static std::map AssessorInfo; Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=76435&r1=76434&r2=76435&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Mon Jul 20 12:33:37 2009 @@ -559,80 +559,49 @@ void LLVMAssessorInfo::initialise() { AssessorInfo[I_VOID].llvmType = Type::VoidTy; AssessorInfo[I_VOID].llvmTypePtr = 0; - AssessorInfo[I_VOID].llvmNullConstant = 0; AssessorInfo[I_VOID].logSizeInBytesConstant = 0; AssessorInfo[I_BOOL].llvmType = Type::Int8Ty; AssessorInfo[I_BOOL].llvmTypePtr = PointerType::getUnqual(Type::Int8Ty); - AssessorInfo[I_BOOL].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::Int8Ty); - AssessorInfo[I_BOOL].logSizeInBytesConstant = - mvm::MvmModule::constantZero; + AssessorInfo[I_BOOL].logSizeInBytesConstant = 0; AssessorInfo[I_BYTE].llvmType = Type::Int8Ty; AssessorInfo[I_BYTE].llvmTypePtr = PointerType::getUnqual(Type::Int8Ty); - AssessorInfo[I_BYTE].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::Int8Ty); - AssessorInfo[I_BYTE].logSizeInBytesConstant = - mvm::MvmModule::constantZero; + AssessorInfo[I_BYTE].logSizeInBytesConstant = 0; AssessorInfo[I_SHORT].llvmType = Type::Int16Ty; AssessorInfo[I_SHORT].llvmTypePtr = PointerType::getUnqual(Type::Int16Ty); - AssessorInfo[I_SHORT].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::Int16Ty); - AssessorInfo[I_SHORT].logSizeInBytesConstant = - mvm::MvmModule::constantOne; + AssessorInfo[I_SHORT].logSizeInBytesConstant = 1; AssessorInfo[I_CHAR].llvmType = Type::Int16Ty; AssessorInfo[I_CHAR].llvmTypePtr = PointerType::getUnqual(Type::Int16Ty); - AssessorInfo[I_CHAR].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::Int16Ty); - AssessorInfo[I_CHAR].logSizeInBytesConstant = - mvm::MvmModule::constantOne; + AssessorInfo[I_CHAR].logSizeInBytesConstant = 1; AssessorInfo[I_INT].llvmType = Type::Int32Ty; AssessorInfo[I_INT].llvmTypePtr = PointerType::getUnqual(Type::Int32Ty); - AssessorInfo[I_INT].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::Int32Ty); - AssessorInfo[I_INT].logSizeInBytesConstant = - mvm::MvmModule::constantTwo; + AssessorInfo[I_INT].logSizeInBytesConstant = 2; AssessorInfo[I_FLOAT].llvmType = Type::FloatTy; AssessorInfo[I_FLOAT].llvmTypePtr = PointerType::getUnqual(Type::FloatTy); - AssessorInfo[I_FLOAT].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::FloatTy); - AssessorInfo[I_FLOAT].logSizeInBytesConstant = - mvm::MvmModule::constantTwo; + AssessorInfo[I_FLOAT].logSizeInBytesConstant = 2; AssessorInfo[I_LONG].llvmType = Type::Int64Ty; AssessorInfo[I_LONG].llvmTypePtr = PointerType::getUnqual(Type::Int64Ty); - AssessorInfo[I_LONG].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::Int64Ty); - AssessorInfo[I_LONG].logSizeInBytesConstant = - mvm::MvmModule::constantThree; + AssessorInfo[I_LONG].logSizeInBytesConstant = 3; AssessorInfo[I_DOUBLE].llvmType = Type::DoubleTy; AssessorInfo[I_DOUBLE].llvmTypePtr = PointerType::getUnqual(Type::DoubleTy); - AssessorInfo[I_DOUBLE].llvmNullConstant = - mvm::MvmModule::globalContext->getNullValue(Type::DoubleTy); - AssessorInfo[I_DOUBLE].logSizeInBytesConstant = - mvm::MvmModule::constantThree; + AssessorInfo[I_DOUBLE].logSizeInBytesConstant = 3; AssessorInfo[I_TAB].llvmType = JnjvmModule::JavaObjectType; AssessorInfo[I_TAB].llvmTypePtr = PointerType::getUnqual(JnjvmModule::JavaObjectType); - AssessorInfo[I_TAB].llvmNullConstant = - JnjvmModule::JavaObjectNullConstant; - AssessorInfo[I_TAB].logSizeInBytesConstant = - mvm::MvmModule::constantPtrLogSize; + AssessorInfo[I_TAB].logSizeInBytesConstant = sizeof(JavaObject*) == 8 ? 3 : 2; AssessorInfo[I_REF].llvmType = JnjvmModule::JavaObjectType; AssessorInfo[I_REF].llvmTypePtr = PointerType::getUnqual(JnjvmModule::JavaObjectType); - AssessorInfo[I_REF].llvmNullConstant = - JnjvmModule::JavaObjectNullConstant; - AssessorInfo[I_REF].logSizeInBytesConstant = - mvm::MvmModule::constantPtrLogSize; + AssessorInfo[I_REF].logSizeInBytesConstant = sizeof(JavaObject*) == 8 ? 3 : 2; } std::map LLVMAssessorInfo::AssessorInfo; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=76435&r1=76434&r2=76435&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Mon Jul 20 12:33:37 2009 @@ -1910,7 +1910,8 @@ #endif LLVMAssessorInfo& LAI = LLVMAssessorInfo::AssessorInfo[charId]; - sizeElement = LAI.logSizeInBytesConstant; + sizeElement = llvmContext->getConstantInt(Type::Int32Ty, + LAI.logSizeInBytesConstant); if (TheCompiler->isStaticCompiling() && valCl->getType() != module->JavaClassArrayType) { valCl = new LoadInst(valCl, "", currentBlock); From nicolas.geoffray at lip6.fr Mon Jul 20 13:25:05 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 20:25:05 -0000 Subject: [vmkit-commits] [vmkit] r76461 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h include/mvm/JIT.h lib/JnJVM/Compiler/JITInfo.cpp lib/JnJVM/Compiler/JavaAOTCompiler.cpp lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/Compiler/LowerConstantCalls.cpp lib/Mvm/Compiler/JIT.cpp lib/N3/VMCore/CLIJit.cpp lib/N3/VMCore/CLIJitMeta.cpp lib/N3/VMCore/LowerArrayLength.cpp lib/N3/VMCore/VMClass.cpp Message-ID: <200907202025.n6KKP5VX011998@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 15:25:05 2009 New Revision: 76461 URL: http://llvm.org/viewvc/llvm-project?rev=76461&view=rev Log: Make constants instance fields instead of static fields. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/include/mvm/JIT.h vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp vmkit/trunk/lib/N3/VMCore/CLIJit.cpp vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp vmkit/trunk/lib/N3/VMCore/VMClass.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Mon Jul 20 15:25:05 2009 @@ -206,10 +206,6 @@ class JnjvmModule : public mvm::MvmModule { public: - static llvm::Constant* JavaArraySizeOffsetConstant; - static llvm::Constant* JavaArrayElementsOffsetConstant; - static llvm::Constant* JavaObjectLockOffsetConstant; - static llvm::Constant* JavaObjectVTOffsetConstant; static const llvm::Type* JavaArrayUInt8Type; static const llvm::Type* JavaArraySInt8Type; @@ -317,27 +313,32 @@ llvm::Function* GetFinalFloatFieldFunction; llvm::Function* GetFinalDoubleFieldFunction; llvm::Function* GetFinalObjectFieldFunction; - - static llvm::Constant* OffsetObjectSizeInClassConstant; - static llvm::Constant* OffsetVTInClassConstant; - static llvm::Constant* OffsetTaskClassMirrorInClassConstant; - static llvm::Constant* OffsetStaticInstanceInTaskClassMirrorConstant; - static llvm::Constant* OffsetInitializedInTaskClassMirrorConstant; - static llvm::Constant* OffsetStatusInTaskClassMirrorConstant; - - static llvm::Constant* OffsetJavaExceptionInThreadConstant; - static llvm::Constant* OffsetCXXExceptionInThreadConstant; - - static llvm::Constant* OffsetClassInVTConstant; - static llvm::Constant* OffsetDepthInVTConstant; - static llvm::Constant* OffsetDisplayInVTConstant; - static llvm::Constant* OffsetBaseClassVTInVTConstant; - - static llvm::Constant* ClassReadyConstant; - - static llvm::Constant* JavaObjectNullConstant; - static llvm::Constant* MaxArraySizeConstant; - static llvm::Constant* JavaArraySizeConstant; + + llvm::Constant* JavaArraySizeOffsetConstant; + llvm::Constant* JavaArrayElementsOffsetConstant; + llvm::Constant* JavaObjectLockOffsetConstant; + llvm::Constant* JavaObjectVTOffsetConstant; + + llvm::Constant* OffsetObjectSizeInClassConstant; + llvm::Constant* OffsetVTInClassConstant; + llvm::Constant* OffsetTaskClassMirrorInClassConstant; + llvm::Constant* OffsetStaticInstanceInTaskClassMirrorConstant; + llvm::Constant* OffsetInitializedInTaskClassMirrorConstant; + llvm::Constant* OffsetStatusInTaskClassMirrorConstant; + + llvm::Constant* OffsetJavaExceptionInThreadConstant; + llvm::Constant* OffsetCXXExceptionInThreadConstant; + + llvm::Constant* OffsetClassInVTConstant; + llvm::Constant* OffsetDepthInVTConstant; + llvm::Constant* OffsetDisplayInVTConstant; + llvm::Constant* OffsetBaseClassVTInVTConstant; + + llvm::Constant* ClassReadyConstant; + + llvm::Constant* JavaObjectNullConstant; + llvm::Constant* MaxArraySizeConstant; + llvm::Constant* JavaArraySizeConstant; llvm::Function* ThrowExceptionFunction; llvm::Function* NullPointerExceptionFunction; Modified: vmkit/trunk/include/mvm/JIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/include/mvm/JIT.h (original) +++ vmkit/trunk/include/mvm/JIT.h Mon Jul 20 15:25:05 2009 @@ -115,80 +115,79 @@ llvm::Function* llvm_atomic_lcs_ptr; - static llvm::Constant* constantInt8Zero; - static llvm::Constant* constantZero; - static llvm::Constant* constantOne; - static llvm::Constant* constantTwo; - static llvm::Constant* constantThree; - static llvm::Constant* constantFour; - static llvm::Constant* constantFive; - static llvm::Constant* constantSix; - static llvm::Constant* constantSeven; - static llvm::Constant* constantEight; - static llvm::Constant* constantMinusOne; - static llvm::Constant* constantLongMinusOne; - static llvm::Constant* constantLongZero; - static llvm::Constant* constantLongOne; - static llvm::Constant* constantMinInt; - static llvm::Constant* constantMaxInt; - static llvm::Constant* constantMinLong; - static llvm::Constant* constantMaxLong; - static llvm::Constant* constantFloatZero; - static llvm::Constant* constantFloatOne; - static llvm::Constant* constantFloatTwo; - static llvm::Constant* constantDoubleZero; - static llvm::Constant* constantDoubleOne; - static llvm::Constant* constantMaxIntFloat; - static llvm::Constant* constantMinIntFloat; - static llvm::Constant* constantMinLongFloat; - static llvm::Constant* constantMinLongDouble; - static llvm::Constant* constantMaxLongFloat; - static llvm::Constant* constantMaxIntDouble; - static llvm::Constant* constantMinIntDouble; - static llvm::Constant* constantMaxLongDouble; - static llvm::Constant* constantDoubleInfinity; - static llvm::Constant* constantDoubleMinusInfinity; - static llvm::Constant* constantFloatInfinity; - static llvm::Constant* constantFloatMinusInfinity; - static llvm::Constant* constantFloatMinusZero; - static llvm::Constant* constantDoubleMinusZero; - static llvm::Constant* constantPtrNull; - static llvm::Constant* constantPtrLogSize; - static llvm::Constant* constantThreadIDMask; - static llvm::Constant* constantStackOverflowMask; - static llvm::Constant* constantFatMask; - static llvm::Constant* constantPtrOne; - static llvm::Constant* constantPtrZero; - static const llvm::PointerType* ptrType; - static const llvm::PointerType* ptr32Type; - static const llvm::PointerType* ptrPtrType; - static const llvm::Type* arrayPtrType; - static const llvm::Type* pointerSizeType; - - static llvm::ExecutionEngine* executionEngine; - static mvm::LockNormal protectEngine; - static llvm::Module *globalModule; - static llvm::LLVMContext *globalContext; - static llvm::ExistingModuleProvider *globalModuleProvider; - static llvm::FunctionPassManager* globalFunctionPasses; - static const llvm::TargetData* TheTargetData; + llvm::Constant* constantInt8Zero; + llvm::Constant* constantZero; + llvm::Constant* constantOne; + llvm::Constant* constantTwo; + llvm::Constant* constantThree; + llvm::Constant* constantFour; + llvm::Constant* constantFive; + llvm::Constant* constantSix; + llvm::Constant* constantSeven; + llvm::Constant* constantEight; + llvm::Constant* constantMinusOne; + llvm::Constant* constantLongMinusOne; + llvm::Constant* constantLongZero; + llvm::Constant* constantLongOne; + llvm::Constant* constantMinInt; + llvm::Constant* constantMaxInt; + llvm::Constant* constantMinLong; + llvm::Constant* constantMaxLong; + llvm::Constant* constantFloatZero; + llvm::Constant* constantFloatOne; + llvm::Constant* constantFloatTwo; + llvm::Constant* constantDoubleZero; + llvm::Constant* constantDoubleOne; + llvm::Constant* constantMaxIntFloat; + llvm::Constant* constantMinIntFloat; + llvm::Constant* constantMinLongFloat; + llvm::Constant* constantMinLongDouble; + llvm::Constant* constantMaxLongFloat; + llvm::Constant* constantMaxIntDouble; + llvm::Constant* constantMinIntDouble; + llvm::Constant* constantMaxLongDouble; + llvm::Constant* constantDoubleInfinity; + llvm::Constant* constantDoubleMinusInfinity; + llvm::Constant* constantFloatInfinity; + llvm::Constant* constantFloatMinusInfinity; + llvm::Constant* constantFloatMinusZero; + llvm::Constant* constantDoubleMinusZero; + llvm::Constant* constantPtrNull; + llvm::Constant* constantPtrLogSize; + llvm::Constant* constantThreadIDMask; + llvm::Constant* constantStackOverflowMask; + llvm::Constant* constantFatMask; + llvm::Constant* constantPtrOne; + llvm::Constant* constantPtrZero; + static const llvm::PointerType* ptrType; + static const llvm::PointerType* ptr32Type; + static const llvm::PointerType* ptrPtrType; + static const llvm::Type* arrayPtrType; + static const llvm::Type* pointerSizeType; + + static llvm::ExecutionEngine* executionEngine; + static mvm::LockNormal protectEngine; + static llvm::Module *globalModule; + static llvm::ExistingModuleProvider *globalModuleProvider; + static llvm::FunctionPassManager* globalFunctionPasses; + static const llvm::TargetData* TheTargetData; - static uint64 getTypeSize(const llvm::Type* type); - static void runPasses(llvm::Function* func, llvm::FunctionPassManager*); - static void initialise(llvm::CodeGenOpt::Level = llvm::CodeGenOpt::Default, + static uint64 getTypeSize(const llvm::Type* type); + static void runPasses(llvm::Function* func, llvm::FunctionPassManager*); + static void initialise(llvm::CodeGenOpt::Level = llvm::CodeGenOpt::Default, llvm::Module* TheModule = 0, llvm::TargetMachine* TheTarget = 0); - static int disassemble(unsigned int* addr); + static int disassemble(unsigned int* addr); - static void protectIR(); - static void unprotectIR(); + static void protectIR(); + static void unprotectIR(); - static void copyDefinitions(llvm::Module* Dst, llvm::Module* Src); + static void copyDefinitions(llvm::Module* Dst, llvm::Module* Src); - static void AddStandardCompilePasses(); + static void AddStandardCompilePasses(); - static const char* getHostTriple(); + static const char* getHostTriple(); }; } // end namespace mvm Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Mon Jul 20 15:25:05 2009 @@ -360,7 +360,7 @@ Value* val = new BitCastInst(ptr, LAI.llvmTypePtr, "", currentBlock); Value* arg = new LoadInst(val, "", currentBlock); Args.push_back(arg); - ptr = GetElementPtrInst::Create(ptr, JnjvmModule::constantEight, "", + ptr = GetElementPtrInst::Create(ptr, Mod->getIntrinsics()->constantEight,"", currentBlock); } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 20 15:25:05 2009 @@ -142,7 +142,7 @@ } } Array = SI->second; - Constant* GEPs[2] = { JnjvmModule::constantZero, MOffset }; + Constant* GEPs[2] = { getIntrinsics()->constantZero, MOffset }; return ConstantExpr::getGetElementPtr(Array, GEPs, 2); } @@ -219,11 +219,13 @@ Constant* Cl = getNativeClass(cl); - Constant* GEP[2] = { JnjvmModule::constantZero, JnjvmModule::constantZero }; + Constant* GEP[2] = { getIntrinsics()->constantZero, + getIntrinsics()->constantZero }; Constant* TCMArray = ConstantExpr::getGetElementPtr(Cl, GEP, 2); - Constant* GEP2[2] = { JnjvmModule::constantZero, JnjvmModule::constantZero }; + Constant* GEP2[2] = { getIntrinsics()->constantZero, + getIntrinsics()->constantZero }; Constant* Ptr = ConstantExpr::getGetElementPtr(TCMArray, GEP2, 2); return Ptr; @@ -978,8 +980,8 @@ dyn_cast(JnjvmModule::JavaClassArrayType->getContainedType(0)); std::vector ClassElts; - Constant* ClGEPs[2] = { JnjvmModule::constantZero, - JnjvmModule::constantZero }; + Constant* ClGEPs[2] = { getIntrinsics()->constantZero, + getIntrinsics()->constantZero }; // common class ClassElts.push_back(CreateConstantFromCommonClass(cl)); Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Mon Jul 20 15:25:05 2009 @@ -54,31 +54,11 @@ const llvm::Type* JnjvmModule::JnjvmType = 0; #endif -llvm::Constant* JnjvmModule::JavaObjectNullConstant; -llvm::Constant* JnjvmModule::MaxArraySizeConstant; -llvm::Constant* JnjvmModule::JavaArraySizeConstant; -llvm::Constant* JnjvmModule::OffsetObjectSizeInClassConstant; -llvm::Constant* JnjvmModule::OffsetVTInClassConstant; -llvm::Constant* JnjvmModule::OffsetTaskClassMirrorInClassConstant; -llvm::Constant* JnjvmModule::OffsetStaticInstanceInTaskClassMirrorConstant; -llvm::Constant* JnjvmModule::OffsetStatusInTaskClassMirrorConstant; -llvm::Constant* JnjvmModule::OffsetInitializedInTaskClassMirrorConstant; -llvm::Constant* JnjvmModule::OffsetJavaExceptionInThreadConstant; -llvm::Constant* JnjvmModule::OffsetCXXExceptionInThreadConstant; -llvm::Constant* JnjvmModule::ClassReadyConstant; const llvm::Type* JnjvmModule::JavaClassType; const llvm::Type* JnjvmModule::JavaClassPrimitiveType; const llvm::Type* JnjvmModule::JavaClassArrayType; const llvm::Type* JnjvmModule::JavaCommonClassType; const llvm::Type* JnjvmModule::VTType; -llvm::Constant* JnjvmModule::JavaArrayElementsOffsetConstant; -llvm::Constant* JnjvmModule::JavaArraySizeOffsetConstant; -llvm::Constant* JnjvmModule::JavaObjectLockOffsetConstant; -llvm::Constant* JnjvmModule::JavaObjectVTOffsetConstant; -llvm::Constant* JnjvmModule::OffsetClassInVTConstant; -llvm::Constant* JnjvmModule::OffsetDepthInVTConstant; -llvm::Constant* JnjvmModule::OffsetDisplayInVTConstant; -llvm::Constant* JnjvmModule::OffsetBaseClassVTInVTConstant; JavaLLVMCompiler::JavaLLVMCompiler(const std::string& str) : @@ -113,7 +93,6 @@ void JnjvmModule::initialise() { Module* module = globalModule; - LLVMContext& Context = module->getContext(); jnjvm::llvm_runtime::makeLLVMModuleContents(module); VTType = PointerType::getUnqual(module->getTypeByName("VT")); @@ -176,7 +155,23 @@ PointerType::getUnqual(module->getTypeByName("Attribut")); JavaThreadType = PointerType::getUnqual(module->getTypeByName("JavaThread")); + + LLVMAssessorInfo::initialise(); +} + +Function* JavaLLVMCompiler::getMethod(JavaMethod* meth) { + return getMethodInfo(meth)->getMethod(); +} +JnjvmModule::JnjvmModule(llvm::Module* module) : + MvmModule(module) { + LLVMContext& Context = module->getContext(); + + if (!VTType) { + initialise(); + copyDefinitions(module, globalModule); + } + JavaObjectNullConstant = module->getContext().getNullValue(JnjvmModule::JavaObjectType); MaxArraySizeConstant = Context.getConstantInt(Type::Int32Ty, @@ -185,41 +180,26 @@ Context.getConstantInt(Type::Int32Ty, sizeof(JavaObject) + sizeof(ssize_t)); - JavaArrayElementsOffsetConstant = mvm::MvmModule::constantTwo; - JavaArraySizeOffsetConstant = mvm::MvmModule::constantOne; - JavaObjectLockOffsetConstant = mvm::MvmModule::constantOne; - JavaObjectVTOffsetConstant = mvm::MvmModule::constantZero; - OffsetClassInVTConstant = mvm::MvmModule::constantThree; - OffsetDepthInVTConstant = mvm::MvmModule::constantFour; - OffsetDisplayInVTConstant = mvm::MvmModule::constantSeven; + JavaArrayElementsOffsetConstant = constantTwo; + JavaArraySizeOffsetConstant = constantOne; + JavaObjectLockOffsetConstant = constantOne; + JavaObjectVTOffsetConstant = constantZero; + OffsetClassInVTConstant = constantThree; + OffsetDepthInVTConstant = constantFour; + OffsetDisplayInVTConstant = constantSeven; OffsetBaseClassVTInVTConstant = Context.getConstantInt(Type::Int32Ty, 17); - OffsetObjectSizeInClassConstant = mvm::MvmModule::constantOne; + OffsetObjectSizeInClassConstant = constantOne; OffsetVTInClassConstant = Context.getConstantInt(Type::Int32Ty, 7); - OffsetTaskClassMirrorInClassConstant = mvm::MvmModule::constantTwo; - OffsetStaticInstanceInTaskClassMirrorConstant = mvm::MvmModule::constantTwo; - OffsetStatusInTaskClassMirrorConstant = mvm::MvmModule::constantZero; - OffsetInitializedInTaskClassMirrorConstant = mvm::MvmModule::constantOne; + OffsetTaskClassMirrorInClassConstant = constantTwo; + OffsetStaticInstanceInTaskClassMirrorConstant = constantTwo; + OffsetStatusInTaskClassMirrorConstant = constantZero; + OffsetInitializedInTaskClassMirrorConstant = constantOne; OffsetJavaExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 9); OffsetCXXExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 10); ClassReadyConstant = Context.getConstantInt(Type::Int8Ty, ready); - - LLVMAssessorInfo::initialise(); -} - -Function* JavaLLVMCompiler::getMethod(JavaMethod* meth) { - return getMethodInfo(meth)->getMethod(); -} - -JnjvmModule::JnjvmModule(llvm::Module* module) : - MvmModule(module) { - - if (!VTType) { - initialise(); - copyDefinitions(module, globalModule); - } module->addTypeName("JavaObject", JavaObjectType->getContainedType(0)); module->addTypeName("JavaArray", JavaArrayType->getContainedType(0)); Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Mon Jul 20 15:25:05 2009 @@ -416,7 +416,7 @@ Value* arg1 = GetElementPtrInst::Create(CTP, indexes, "", CI); arg1 = new LoadInst(arg1, "", false, CI); Value* test = new ICmpInst(CI, ICmpInst::ICMP_EQ, arg1, - mvm::MvmModule::constantPtrNull, ""); + module->constantPtrNull, ""); BasicBlock* trueCl = BasicBlock::Create("Ctp OK", &F); BasicBlock* falseCl = BasicBlock::Create("Ctp Not OK", &F); Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 20 15:25:05 2009 @@ -55,8 +55,7 @@ llvm::ExceptionHandling = false; #endif if (!M) { - globalContext = new llvm::LLVMContext(); - globalModule = new llvm::Module("bootstrap module", *globalContext); + globalModule = new Module("bootstrap module", *(new LLVMContext())); globalModuleProvider = new ExistingModuleProvider (globalModule); InitializeNativeTarget(); @@ -86,6 +85,16 @@ pointerSizeType = globalModule->getPointerSize() == Module::Pointer32 ? Type::Int32Ty : Type::Int64Ty; +} + + +MvmModule::MvmModule(llvm::Module* module) { + + module->setDataLayout(globalModule->getDataLayout()); + module->setTargetTriple(globalModule->getTargetTriple()); + LLVMContext* globalContext = &(module->getContext()); + + // Constant declaration constantLongMinusOne = globalContext->getConstantInt(Type::Int64Ty, (uint64_t)-1); constantLongZero = globalContext->getConstantInt(Type::Int64Ty, 0); @@ -137,14 +146,8 @@ constantPtrLogSize = globalContext->getConstantInt(Type::Int32Ty, sizeof(void*) == 8 ? 3 : 2); arrayPtrType = PointerType::getUnqual(ArrayType::get(Type::Int8Ty, 0)); -} -MvmModule::MvmModule(llvm::Module* module) { - - module->setDataLayout(globalModule->getDataLayout()); - module->setTargetTriple(globalModule->getTargetTriple()); - copyDefinitions(module, globalModule); printFloatLLVM = module->getFunction("printFloat"); @@ -208,50 +211,6 @@ } -llvm::Constant* MvmModule::constantInt8Zero; -llvm::Constant* MvmModule::constantZero; -llvm::Constant* MvmModule::constantOne; -llvm::Constant* MvmModule::constantTwo; -llvm::Constant* MvmModule::constantThree; -llvm::Constant* MvmModule::constantFour; -llvm::Constant* MvmModule::constantFive; -llvm::Constant* MvmModule::constantSix; -llvm::Constant* MvmModule::constantSeven; -llvm::Constant* MvmModule::constantEight; -llvm::Constant* MvmModule::constantMinusOne; -llvm::Constant* MvmModule::constantLongMinusOne; -llvm::Constant* MvmModule::constantLongZero; -llvm::Constant* MvmModule::constantLongOne; -llvm::Constant* MvmModule::constantMinInt; -llvm::Constant* MvmModule::constantMaxInt; -llvm::Constant* MvmModule::constantMinLong; -llvm::Constant* MvmModule::constantMaxLong; -llvm::Constant* MvmModule::constantFloatZero; -llvm::Constant* MvmModule::constantFloatOne; -llvm::Constant* MvmModule::constantFloatTwo; -llvm::Constant* MvmModule::constantDoubleZero; -llvm::Constant* MvmModule::constantDoubleOne; -llvm::Constant* MvmModule::constantMaxIntFloat; -llvm::Constant* MvmModule::constantMinIntFloat; -llvm::Constant* MvmModule::constantMinLongFloat; -llvm::Constant* MvmModule::constantMinLongDouble; -llvm::Constant* MvmModule::constantMaxLongFloat; -llvm::Constant* MvmModule::constantMaxIntDouble; -llvm::Constant* MvmModule::constantMinIntDouble; -llvm::Constant* MvmModule::constantMaxLongDouble; -llvm::Constant* MvmModule::constantDoubleInfinity; -llvm::Constant* MvmModule::constantDoubleMinusInfinity; -llvm::Constant* MvmModule::constantFloatInfinity; -llvm::Constant* MvmModule::constantFloatMinusInfinity; -llvm::Constant* MvmModule::constantFloatMinusZero; -llvm::Constant* MvmModule::constantDoubleMinusZero; -llvm::Constant* MvmModule::constantPtrNull; -llvm::Constant* MvmModule::constantPtrLogSize; -llvm::Constant* MvmModule::constantThreadIDMask; -llvm::Constant* MvmModule::constantStackOverflowMask; -llvm::Constant* MvmModule::constantFatMask; -llvm::Constant* MvmModule::constantPtrOne; -llvm::Constant* MvmModule::constantPtrZero; const llvm::PointerType* MvmModule::ptrType; const llvm::PointerType* MvmModule::ptr32Type; const llvm::PointerType* MvmModule::ptrPtrType; @@ -260,7 +219,6 @@ const llvm::TargetData* MvmModule::TheTargetData; llvm::Module *MvmModule::globalModule; -llvm::LLVMContext *MvmModule::globalContext; llvm::ExistingModuleProvider *MvmModule::globalModuleProvider; llvm::FunctionPassManager* MvmModule::globalFunctionPasses; llvm::ExecutionEngine* MvmModule::executionEngine; Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Mon Jul 20 15:25:05 2009 @@ -104,7 +104,7 @@ #endif Function* llvmFunction = block->getParent(); - Constant* zero = mvm::MvmModule::constantZero; + Constant* zero = cl->vm->module->constantZero; for (std::vector::iterator i = fields.begin(), e = fields.end(); i!= e; ++i) { VMField* field = *i; @@ -160,9 +160,9 @@ Argument* GC = ++(func->arg_begin()); #endif // Constant Definitions - Constant* const_int32_8 = mvm::MvmModule::constantZero; - Constant* const_int32_9 = mvm::MvmModule::constantOne; - Constant* const_int32_10 = mvm::MvmModule::constantTwo; + Constant* const_int32_8 = cl->vm->module->constantZero; + Constant* const_int32_9 = cl->vm->module->constantOne; + Constant* const_int32_10 = cl->vm->module->constantTwo; // Function Definitions @@ -856,11 +856,11 @@ } Constant* VMArray::sizeOffset() { - return mvm::MvmModule::constantOne; + return VMThread::get()->vm->module->constantOne; } Constant* VMArray::elementsOffset() { - return mvm::MvmModule::constantTwo; + return VMThread::get()->vm->module->constantTwo; } Value* CLIJit::arraySize(Value* array) { Modified: vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp Mon Jul 20 15:25:05 2009 @@ -423,5 +423,5 @@ } Constant* VMObject::classOffset() { - return mvm::MvmModule::constantOne; + return VMThread::get()->vm->module->constantOne; } Modified: vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp Mon Jul 20 15:25:05 2009 @@ -46,7 +46,7 @@ Changed = true; Value* val = CI->getOperand(1); // get the array std::vector args; //size= 2 - args.push_back(mvm::MvmModule::constantZero); + args.push_back(F.getContext()->getConstantInt(Type::Int32Ty, 0)); args.push_back(n3::VMArray::sizeOffset()); Value* ptr = GetElementPtrInst::Create(val, args.begin(), args.end(), "", CI); Modified: vmkit/trunk/lib/N3/VMCore/VMClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMClass.cpp?rev=76461&r1=76460&r2=76461&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMClass.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMClass.cpp Mon Jul 20 15:25:05 2009 @@ -320,7 +320,7 @@ if (super == MSCorlib::pValue) { uint32 size = virtualFields.size(); if (size == 1) { - virtualFields[0]->offset = mvm::MvmModule::constantZero; + virtualFields[0]->offset = VMThread::get()->vm->module->constantZero; ResultTy = virtualFields[0]->signature->naturalType; } else if (size == 0) { ResultTy = llvm::Type::VoidTy; From nicolas.geoffray at lip6.fr Mon Jul 20 13:53:59 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 20:53:59 -0000 Subject: [vmkit-commits] [vmkit] r76467 - /vmkit/trunk/include/mvm/Allocator.h Message-ID: <200907202054.n6KKs2MS012994@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 15:53:46 2009 New Revision: 76467 URL: http://llvm.org/viewvc/llvm-project?rev=76467&view=rev Log: Fiw macro. Modified: vmkit/trunk/include/mvm/Allocator.h Modified: vmkit/trunk/include/mvm/Allocator.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Allocator.h?rev=76467&r1=76466&r2=76467&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Allocator.h (original) +++ vmkit/trunk/include/mvm/Allocator.h Mon Jul 20 15:53:46 2009 @@ -23,7 +23,7 @@ #ifdef LLVM_GCC extern "C" void llvm_gcroot(const void*, void*) asm("llvm.gcroot"); #else -#define llvm_gcroot +#define llvm_gcroot(a, b) #endif namespace mvm { From nicolas.geoffray at lip6.fr Mon Jul 20 13:54:58 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 20:54:58 -0000 Subject: [vmkit-commits] [vmkit] r76468 - /vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Message-ID: <200907202055.n6KKt0uS013035@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 15:54:45 2009 New Revision: 76468 URL: http://llvm.org/viewvc/llvm-project?rev=76468&view=rev Log: Do the initialization of passes when runnnin them. Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=76468&r1=76467&r2=76468&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 20 15:54:45 2009 @@ -231,6 +231,7 @@ void MvmModule::runPasses(llvm::Function* func, llvm::FunctionPassManager* pm) { + pm->doInitialization(); pm->run(*func); } @@ -288,7 +289,6 @@ addPass(PM, createAggressiveDCEPass()); // Delete dead instructions addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs - PM->doInitialization(); } // We protect the creation of IR with the executionEngine lock because From nicolas.geoffray at lip6.fr Mon Jul 20 14:12:00 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 21:12:00 -0000 Subject: [vmkit-commits] [vmkit] r76470 - in /vmkit/trunk/lib: JnJVM/Compiler/JnjvmModule.cpp Mvm/Compiler/JIT.cpp Message-ID: <200907202112.n6KLC0uj013623@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 16:11:58 2009 New Revision: 76470 URL: http://llvm.org/viewvc/llvm-project?rev=76470&view=rev Log: Use the global context for now. Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=76470&r1=76469&r2=76470&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Mon Jul 20 16:11:58 2009 @@ -62,7 +62,7 @@ JavaLLVMCompiler::JavaLLVMCompiler(const std::string& str) : - TheModule(new llvm::Module(str, *(new llvm::LLVMContext()))), + TheModule(new llvm::Module(str, getGlobalContext())), JavaIntrinsics(TheModule) { enabledException = true; Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=76470&r1=76469&r2=76470&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 20 16:11:58 2009 @@ -55,7 +55,7 @@ llvm::ExceptionHandling = false; #endif if (!M) { - globalModule = new Module("bootstrap module", *(new LLVMContext())); + globalModule = new Module("bootstrap module", getGlobalContext()); globalModuleProvider = new ExistingModuleProvider (globalModule); InitializeNativeTarget(); @@ -231,7 +231,6 @@ void MvmModule::runPasses(llvm::Function* func, llvm::FunctionPassManager* pm) { - pm->doInitialization(); pm->run(*func); } @@ -289,6 +288,8 @@ addPass(PM, createAggressiveDCEPass()); // Delete dead instructions addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs + PM->doInitialization(); + } // We protect the creation of IR with the executionEngine lock because From nicolas.geoffray at lip6.fr Mon Jul 20 14:13:35 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 21:13:35 -0000 Subject: [vmkit-commits] [vmkit] r76471 - /vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Message-ID: <200907202113.n6KLDZIY013677@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 16:13:35 2009 New Revision: 76471 URL: http://llvm.org/viewvc/llvm-project?rev=76471&view=rev Log: Apparently, MacosX requires to return the address for it to work. Not really sure why yet... Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=76471&r1=76470&r2=76471&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Mon Jul 20 16:13:35 2009 @@ -391,9 +391,9 @@ } // Never throws. -extern "C" void jnjvmGetSJLJBuffer(uint32* localReferencesNumber, - uint32** oldLocalReferencesNumber, - void* newBuffer, void** oldBuffer) { +extern "C" void** jnjvmGetSJLJBuffer(uint32* localReferencesNumber, + uint32** oldLocalReferencesNumber, + void* newBuffer, void** oldBuffer) { JavaThread* th = JavaThread::get(); *oldBuffer = th->currentSjljBuffer; @@ -407,8 +407,9 @@ // Start JNI because the next instruction after setjmp is a call to a // JNI function. th->startJNI(2); + void** val = (void**)th->addresses.back(); - return; + return val; } // Never throws. From nicolas.geoffray at lip6.fr Mon Jul 20 14:19:01 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 21:19:01 -0000 Subject: [vmkit-commits] [vmkit] r76474 - /vmkit/trunk/tools/vmkit/Launcher.cpp Message-ID: <200907202119.n6KLJ1JJ013862@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 16:19:00 2009 New Revision: 76474 URL: http://llvm.org/viewvc/llvm-project?rev=76474&view=rev Log: Force the initialization of passes. Modified: vmkit/trunk/tools/vmkit/Launcher.cpp Modified: vmkit/trunk/tools/vmkit/Launcher.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmkit/Launcher.cpp?rev=76474&r1=76473&r2=76474&view=diff ============================================================================== --- vmkit/trunk/tools/vmkit/Launcher.cpp (original) +++ vmkit/trunk/tools/vmkit/Launcher.cpp Mon Jul 20 16:19:00 2009 @@ -105,7 +105,8 @@ // If -std-compile-opts was specified at the end of the pass list, add them. if (StandardCompileOpts) { mvm::MvmModule::AddStandardCompilePasses(); - } + } + Passes->doInitialization(); } From nicolas.geoffray at lip6.fr Mon Jul 20 14:24:43 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 21:24:43 -0000 Subject: [vmkit-commits] [vmkit] r76478 - /vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Message-ID: <200907202124.n6KLOhdA014156@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 16:24:43 2009 New Revision: 76478 URL: http://llvm.org/viewvc/llvm-project?rev=76478&view=rev Log: Disable stack traces. Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=76478&r1=76477&r2=76478&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 20 16:24:43 2009 @@ -49,6 +49,7 @@ void MvmModule::initialise(CodeGenOpt::Level level, Module* M, TargetMachine* T) { llvm::NoFramePointerElim = true; + llvm::DisablePrettyStackTrace = true; #if DWARF_EXCEPTIONS llvm::ExceptionHandling = true; #else From nicolas.geoffray at lip6.fr Mon Jul 20 15:09:52 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 22:09:52 -0000 Subject: [vmkit-commits] [vmkit] r76488 - /vmkit/trunk/tools/vmjc/vmjc.cpp Message-ID: <200907202209.n6KM9qr6015987@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 17:09:52 2009 New Revision: 76488 URL: http://llvm.org/viewvc/llvm-project?rev=76488&view=rev Log: Force the initialization of passes. Modified: vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=76488&r1=76487&r2=76488&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Mon Jul 20 17:09:52 2009 @@ -164,8 +164,9 @@ // If -std-compile-opts was specified at the end of the pass list, add them. if (StandardCompileOpts) { mvm::MvmModule::AddStandardCompilePasses(); - } + } + Passes->doInitialization(); } From nicolas.geoffray at lip6.fr Mon Jul 20 15:27:37 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 20 Jul 2009 22:27:37 -0000 Subject: [vmkit-commits] [vmkit] r76491 - /vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Message-ID: <200907202227.n6KMRbO5016535@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 20 17:27:37 2009 New Revision: 76491 URL: http://llvm.org/viewvc/llvm-project?rev=76491&view=rev Log: Add llvm_gcroot's. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=76491&r1=76490&r2=76491&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Mon Jul 20 17:27:37 2009 @@ -935,11 +935,14 @@ } ArrayObject* JavaMethod::getParameterTypes(JnjvmClassLoader* loader) { + + ArrayObject* res = 0; + llvm_gcroot(res, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); Signdef* sign = getSignature(); Typedef* const* arguments = sign->getArgumentsType(); - ArrayObject* res = - (ArrayObject*)vm->upcalls->classArrayClass->doNew(sign->nbArguments, vm); + res = (ArrayObject*)vm->upcalls->classArrayClass->doNew(sign->nbArguments,vm); for (uint32 index = 0; index < sign->nbArguments; ++index) { res->elements[index] = getClassType(vm, loader, arguments[index]); @@ -956,6 +959,10 @@ } ArrayObject* JavaMethod::getExceptionTypes(JnjvmClassLoader* loader) { + + ArrayObject* res = 0; + llvm_gcroot(res, 0); + Attribut* exceptionAtt = lookupAttribut(Attribut::exceptionsAttribut); Jnjvm* vm = JavaThread::get()->getJVM(); if (exceptionAtt == 0) { @@ -964,16 +971,14 @@ UserConstantPool* ctp = classDef->getConstantPool(); Reader reader(exceptionAtt, classDef->getBytes()); uint16 nbe = reader.readU2(); - ArrayObject* res = - (ArrayObject*)vm->upcalls->classArrayClass->doNew(nbe, vm); + res = (ArrayObject*)vm->upcalls->classArrayClass->doNew(nbe, vm); for (uint16 i = 0; i < nbe; ++i) { uint16 idx = reader.readU2(); UserCommonClass* cl = ctp->loadClass(idx); assert(cl->asClass() && "Wrong exception type"); cl->asClass()->resolveClass(); - JavaObject* obj = cl->getClassDelegatee(vm); - res->elements[i] = obj; + res->elements[i] = cl->getClassDelegatee(vm); } return res; } @@ -1020,6 +1025,9 @@ UserCommonClass* UserCommonClass::resolvedImplClass(Jnjvm* vm, JavaObject* clazz, bool doClinit) { + + llvm_gcroot(clazz, 0); + UserCommonClass* cl = ((JavaObjectClass*)clazz)->getClass(); if (cl->isClass()) { cl->asClass()->resolveClass(); @@ -1204,9 +1212,12 @@ ArrayUInt16* JavaMethod::toString() const { + Jnjvm* vm = JavaThread::get()->getJVM(); uint32 size = classDef->name->size + name->size + type->size + 1; ArrayUInt16* res = (ArrayUInt16*)vm->upcalls->ArrayOfChar->doNew(size, vm); + llvm_gcroot(res, 0); + uint32 i = 0; for (sint32 j = 0; j < classDef->name->size; ++j) { From nicolas.geoffray at lip6.fr Tue Jul 21 00:38:11 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 07:38:11 -0000 Subject: [vmkit-commits] [vmkit] r76544 - in /vmkit/trunk/lib/JnJVM: Classpath/ClasspathVMClassLoader.inc Classpath/ClasspathVMThrowable.inc Compiler/JavaAOTCompiler.cpp Compiler/JavaJIT.cpp VMCore/JavaClass.cpp VMCore/JavaClass.h VMCore/JavaConstantPool.cpp VMCore/Reader.h VMCore/Zip.cpp Message-ID: <200907210738.n6L7cD3O003395@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 02:38:09 2009 New Revision: 76544 URL: http://llvm.org/viewvc/llvm-project?rev=76544&view=rev Log: Add an indirection to manipulate an array in the Reader class. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp vmkit/trunk/lib/JnJVM/VMCore/Reader.h vmkit/trunk/lib/JnJVM/VMCore/Zip.cpp Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClassLoader.inc Tue Jul 21 02:38:09 2009 @@ -130,7 +130,7 @@ Jnjvm* vm = JavaThread::get()->getJVM(); // Before creating a class, do a check on the bytes. - Reader reader(bytes); + Reader reader(&bytes); uint32 magic = reader.readU4(); if (magic != Jnjvm::Magic) { JavaThread::get()->getJVM()->classFormatError("bad magic number"); Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc Tue Jul 21 02:38:09 2009 @@ -90,7 +90,7 @@ // We don't have the bytes if the class was vmjc'ed. if (sourceAtt && cl->getBytes()) { - Reader reader(sourceAtt, cl->getBytes()); + Reader reader(sourceAtt, cl->getBytesPtr()); uint16 index = reader.readU2(); sourceName = vm->internalUTF8ToStr(cl->getConstantPool()->UTF8At(index)); } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Tue Jul 21 02:38:09 2009 @@ -379,7 +379,7 @@ Elts.push_back(Mod.getContext().getNullValue(Ty)); } } else { - Reader reader(attribut, cl->bytes); + Reader reader(attribut, &(cl->bytes)); JavaConstantPool * ctpInfo = cl->ctpInfo; uint16 idx = reader.readU2(); if (type->isPrimitive()) { Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 21 02:38:09 2009 @@ -668,7 +668,7 @@ abort(); } - Reader reader(codeAtt, compilingClass->bytes); + Reader reader(codeAtt, &(compilingClass->bytes)); /* uint16 maxStack = */ reader.readU2(); uint16 maxLocals = reader.readU2(); uint32 codeLen = reader.readU4(); @@ -801,7 +801,7 @@ abort(); } - Reader reader(codeAtt, compilingClass->bytes); + Reader reader(codeAtt, &(compilingClass->bytes)); /* uint16 maxStack = */ reader.readU2(); uint16 maxLocals = reader.readU2(); uint32 codeLen = reader.readU4(); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Tue Jul 21 02:38:09 2009 @@ -584,7 +584,7 @@ if (!attribut) { InitField(obj); } else { - Reader reader(attribut, classDef->bytes); + Reader reader(attribut, &(classDef->bytes)); JavaConstantPool * ctpInfo = classDef->ctpInfo; uint16 idx = reader.readU2(); if (type->isPrimitive()) { @@ -685,7 +685,7 @@ Attribut* codeAtt = meth.lookupAttribut(Attribut::codeAttribut); if (codeAtt) { - Reader reader(codeAtt, meth.classDef->bytes); + Reader reader(codeAtt, &(meth.classDef->bytes)); //uint16 maxStack = reader.readU2(); //uint16 maxLocals = @@ -821,7 +821,7 @@ PRINT_DEBUG(JNJVM_LOAD, 0, LIGHT_GREEN, "reading ", 0); PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "%s\n", printString()); - Reader reader(bytes); + Reader reader(&bytes); uint32 magic = reader.readU4(); assert(magic == Jnjvm::Magic && "I've created a class but magic is no good!"); @@ -897,7 +897,7 @@ if (!innerOuterResolved) { Attribut* attribut = lookupAttribut(Attribut::innerClassesAttribut); if (attribut != 0) { - Reader reader(attribut, getBytes()); + Reader reader(attribut, getBytesPtr()); uint16 nbi = reader.readU2(); for (uint16 i = 0; i < nbi; ++i) { uint16 inner = reader.readU2(); @@ -969,7 +969,7 @@ return (ArrayObject*)vm->upcalls->classArrayClass->doNew(0, vm); } else { UserConstantPool* ctp = classDef->getConstantPool(); - Reader reader(exceptionAtt, classDef->getBytes()); + Reader reader(exceptionAtt, classDef->getBytesPtr()); uint16 nbe = reader.readU2(); res = (ArrayObject*)vm->upcalls->classArrayClass->doNew(nbe, vm); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h Tue Jul 21 02:38:09 2009 @@ -687,6 +687,10 @@ return bytes; } + ArrayUInt8** getBytesPtr() { + return &bytes; + } + /// resolveInnerOuterClasses - Resolve the inner/outer information. /// void resolveInnerOuterClasses(); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp Tue Jul 21 02:38:09 2009 @@ -187,7 +187,7 @@ } if (!ctpRes[entry]) { - Reader reader(classDef->bytes, ctpDef[entry]); + Reader reader(&(classDef->bytes), ctpDef[entry]); uint32 len = reader.readU2(); uint16* buf = (uint16*)alloca(len * sizeof(uint16)); uint32 n = 0; Modified: vmkit/trunk/lib/JnJVM/VMCore/Reader.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Reader.h?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Reader.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Reader.h Tue Jul 21 02:38:09 2009 @@ -24,12 +24,14 @@ class Reader { public: - ArrayUInt8* bytes; + // bytes - Pointer to a reference array. The array is not manipulated directly + // in order to support copying GC. + ArrayUInt8** bytes; uint32 min; uint32 cursor; uint32 max; - Reader(Attribut* attr, ArrayUInt8* bytes) { + Reader(Attribut* attr, ArrayUInt8** bytes) { this->bytes = bytes; this->cursor = attr->start; this->min = attr->start; @@ -82,11 +84,11 @@ const char* filename); uint8 readU1() { - return bytes->elements[cursor++]; + return (*bytes)->elements[cursor++]; } sint8 readS1() { - return bytes->elements[cursor++]; + return (*bytes)->elements[cursor++]; } uint16 readU2() { @@ -119,8 +121,8 @@ return tmp | ((sint64)(readS8())); } - Reader(ArrayUInt8* array, uint32 start = 0, uint32 end = 0) { - if (!end) end = array->size; + Reader(ArrayUInt8** array, uint32 start = 0, uint32 end = 0) { + if (!end) end = (*array)->size; this->bytes = array; this->cursor = start; this->min = start; Modified: vmkit/trunk/lib/JnJVM/VMCore/Zip.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Zip.cpp?rev=76544&r1=76543&r2=76544&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Zip.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Zip.cpp Tue Jul 21 02:38:09 2009 @@ -73,7 +73,7 @@ sint32 minOffs = 0; sint32 st = END_CENTRAL_DIRECTORY_FILE_HEADER_SIZE + 4; - Reader reader(bytes); + Reader reader(&bytes); curOffs = reader.max; if (curOffs >= (65535 + END_CENTRAL_DIRECTORY_FILE_HEADER_SIZE + 4)) { minOffs = curOffs - (65535 + END_CENTRAL_DIRECTORY_FILE_HEADER_SIZE + 4); @@ -103,8 +103,8 @@ if (searchPos >= st) { sint32 searchPtr = temp + (searchPos - st); while (searchPtr > temp) { - if (reader.bytes->elements[searchPtr] == 'P' && - !(memcmp(&(reader.bytes->elements[searchPtr]), HDR_ENDCENTRAL, 4))) { + if ((*(reader.bytes))->elements[searchPtr] == 'P' && + !(memcmp(&((*(reader.bytes))->elements[searchPtr]), HDR_ENDCENTRAL, 4))) { sint32 offset = searchPtr + 4 + E_OFFSET_START_CENTRAL_DIRECTORY; reader.cursor = offset; this->ofscd = readEndianDep4(reader); @@ -119,11 +119,11 @@ void ZipArchive::addFiles() { sint32 temp = ofscd; - Reader reader(bytes); + Reader reader(&bytes); reader.cursor = temp; while (true) { - if (memcmp(&(reader.bytes->elements[temp]), HDR_CENTRAL, 4)) return; + if (memcmp(&((*(reader.bytes))->elements[temp]), HDR_CENTRAL, 4)) return; ZipFile* ptr = new(allocator, "ZipFile") ZipFile(); reader.cursor = temp + 4 + C_COMPRESSION_METHOD; ptr->compressionMethod = readEndianDep2(reader); @@ -147,7 +147,8 @@ ptr->filename = (char*)allocator.Allocate(ptr->filenameLength + 1, "Zip file name"); - memcpy(ptr->filename, &(reader.bytes->elements[temp]), ptr->filenameLength); + memcpy(ptr->filename, &((*(reader.bytes))->elements[temp]), + ptr->filenameLength); ptr->filename[ptr->filenameLength] = 0; if (ptr->filename[ptr->filenameLength - 1] != PATH_SEPARATOR) { @@ -166,10 +167,10 @@ char* ptr = (char*)array->elements; uint32 temp = 0; - Reader reader(bytes); + Reader reader(&bytes); reader.cursor = file->rolh; - if (!(memcmp(&(reader.bytes->elements[file->rolh]), HDR_LOCAL, 4))) { + if (!(memcmp(&((*(reader.bytes))->elements[file->rolh]), HDR_LOCAL, 4))) { reader.cursor += 4; temp = reader.cursor; reader.cursor += L_FILENAME_LENGTH; @@ -180,7 +181,7 @@ temp + extraFieldLength + filenameLength + LOCAL_FILE_HEADER_SIZE; if (file->compressionMethod == ZIP_STORE) { - memcpy(ptr, &(reader.bytes->elements[reader.cursor]), file->ucsize); + memcpy(ptr, &((*(reader.bytes))->elements[reader.cursor]), file->ucsize); return 1; } else if (file->compressionMethod == ZIP_DEFLATE) { z_stream stre; @@ -200,7 +201,7 @@ while (bytesLeft) { uint32 size = 0; - stre.next_in = &(reader.bytes->elements[reader.cursor]); + stre.next_in = &((*(reader.bytes))->elements[reader.cursor]); if (bytesLeft > 1024) size = 1024; else size = bytesLeft; From nicolas.geoffray at lip6.fr Tue Jul 21 00:47:08 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 07:47:08 -0000 Subject: [vmkit-commits] [vmkit] r76545 - /vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Message-ID: <200907210747.n6L7l86H008063@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 02:47:07 2009 New Revision: 76545 URL: http://llvm.org/viewvc/llvm-project?rev=76545&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp?rev=76545&r1=76544&r2=76545&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Tue Jul 21 02:47:07 2009 @@ -132,7 +132,7 @@ Value* Arg = Cmp->getOperand(0); if (isVirtual(meth->access) && Arg == F.arg_begin()) { Changed = true; - Cmp->replaceAllUsesWith(ConstantInt::getFalse()); + Cmp->replaceAllUsesWith(Context->getConstantIntFalse()); Cmp->eraseFromParent(); break; } @@ -141,7 +141,7 @@ Instruction* CI = Ca.getInstruction(); if (CI && Ca.getCalledValue() == module->JavaObjectAllocateFunction) { Changed = true; - Cmp->replaceAllUsesWith(ConstantInt::getFalse()); + Cmp->replaceAllUsesWith(Context->getConstantIntFalse()); Cmp->eraseFromParent(); break; } @@ -551,7 +551,7 @@ Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, CurVT, VT2, ""); - node->addIncoming(ConstantInt::getTrue(), CI->getParent()); + node->addIncoming(Context->getConstantIntTrue(), CI->getParent()); BranchInst::Create(CurEndBlock, FailedBlock, res, CI); Value* Args[2] = { VT1, VT2 }; @@ -670,9 +670,9 @@ // Final block, that gets the result. PHINode* node = PHINode::Create(Type::Int1Ty, "", BB9); node->reserveOperandSpace(3); - node->addIncoming(ConstantInt::getTrue(), CI->getParent()); - node->addIncoming(ConstantInt::getFalse(), BB7); - node->addIncoming(ConstantInt::getTrue(), BB5); + node->addIncoming(Context->getConstantIntTrue(), CI->getParent()); + node->addIncoming(Context->getConstantIntFalse(), BB7); + node->addIncoming(Context->getConstantIntTrue(), BB5); // Don't forget to jump to the next block. BranchInst::Create(EndBlock, BB9); From nicolas.geoffray at lip6.fr Tue Jul 21 01:04:08 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 08:04:08 -0000 Subject: [vmkit-commits] [vmkit] r76548 - /vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp Message-ID: <200907210804.n6L84IYM011652@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 03:04:01 2009 New Revision: 76548 URL: http://llvm.org/viewvc/llvm-project?rev=76548&view=rev Log: Fix 80-col violations. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp?rev=76548&r1=76547&r2=76548&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaConstantPool.cpp Tue Jul 21 03:04:01 2009 @@ -94,8 +94,9 @@ return 1; } -uint32 JavaConstantPool::CtpReaderFieldref(JavaConstantPool* ctp, Reader& reader, - uint32 index) { +uint32 JavaConstantPool::CtpReaderFieldref(JavaConstantPool* ctp, + Reader& reader, uint32 index) { + uint32 entry = reader.readU4(); ctp->ctpDef[index] = entry; PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, @@ -105,7 +106,7 @@ } uint32 JavaConstantPool::CtpReaderString(JavaConstantPool* ctp, Reader& reader, - uint32 index) { + uint32 index) { uint16 entry = reader.readU2(); ctp->ctpDef[index] = entry; PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] \tutf8 is at %d\n", @@ -113,8 +114,9 @@ return 1; } -uint32 JavaConstantPool::CtpReaderMethodref(JavaConstantPool* ctp, Reader& reader, - uint32 index) { +uint32 JavaConstantPool::CtpReaderMethodref(JavaConstantPool* ctp, + Reader& reader, + uint32 index) { uint32 entry = reader.readU4(); ctp->ctpDef[index] = entry; PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, @@ -124,8 +126,8 @@ } uint32 JavaConstantPool::CtpReaderInterfaceMethodref(JavaConstantPool* ctp, - Reader& reader, - uint32 index) { + Reader& reader, + uint32 index) { uint32 entry = reader.readU4(); ctp->ctpDef[index] = entry; PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, @@ -135,7 +137,7 @@ } uint32 JavaConstantPool::CtpReaderLong(JavaConstantPool* ctp, Reader& reader, - uint32 index) { + uint32 index) { ctp->ctpDef[index + 1] = reader.readU4(); ctp->ctpDef[index] = reader.readU4(); PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] %d %d\n", index, @@ -144,7 +146,7 @@ } uint32 JavaConstantPool::CtpReaderDouble(JavaConstantPool* ctp, Reader& reader, - uint32 index) { + uint32 index) { ctp->ctpDef[index + 1] = reader.readU4(); ctp->ctpDef[index] = reader.readU4(); PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] %d %d\n", index, From nicolas.geoffray at lip6.fr Tue Jul 21 01:07:56 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 08:07:56 -0000 Subject: [vmkit-commits] [vmkit] r76549 - /vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Message-ID: <200907210807.n6L87xPX011770@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 03:07:43 2009 New Revision: 76549 URL: http://llvm.org/viewvc/llvm-project?rev=76549&view=rev Log: Add a comment. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp?rev=76549&r1=76548&r2=76549&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Tue Jul 21 03:07:43 2009 @@ -62,6 +62,12 @@ buf += 8; \ }\ +//===----------------------------------------------------------------------===// +// We do not need to have special care on the GC-pointers manipulated in these +// functions (this and the buffer). Once the Java function is called, they +// are never used (because the buffer is alloca'd and "this" is only used when +// calling). +//===----------------------------------------------------------------------===// #if defined(DWARF_EXCEPTIONS) From nicolas.geoffray at lip6.fr Tue Jul 21 01:38:58 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 08:38:58 -0000 Subject: [vmkit-commits] [vmkit] r76550 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaObject.cpp JnjvmClassLoader.cpp Message-ID: <200907210839.n6L8d3MH012862@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 03:38:40 2009 New Revision: 76550 URL: http://llvm.org/viewvc/llvm-project?rev=76550&view=rev Log: Add llvm_gcroot's. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp?rev=76550&r1=76549&r2=76550&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp Tue Jul 21 03:38:40 2009 @@ -19,6 +19,7 @@ using namespace jnjvm; LockObj* LockObj::allocate(JavaObject* owner) { + llvm_gcroot(owner, 0); #ifdef USE_GC_BOEHM LockObj* res = new LockObj(); #else @@ -34,9 +35,12 @@ } void JavaObject::waitIntern(struct timeval* info, bool timed) { + LockObj* l = 0; + llvm_gcroot(this, 0); + llvm_gcroot(l, 0); if (owner()) { - LockObj * l = lock.changeToFatlock(this); + l = lock.changeToFatlock(this); JavaThread* thread = JavaThread::get(); thread->waitsOn = l; mvm::Cond& varcondThread = thread->varcond; @@ -128,16 +132,22 @@ } void JavaObject::wait() { + llvm_gcroot(this, 0); waitIntern(0, false); } void JavaObject::timedWait(struct timeval& info) { + llvm_gcroot(this, 0); waitIntern(&info, true); } void JavaObject::notify() { + LockObj* l = 0; + llvm_gcroot(this, 0); + llvm_gcroot(l, 0); + if (owner()) { - LockObj * l = lock.getFatLock(); + l = lock.getFatLock(); if (l) { JavaThread* cur = l->firstThread; if (cur) { @@ -177,8 +187,12 @@ } void JavaObject::notifyAll() { + LockObj* l = 0; + llvm_gcroot(this, 0); + llvm_gcroot(l, 0); + if (owner()) { - LockObj * l = lock.getFatLock(); + l = lock.getFatLock(); if (l) { JavaThread* cur = l->firstThread; if (cur) { @@ -203,6 +217,8 @@ const Typedef* signature) { JavaObject* obj = this; + llvm_gcroot(obj, 0); + if (!signature->isPrimitive()) { if (obj && !(obj->getClass()->isOfTypeName(signature->getName()))) { vm->illegalArgumentException("wrong type argument"); @@ -343,6 +359,8 @@ } bool JavaObject::instanceOf(UserCommonClass* cl) { + llvm_gcroot(this, 0); + if (!this) return false; else return this->getClass()->isAssignableFrom(cl); } Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=76550&r1=76549&r2=76550&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Tue Jul 21 03:38:40 2009 @@ -341,6 +341,7 @@ char* buf = (char*)alloca(strLen + alen + 7); sprintf(buf, "%s%s.class", str, asciiz); + // This array is not allocated by the GC. res = Reader::openFile(this, buf); if (res) return res; } @@ -351,6 +352,7 @@ ZipArchive* archive = *i; char* buf = (char*)alloca(alen + 7); sprintf(buf, "%s.class", asciiz); + // This array is not allocated by the GC. res = Reader::openZip(this, archive, buf); if (res) return res; } @@ -362,10 +364,13 @@ UserClass* JnjvmBootstrapLoader::internalLoad(const UTF8* name, bool doResolve, JavaString* strName) { - + + llvm_gcroot(strName, 0); + UserCommonClass* cl = lookupClass(name); if (!cl) { + // This array is not allocated by the GC. ArrayUInt8* bytes = openName(name); if (bytes) { cl = constructClass(name, bytes); @@ -382,6 +387,10 @@ UserClass* JnjvmClassLoader::internalLoad(const UTF8* name, bool doResolve, JavaString* strName) { + JavaObject* obj = 0; + llvm_gcroot(strName, 0); + llvm_gcroot(obj, 0); + UserCommonClass* cl = lookupClass(name); if (!cl) { @@ -390,10 +399,8 @@ if (!strName) { strName = JavaString::internalToJava(name, isolate); } - JavaObject* obj = (JavaObject*) - upcalls->loadInClassLoader->invokeJavaObjectVirtual(isolate, forCtp, - javaLoader, strName, - doResolve); + obj = upcalls->loadInClassLoader->invokeJavaObjectVirtual(isolate, forCtp, + javaLoader, strName, doResolve); cl = (UserCommonClass*)((JavaObjectClass*)obj)->getClass(); } @@ -407,7 +414,8 @@ UserClass* JnjvmClassLoader::loadName(const UTF8* name, bool doResolve, bool doThrow, JavaString* strName) { - + + llvm_gcroot(strName, 0); UserClass* cl = internalLoad(name, doResolve, strName); @@ -511,6 +519,8 @@ bool doResolve, bool doThrow, JavaString* strName) { + llvm_gcroot(strName, 0); + if (name->size == 0) { return 0; } else if (name->elements[0] == I_TAB) { @@ -564,6 +574,8 @@ JnjvmClassLoader::loadClassFromJavaString(JavaString* str, bool doResolve, bool doThrow) { + llvm_gcroot(str, 0); + UTF8* name = (UTF8*)alloca(sizeof(UTF8) + str->count * sizeof(uint16)); if (name) { @@ -591,6 +603,8 @@ UserCommonClass* JnjvmClassLoader::lookupClassFromJavaString(JavaString* str) { + llvm_gcroot(str, 0); + UTF8* name = (UTF8*)alloca(sizeof(UTF8) + str->count * sizeof(uint16)); if (name) { name->size = str->count; @@ -653,6 +667,9 @@ UserClass* JnjvmClassLoader::constructClass(const UTF8* name, ArrayUInt8* bytes) { + + // The array of bytes might be GC-allocated or malloc'd. Consider + // that this function can never be interrupted. assert(bytes && "constructing a class without bytes"); classes->lock.lock(); ClassMap::iterator End = classes->map.end(); @@ -831,12 +848,17 @@ JnjvmClassLoader* JnjvmClassLoader::getJnjvmLoaderFromJavaObject(JavaObject* loader, Jnjvm* vm) { + VMClassLoader* vmdata = 0 + + llvm_gcroot(loader, 0); + llvm_gcroot(vmdata, 0); + if (loader == 0) return vm->bootstrapLoader; JnjvmClassLoader* JCL = 0; Classpath* upcalls = vm->bootstrapLoader->upcalls; - VMClassLoader* vmdata = + vmdata = (VMClassLoader*)(upcalls->vmdataClassLoader->getObjectField(loader)); if (!vmdata) { From nicolas.geoffray at lip6.fr Tue Jul 21 01:52:21 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 08:52:21 -0000 Subject: [vmkit-commits] [vmkit] r76552 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaRuntimeJIT.cpp JavaString.cpp JavaThread.cpp Message-ID: <200907210852.n6L8qWCE013263@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 03:52:02 2009 New Revision: 76552 URL: http://llvm.org/viewvc/llvm-project?rev=76552&view=rev Log: Add llvm_gcroot's. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=76552&r1=76551&r2=76552&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Tue Jul 21 03:52:02 2009 @@ -28,6 +28,8 @@ // Throws if the method is not found. extern "C" void* jnjvmInterfaceLookup(CacheNode* cache, JavaObject *obj) { + llvm_gcroot(obj, 0); + void* res = 0; BEGIN_NATIVE_EXCEPTION(1) @@ -285,6 +287,7 @@ // Calls Java code. extern "C" JavaObject* jnjvmRuntimeDelegatee(UserCommonClass* cl) { JavaObject* res = 0; + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(1) Jnjvm* vm = JavaThread::get()->getJVM(); @@ -303,9 +306,14 @@ static JavaArray* multiCallNewIntern(UserClassArray* cl, uint32 len, sint32* dims, Jnjvm* vm) { assert(len > 0 && "Negative size given by VMKit"); + JavaArray* _res = cl->doNew(dims[0], vm); + ArrayObject* res = 0; + llvm_gcroot(_res, 0); + llvm_gcroot(res, 0); + if (len > 1) { - ArrayObject* res = (ArrayObject*)_res; + res = (ArrayObject*)_res; UserCommonClass* _base = cl->baseClass(); assert(_base->isArray() && "Base class not an array"); UserClassArray* base = (UserClassArray*)_base; @@ -327,6 +335,7 @@ // Throws if one of the dimension is negative. extern "C" JavaArray* jnjvmMultiCallNew(UserClassArray* cl, uint32 len, ...) { JavaArray* res = 0; + llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(1) @@ -414,11 +423,13 @@ // Never throws. extern "C" void jnjvmJavaObjectAquire(JavaObject* obj) { + llvm_gcroot(obj, 0); obj->acquire(); } // Never throws. extern "C" void jnjvmJavaObjectRelease(JavaObject* obj) { + llvm_gcroot(obj, 0); obj->release(); } @@ -537,6 +548,9 @@ extern "C" JavaObject* jnjvmClassCastException(JavaObject* obj, UserCommonClass* cl) { JavaObject *exc = 0; + llvm_gcroot(obj, 0); + llvm_gcroot(exc, 0); + JavaThread *th = JavaThread::get(); BEGIN_NATIVE_EXCEPTION(1) @@ -558,6 +572,9 @@ extern "C" JavaObject* jnjvmIndexOutOfBoundsException(JavaObject* obj, sint32 index) { JavaObject *exc = 0; + llvm_gcroot(obj, 0); + llvm_gcroot(exc, 0); + JavaThread *th = JavaThread::get(); BEGIN_NATIVE_EXCEPTION(1) Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp?rev=76552&r1=76551&r2=76552&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp Tue Jul 21 03:52:02 2009 @@ -20,6 +20,8 @@ JavaVirtualTable* JavaString::internStringVT = 0; JavaString* JavaString::stringDup(const ArrayUInt16*& array, Jnjvm* vm) { + llvm_gcroot(array, 0); + UserClass* cl = vm->upcalls->newString; JavaString* res = (JavaString*)cl->doNew(vm); @@ -47,6 +49,8 @@ } const ArrayUInt16* JavaString::strToArray(Jnjvm* vm) { + llvm_gcroot(this, 0); + assert(value && "String without an array?"); if (offset || (count != value->size)) { ArrayUInt16* array = @@ -63,14 +67,20 @@ } void JavaString::stringDestructor(JavaString* str) { + llvm_gcroot(str, 0); + Jnjvm* vm = JavaThread::get()->getJVM(); assert(vm && "No vm when destroying a string"); if (str->value) vm->hashStr.removeUnlocked(str->value, str); } JavaString* JavaString::internalToJava(const UTF8* name, Jnjvm* vm) { - ArrayUInt16* array = - (ArrayUInt16*)vm->upcalls->ArrayOfChar->doNew(name->size, vm); + + ArrayUInt16* array = 0; + llvm_gcroot(this, 0); + llvm_gcroot(array, 0); + + array = (ArrayUInt16*)vm->upcalls->ArrayOfChar->doNew(name->size, vm); uint16* java = array->elements; for (sint32 i = 0; i < name->size; i++) { @@ -83,6 +93,8 @@ } const UTF8* JavaString::javaToInternal(UTF8Map* map) const { + llvm_gcroot(this, 0); + uint16* java = (uint16*)alloca(sizeof(uint16) * count); for (sint32 i = 0; i < count; ++i) { Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp?rev=76552&r1=76551&r2=76552&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Tue Jul 21 03:52:02 2009 @@ -24,6 +24,9 @@ const unsigned int JavaThread::StateInterrupted = 2; JavaThread::JavaThread(JavaObject* thread, JavaObject* vmth, Jnjvm* isolate) { + llvm_gcroot(thread, 0); + llvm_gcroot(vmth, 0); + javaThread = thread; vmThread = vmth; MyVM = isolate; @@ -58,6 +61,7 @@ extern "C" void __cxa_throw(void*, void*, void*); void JavaThread::throwException(JavaObject* obj) { + llvm_gcroot(obj, 0); JavaThread* th = JavaThread::get(); assert(th->pendingException == 0 && "pending exception already there?"); th->pendingException = obj; @@ -195,6 +199,10 @@ } JavaObject* JavaThread::getNonNullClassLoader() { + + JavaObject* obj = 0; + llvm_gcroot(obj, 0); + std::vector::iterator it = addresses.end(); // Loop until we cross the first Java frame. @@ -210,7 +218,7 @@ void* ip = FRAME_IP(addr); JavaMethod* meth = getJVM()->IPToMethod(ip); JnjvmClassLoader* loader = meth->classDef->classLoader; - JavaObject* obj = loader->getJavaClassLoader(); + obj = loader->getJavaClassLoader(); if (obj) return obj; addr = (void**)addr[0]; // We end walking the stack when we cross a native -> Java call. Here @@ -298,6 +306,8 @@ JavaObject** JNILocalReferences::addJNIReference(JavaThread* th, JavaObject* obj) { + llvm_gcroot(obj, 0); + if (length == MAXIMUM_REFERENCES) { JNILocalReferences* next = new JNILocalReferences(); th->localJNIRefs = next; From nicolas.geoffray at lip6.fr Tue Jul 21 02:58:02 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 09:58:02 -0000 Subject: [vmkit-commits] [vmkit] r76560 - /vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp Message-ID: <200907210958.n6L9wBwk020334@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 04:57:29 2009 New Revision: 76560 URL: http://llvm.org/viewvc/llvm-project?rev=76560&view=rev Log: Add llvm_gcroot's. Also remove an unfortunate abort. Modified: vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp?rev=76560&r1=76559&r2=76560&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp Tue Jul 21 04:57:29 2009 @@ -87,6 +87,7 @@ // Local object references. JavaObject* meth = *(JavaObject**)method; + llvm_gcroot(meth, 0); Jnjvm* vm = myVM(env); Classpath* upcalls = vm->upcalls; @@ -116,6 +117,8 @@ // Local object references. JavaObject* sub = *(JavaObject**)_sub; JavaObject* sup = *(JavaObject**)_sup; + llvm_gcroot(sub, 0); + llvm_gcroot(sup, 0); Jnjvm* vm = JavaThread::get()->getJVM(); UserCommonClass* cl2 = @@ -144,6 +147,9 @@ // Local object references. JavaObject* Cl = *(JavaObject**)_Cl; + JavaObject* res = 0; + llvm_gcroot(Cl, 0); + llvm_gcroot(res, 0); Jnjvm* vm = JavaThread::get()->getJVM(); @@ -152,7 +158,7 @@ if (!cl->isClass()) return 0; UserClass* realCl = cl->asClass(); - JavaObject* res = realCl->doNew(vm); + res = realCl->doNew(vm); JavaMethod* init = realCl->lookupMethod(vm->bootstrapLoader->initName, vm->bootstrapLoader->initExceptionSig, false, true, 0); @@ -237,6 +243,8 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; JavaObject* res = 0; + llvm_gcroot(clazz, 0); + llvm_gcroot(res, 0); JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); @@ -261,6 +269,8 @@ // Local object references JavaObject* clazz = *(JavaObject**)_clazz; JavaObject* res = 0; + llvm_gcroot(clazz, 0); + llvm_gcroot(res, 0); JavaMethod* meth = (JavaMethod*)methodID; JavaThread* th = JavaThread::get(); @@ -339,6 +349,8 @@ // Local object references JavaObject* clazz = *(JavaObject**)_clazz; JavaObject* res = 0; + llvm_gcroot(clazz, 0); + llvm_gcroot(res, 0); JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); @@ -368,6 +380,7 @@ // Local object references JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); @@ -417,6 +430,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); @@ -448,13 +462,16 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + JavaObject* res = 0; + llvm_gcroot(obj, 0); + llvm_gcroot(res, 0); JavaMethod* meth = (JavaMethod*)methodID; JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); - JavaObject* res = meth->invokeJavaObjectVirtualAP(vm, cl, obj, ap, true); + res = meth->invokeJavaObjectVirtualAP(vm, cl, obj, ap, true); va_end(ap); return (jobject)th->pushJNIRef(res); @@ -474,6 +491,8 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; JavaObject* res = 0; + llvm_gcroot(obj, 0); + llvm_gcroot(res, 0); JavaMethod* meth = (JavaMethod*)methodID; JavaThread* th = JavaThread::get(); @@ -509,6 +528,7 @@ // Local object references. JavaObject* self = *(JavaObject**)_obj; + llvm_gcroot(self, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -533,6 +553,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -568,6 +589,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -604,8 +626,8 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; - - + llvm_gcroot(obj, 0); + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); @@ -641,6 +663,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -673,6 +696,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -697,6 +721,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -735,6 +760,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -767,6 +793,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -789,6 +816,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -821,6 +849,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -843,6 +872,8 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); + JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* cl = getClassFromVirtualMethod(vm, meth, obj->getClass()); @@ -874,6 +905,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -894,6 +926,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1148,6 +1181,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1180,6 +1214,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); @@ -1209,6 +1244,8 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; JavaObject* res = 0; + llvm_gcroot(obj, 0); + llvm_gcroot(res, 0); JavaField* field = (JavaField*)fieldID; @@ -1229,6 +1266,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return (uint8)field->getInt8Field(obj); @@ -1244,6 +1282,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return (sint8)field->getInt8Field(obj); @@ -1259,6 +1298,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return (uint16)field->getInt16Field(obj); @@ -1274,6 +1314,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return (sint16)field->getInt16Field(obj); @@ -1289,6 +1330,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return (sint32)field->getInt32Field(obj); @@ -1304,6 +1346,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return (sint64)field->getLongField(obj); @@ -1319,6 +1362,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return field->getFloatField(obj); @@ -1334,6 +1378,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; return (jdouble)field->getDoubleField(obj); @@ -1350,6 +1395,8 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; JavaObject* value = *(JavaObject**)_value; + llvm_gcroot(obj, 0); + llvm_gcroot(value, 0); JavaField* field = (JavaField*)fieldID; field->setObjectField(obj, value); @@ -1365,6 +1412,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setInt8Field(obj, (uint8)value); @@ -1379,6 +1427,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setInt8Field(obj, (uint8)value); @@ -1393,6 +1442,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setInt16Field(obj, (uint16)value); @@ -1407,6 +1457,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setInt16Field(obj, (sint16)value); @@ -1421,6 +1472,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setInt32Field(obj, (sint32)value); @@ -1435,6 +1487,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setLongField(obj, (sint64)value); @@ -1449,6 +1502,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setFloatField(obj, (float)value); @@ -1463,6 +1517,7 @@ // Local object references. JavaObject* obj = *(JavaObject**)_obj; + llvm_gcroot(obj, 0); JavaField* field = (JavaField*)fieldID; field->setDoubleField(obj, (float)value); @@ -1478,6 +1533,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); @@ -1510,6 +1566,8 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; JavaObject* res = 0; + llvm_gcroot(clazz, 0); + llvm_gcroot(res, 0); JavaMethod* meth = (JavaMethod*)methodID; @@ -1535,6 +1593,8 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; JavaObject* res = 0; + llvm_gcroot(clazz, 0); + llvm_gcroot(res, 0); JavaMethod* meth = (JavaMethod*)methodID; JavaThread* th = JavaThread::get(); @@ -1569,6 +1629,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1589,6 +1650,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1614,6 +1676,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); va_list ap; va_start(ap, methodID); @@ -1636,6 +1699,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1664,6 +1728,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1683,6 +1748,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1712,6 +1778,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1732,6 +1799,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1760,6 +1828,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1779,6 +1848,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1808,6 +1878,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1828,6 +1899,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1859,6 +1931,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1879,6 +1952,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1909,6 +1983,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1928,6 +2003,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1957,6 +2033,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1975,6 +2052,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaMethod* meth = (JavaMethod*)methodID; Jnjvm* vm = JavaThread::get()->getJVM(); @@ -1999,6 +2077,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, clazz, true); @@ -2026,6 +2105,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); @@ -2045,6 +2125,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2063,6 +2144,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2081,6 +2163,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2099,6 +2182,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2117,6 +2201,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2135,6 +2220,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2153,6 +2239,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2171,6 +2258,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2191,6 +2279,8 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; JavaObject* value = *(JavaObject**)_value; + llvm_gcroot(clazz, 0); + llvm_gcroot(value, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2227,6 +2317,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2245,6 +2336,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2263,6 +2355,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2281,6 +2374,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2299,6 +2393,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2317,6 +2412,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2335,6 +2431,7 @@ // Local object references. JavaObject* clazz = *(JavaObject**)_clazz; + llvm_gcroot(clazz, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = (JavaField*)fieldID; @@ -2399,6 +2496,7 @@ // Local object references. JavaString* string = *(JavaString**)_string; + llvm_gcroot(string, 0); if (isCopy != 0) (*isCopy) = true; return string->strToAsciiz(); @@ -2419,6 +2517,7 @@ // Local object references. JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); return array->size; @@ -2436,6 +2535,9 @@ JavaObject* initialElement = _initialElement ? *(JavaObject**)_initialElement : 0; ArrayObject* res = 0; + llvm_gcroot(elementClass, 0); + llvm_gcroot(initialElement, 0); + llvm_gcroot(res, 0); JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); @@ -2469,6 +2571,8 @@ // Local object references. ArrayObject* array = *(ArrayObject**)_array; JavaObject* res = 0; + llvm_gcroot(array, 0); + llvm_gcroot(res, 0); JavaThread* th = JavaThread::get(); Jnjvm* vm = th->getJVM(); @@ -2494,6 +2598,8 @@ // Local object references. ArrayObject* array = *(ArrayObject**)_array; JavaObject* val = *(JavaObject**)_val; + llvm_gcroot(array, 0); + llvm_gcroot(val, 0); if (index >= array->size) JavaThread::get()->getJVM()->indexOutOfBounds(array, index); @@ -2625,6 +2731,7 @@ // Local object references. ArrayUInt8* array = *(ArrayUInt8**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2645,6 +2752,7 @@ // Local object references. ArraySInt8* array = *(ArraySInt8**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2665,6 +2773,7 @@ // Local object references. ArrayUInt16* array = *(ArrayUInt16**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2686,6 +2795,7 @@ // Local object references. ArraySInt16* array = *(ArraySInt16**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2706,6 +2816,7 @@ // Local object references. ArraySInt32* array = *(ArraySInt32**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2726,6 +2837,7 @@ // Local object references. ArrayLong* array = *(ArrayLong**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2747,6 +2859,7 @@ // Local object references. ArrayFloat* array = *(ArrayFloat**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2768,6 +2881,7 @@ // Local object references. ArrayDouble* array = *(ArrayDouble**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -2788,6 +2902,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size; memcpy(array->elements, elems, len); @@ -2803,6 +2918,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size; memcpy(array->elements, elems, len); @@ -2818,6 +2934,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size << 1; memcpy(array->elements, elems, len); @@ -2833,6 +2950,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size << 1; memcpy(array->elements, elems, len); @@ -2848,6 +2966,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size << 2; memcpy(array->elements, elems, len); @@ -2863,6 +2982,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size << 3; memcpy(array->elements, elems, len); @@ -2878,6 +2998,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size << 2; memcpy(array->elements, elems, len); @@ -2893,6 +3014,7 @@ free(elems); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); sint32 len = array->size << 3; memcpy(array->elements, elems, len); @@ -2905,6 +3027,7 @@ void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, jsize len, jboolean *buf) { ArrayUInt8* Array = *(ArrayUInt8**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(uint8)); } @@ -2912,6 +3035,7 @@ void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf) { ArraySInt8* Array = *(ArraySInt8**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(sint8)); } @@ -2919,6 +3043,7 @@ void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf) { ArrayUInt16* Array = *(ArrayUInt16**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(uint16)); } @@ -2926,6 +3051,7 @@ void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf) { ArraySInt16* Array = *(ArraySInt16**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(sint16)); } @@ -2933,6 +3059,7 @@ void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf) { ArraySInt32* Array = *(ArraySInt32**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(sint32)); } @@ -2940,6 +3067,7 @@ void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf) { ArrayLong* Array = *(ArrayLong**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(sint64)); } @@ -2947,6 +3075,7 @@ void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf) { ArrayFloat* Array = *(ArrayFloat**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(float)); } @@ -2954,6 +3083,7 @@ void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf) { ArrayDouble* Array = *(ArrayDouble**)array; + llvm_gcroot(Array, 0); memcpy(buf, &(Array->elements[start]), len * sizeof(double)); } @@ -2961,14 +3091,15 @@ void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, jsize len, const jboolean *buf) { ArrayUInt8* Array = *(ArrayUInt8**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(uint8)); } void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf) { - abort(); ArraySInt8* Array = *(ArraySInt8**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(sint8)); } @@ -2976,6 +3107,7 @@ void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf) { ArrayUInt16* Array = *(ArrayUInt16**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(uint16)); } @@ -2983,6 +3115,7 @@ void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf) { ArraySInt16* Array = *(ArraySInt16**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(sint16)); } @@ -2990,6 +3123,7 @@ void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf) { ArraySInt32* Array = *(ArraySInt32**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(sint32)); } @@ -2997,6 +3131,7 @@ void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, const jlong *buf) { ArrayLong* Array = *(ArrayLong**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(sint64)); } @@ -3004,6 +3139,7 @@ void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf) { ArrayFloat* Array = *(ArrayFloat**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(float)); } @@ -3011,6 +3147,7 @@ void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf) { ArrayDouble* Array = *(ArrayDouble**)array; + llvm_gcroot(Array, 0); memcpy(&(Array->elements[start]), buf, len * sizeof(double)); } @@ -3034,6 +3171,7 @@ BEGIN_JNI_EXCEPTION JavaObject* Obj = *(JavaObject**)_obj; + llvm_gcroot(Obj, 0); if (Obj) { Obj->acquire(); @@ -3053,6 +3191,7 @@ BEGIN_JNI_EXCEPTION JavaObject* Obj = *(JavaObject**)_obj; + llvm_gcroot(Obj, 0); if (Obj) { @@ -3099,6 +3238,7 @@ BEGIN_JNI_EXCEPTION JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); if (isCopy) (*isCopy) = true; @@ -3121,6 +3261,7 @@ free(carray); } else { JavaArray* array = *(JavaArray**)_array; + llvm_gcroot(array, 0); UserClassArray* cl = array->getClass()->asArrayClass(); uint32 logSize = cl->baseClass()->asPrimitiveClass()->logSize; @@ -3163,6 +3304,7 @@ // Local object references. if (obj) { JavaObject* Obj = *(JavaObject**)obj; + llvm_gcroot(Obj, 0); Jnjvm* vm = JavaThread::get()->getJVM(); @@ -3197,19 +3339,24 @@ BEGIN_JNI_EXCEPTION + JavaObject* res = 0; + JavaObject* p = 0; + llvm_gcroot(res, 0); + llvm_gcroot(p, 0); + JavaThread* th = JavaThread::get(); Jnjvm* myvm = th->getJVM(); UserClass* BB = myvm->upcalls->newDirectByteBuffer; - JavaObject* res = BB->doNew(myvm); + res = BB->doNew(myvm); #if (__WORDSIZE == 32) UserClass* PP = myvm->upcalls->newPointer32; - JavaObject* p = PP->doNew(myvm); + p = PP->doNew(myvm); myvm->upcalls->dataPointer32->setInt32Field(p, (uint32)address); #else UserClass* PP = myvm->upcalls->newPointer64; - JavaObject* p = PP->doNew(myvm); + p = PP->doNew(myvm); myvm->upcalls->dataPointer64->setLongField(p, (jlong)address); #endif @@ -3231,9 +3378,12 @@ // Local object references. JavaObject* buf = *(JavaObject**)_buf; + JavaObject* address = 0; + llvm_gcroot(buf, 0); + llvm_gcroot(address, 0); Jnjvm* vm = myVM(env); - JavaObject* address = vm->upcalls->bufferAddress->getObjectField(buf); + address = vm->upcalls->bufferAddress->getObjectField(buf); if (address != 0) { #if (__WORDSIZE == 32) int res = vm->upcalls->dataPointer32->getInt32Field(address); @@ -3291,6 +3441,8 @@ JavaThread* _th = JavaThread::get(); JavaObject* th = _th->currentThread(); + llvm_gcroot(th, 0); + Jnjvm* myvm = _th->getJVM(); if (th != 0) { (*env) = &(myvm->jniEnv); From nicolas.geoffray at lip6.fr Tue Jul 21 03:34:05 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 10:34:05 -0000 Subject: [vmkit-commits] [vmkit] r76561 - in /vmkit/trunk/lib/JnJVM/VMCore: JNIReferences.h JavaObject.h Jnjvm.cpp Message-ID: <200907211034.n6LAYBro021452@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 05:33:22 2009 New Revision: 76561 URL: http://llvm.org/viewvc/llvm-project?rev=76561&view=rev Log: Add more llvm_gcroot's. Modified: vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h?rev=76561&r1=76560&r2=76561&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JNIReferences.h Tue Jul 21 05:33:22 2009 @@ -10,6 +10,8 @@ #ifndef JNI_REFERENCES_H #define JNI_REFERENCES_H +#include "mvm/Allocator.h" + namespace jnjvm { class JavaObject; @@ -58,6 +60,7 @@ } JavaObject** addJNIReference(JavaObject* obj) { + llvm_gcroot(obj, 0); if (length == MAXIMUM_REFERENCES) { if (!next) { next = new JNIGlobalReferences(); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h?rev=76561&r1=76560&r2=76561&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h Tue Jul 21 05:33:22 2009 @@ -49,6 +49,7 @@ /// acquire - Acquires the lock. /// void acquire() { + llvm_gcroot(this, 0); lock.lock(); } @@ -60,6 +61,7 @@ /// acquireAll - Acquires the lock nb times. void acquireAll(uint32 nb) { + llvm_gcroot(this, 0); lock.lockAll(nb); } @@ -299,6 +301,7 @@ /// acquire - Acquire the lock on this object. void acquire() { + llvm_gcroot(this, 0); lock.acquire(); } Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=76561&r1=76560&r2=76561&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Tue Jul 21 05:33:22 2009 @@ -157,8 +157,11 @@ } } -#ifdef SERVICE JavaObject* exc = 0; + JavaObject* obj = 0; + llvm_gcroot(exc, 0); + llvm_gcroot(obj, 0); +#ifdef SERVICE if (classLoader == classLoader->bootstrapLoader || classLoader->getIsolate() == vm) { #endif @@ -188,7 +191,6 @@ vm->bootstrapLoader->clinitType, true, false, 0); - JavaObject* exc = 0; if (meth) { try{ meth->invokeIntStatic(vm, cl); @@ -226,7 +228,7 @@ Classpath* upcalls = classLoader->bootstrapLoader->upcalls; UserClass* clExcp = upcalls->ExceptionInInitializerError; Jnjvm* vm = self->getJVM(); - JavaObject* obj = clExcp->doNew(vm); + obj = clExcp->doNew(vm); if (!obj) { fprintf(stderr, "implement me"); abort(); @@ -251,6 +253,7 @@ void Jnjvm::errorWithExcp(UserClass* cl, JavaMethod* init, const JavaObject* excp) { JavaObject* obj = cl->doNew(this); + llvm_gcroot(obj, 0); init->invokeIntSpecial(this, cl, obj, excp); JavaThread::get()->throwException(obj); } @@ -435,6 +438,7 @@ Jnjvm* vm) { ArrayUInt16* msg = (ArrayUInt16*) vm->upcalls->ArrayOfChar->doNew(19 + cl->name->size + name->size, vm); + uint32 i = 0; @@ -630,6 +634,7 @@ JavaString* Jnjvm::internalUTF8ToStr(const UTF8* utf8) { uint32 size = utf8->size; ArrayUInt16* tmp = (ArrayUInt16*)upcalls->ArrayOfChar->doNew(size, this); + llvm_gcroot(tmp, 0); uint16* buf = tmp->elements; for (uint32 i = 0; i < size; i++) { @@ -657,12 +662,18 @@ // Mimic what's happening in Classpath when creating a java.lang.Class object. JavaObject* UserCommonClass::getClassDelegatee(Jnjvm* vm, JavaObject* pd) { + JavaObjectClass* delegatee = 0; + JavaObjectClass* base = 0; + llvm_gcroot(pd, 0); + llvm_gcroot(delegatee, 0); + llvm_gcroot(base, 0); + if (!getDelegatee()) { UserClass* cl = vm->upcalls->newClass; - JavaObjectClass* delegatee = (JavaObjectClass*)cl->doNew(vm); + delegatee = (JavaObjectClass*)cl->doNew(vm); delegatee->vmdata = this; if (!pd && isArray()) { - JavaObjectClass* base = (JavaObjectClass*) + base = (JavaObjectClass*) asArrayClass()->baseClass()->getClassDelegatee(vm, pd); delegatee->pd = base->pd; } else { @@ -679,6 +690,11 @@ return getDelegateePtr(); } +//===----------------------------------------------------------------------===// +// The command line parsing tool does not manipulate any GC-allocated objects. +// +//===----------------------------------------------------------------------===// + #define PATH_MANIFEST "META-INF/MANIFEST.MF" #define MAIN_CLASS "Main-Class: " #define MAIN_LOWER_CLASS "Main-class: " @@ -942,10 +958,12 @@ JnjvmClassLoader* Jnjvm::loadAppClassLoader() { + JavaObject* loader = 0; + llvm_gcroot(loader, 0); + if (appClassLoader == 0) { UserClass* cl = upcalls->newClassLoader; - JavaObject* loader = - upcalls->getSystemClassLoader->invokeJavaObjectStatic(this, cl); + loader = upcalls->getSystemClassLoader->invokeJavaObjectStatic(this, cl); appClassLoader = JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, this); if (argumentsInfo.jarFile) @@ -1072,6 +1090,15 @@ } void Jnjvm::executeClass(const char* className, ArrayObject* args) { + JavaObject* exc = 0; + JavaObject* obj = 0; + JavaObject* group = 0; + + llvm_gcroot(args, 0); + llvm_gcroot(ex, 0); + llvm_gcroot(obj, 0); + llvm_gcroot(group, 0); + try { // First try to see if we are a self-contained executable. @@ -1094,13 +1121,12 @@ }catch(...) { } - JavaObject* exc = JavaThread::get()->pendingException; + exc = JavaThread::get()->pendingException; if (exc) { JavaThread* th = JavaThread::get(); th->clearException(); - JavaObject* obj = th->currentThread(); - JavaObject* group = - upcalls->group->getObjectField(obj); + obj = th->currentThread(); + group = upcalls->group->getObjectField(obj); try{ upcalls->uncaughtException->invokeIntSpecial(this, upcalls->threadGroup, group, obj, exc); @@ -1113,6 +1139,7 @@ void Jnjvm::executePremain(const char* className, JavaString* args, JavaObject* instrumenter) { + llvm_gcroot(instrumenter, 0); try { const UTF8* name = appClassLoader->asciizConstructUTF8(className); UserClass* cl = (UserClass*)appClassLoader->loadName(name, true, true); @@ -1143,6 +1170,15 @@ } void Jnjvm::mainJavaStart(JavaThread* thread) { + + JavaString* str = 0; + JavaObject* instrumenter = 0; + ArrayObject* args = 0; + + llvm_gcroot(str, 0); + llvm_gcroot(instrumenter, 0); + llvm_gcroot(args, 0); + Jnjvm* vm = thread->getJVM(); vm->mainThread = thread; @@ -1156,17 +1192,17 @@ if (info.agents.size()) { assert(0 && "implement me"); - JavaObject* instrumenter = 0;//createInstrumenter(); + instrumenter = 0;//createInstrumenter(); for (std::vector< std::pair >::iterator i = info.agents.begin(), e = info.agents.end(); i!= e; ++i) { - JavaString* args = vm->asciizToStr(i->second); - vm->executePremain(i->first, args, instrumenter); + str = vm->asciizToStr(i->second); + vm->executePremain(i->first, str, instrumenter); } } UserClassArray* array = vm->bootstrapLoader->upcalls->ArrayOfString; - ArrayObject* args = (ArrayObject*)array->doNew(info.argc - 2, vm); + args = (ArrayObject*)array->doNew(info.argc - 2, vm); for (int i = 2; i < info.argc; ++i) { args->elements[i - 2] = (JavaObject*)vm->asciizToStr(info.argv[i]); } From nicolas.geoffray at lip6.fr Tue Jul 21 03:41:41 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 10:41:41 -0000 Subject: [vmkit-commits] [vmkit] r76563 - in /vmkit/trunk/lib/JnJVM/VMCore: JnjvmClassLoader.cpp LockedMap.h Message-ID: <200907211041.n6LAfknu021694@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 05:41:04 2009 New Revision: 76563 URL: http://llvm.org/viewvc/llvm-project?rev=76563&view=rev Log: Remove useless information in UTF8Map. Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=76563&r1=76562&r2=76563&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Tue Jul 21 05:41:04 2009 @@ -61,7 +61,7 @@ TheCompiler = Comp; - hashUTF8 = new(allocator, "UTF8Map") UTF8Map(allocator, 0); + hashUTF8 = new(allocator, "UTF8Map") UTF8Map(allocator); classes = new(allocator, "ClassMap") ClassMap(); javaTypes = new(allocator, "TypeMap") TypeMap(); javaSignatures = new(allocator, "SignMap") SignMap(); @@ -257,8 +257,7 @@ bootstrapLoader = JCL.bootstrapLoader; TheCompiler = bootstrapLoader->getCompiler()->Create("Applicative loader"); - hashUTF8 = new(allocator, "UTF8Map") - UTF8Map(allocator, bootstrapLoader->upcalls->ArrayOfChar); + hashUTF8 = new(allocator, "UTF8Map") UTF8Map(allocator); classes = new(allocator, "ClassMap") ClassMap(); javaTypes = new(allocator, "TypeMap") TypeMap(); javaSignatures = new(allocator, "SignMap") SignMap(); Modified: vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h?rev=76563&r1=76562&r2=76563&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h Tue Jul 21 05:41:04 2009 @@ -122,16 +122,13 @@ mvm::LockNormal lock; mvm::BumpPtrAllocator& allocator; - UserClassArray* array; std::multimap map; const UTF8* lookupOrCreateAsciiz(const char* asciiz); const UTF8* lookupOrCreateReader(const uint16* buf, uint32 size); const UTF8* lookupAsciiz(const char* asciiz); const UTF8* lookupReader(const uint16* buf, uint32 size); - UTF8Map(mvm::BumpPtrAllocator& A, UserClassArray* cl) : allocator(A) { - array = cl; - } + UTF8Map(mvm::BumpPtrAllocator& A) : allocator(A) {} ~UTF8Map() { for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { From nicolas.geoffray at lip6.fr Tue Jul 21 05:33:03 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 12:33:03 -0000 Subject: [vmkit-commits] [vmkit] r76573 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JavaJIT.cpp lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll lib/JnJVM/LLVMRuntime/runtime-isolate.ll lib/JnJVM/VMCore/JavaRuntimeJIT.cpp lib/JnJVM/VMCore/LinkJavaRuntime.h lib/JnJVM/VMCore/VirtualTables.cpp Message-ID: <200907211233.n6LCX56h025473@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 07:32:49 2009 New Revision: 76573 URL: http://llvm.org/viewvc/llvm-project?rev=76573&view=rev Log: Re-animate jnjvmStringLookup and avoid doing any GC-allocation when compiling. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-isolate.ll vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Tue Jul 21 07:32:49 2009 @@ -258,6 +258,7 @@ llvm::Function* ForceInitialisationCheckFunction; llvm::Function* ForceLoadedCheckFunction; llvm::Function* ClassLookupFunction; + llvm::Function* StringLookupFunction; #ifndef WITHOUT_VTABLE llvm::Function* VirtualLookupFunction; #endif @@ -273,8 +274,6 @@ llvm::Function* MultiCallNewFunction; llvm::Function* GetArrayClassFunction; -#ifdef ISOLATE - llvm::Function* StringLookupFunction; #ifdef ISOLATE_SHARING llvm::Function* GetCtpCacheNodeFunction; llvm::Function* GetCtpClassFunction; @@ -284,7 +283,6 @@ llvm::Function* StaticCtpLookupFunction; llvm::Function* SpecialCtpLookupFunction; #endif -#endif #ifdef SERVICE llvm::Function* ServiceCallStartFunction; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 21 07:32:49 2009 @@ -1097,34 +1097,27 @@ uint8 type = ctpInfo->typeAt(index); if (type == JavaConstantPool::ConstantString) { -#if defined(ISOLATE) - if (compilingClass->classLoader != - compilingClass->classLoader->bootstrapLoader) { - const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]); - JavaString* str = compilingClass->classLoader->UTF8ToStr(utf8); - - Value* val = module->getString(str, currentBlock); +#if defined(ISOLATE) + abort(); +#else + + JavaString* str = (JavaString*)ctpInfo->ctpRes[index]; + if (str) { + Value* val = TheCompiler->getString(str); push(val, false); } else { - + if (TheCompiler->isStaticCompiling()) { + const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]); + JavaString* str = compilingClass->classLoader->UTF8ToStr(utf8); + Value* val = TheCompiler->getString(str); + push(val, false); + } // Lookup the constant pool cache Value* val = getConstantPoolAt(index, module->StringLookupFunction, module->JavaObjectType, 0, false); push(val, false); } -#elif defined(ISOLATE_SHARING) - // Lookup the constant pool cache - Value* val = getConstantPoolAt(index, module->StringLookupFunction, - module->JavaObjectType, 0, false); - push(val, false); -#else - const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]); - JavaString* str = compilingClass->classLoader->UTF8ToStr(utf8); - - Value* val = TheCompiler->getString(str); - push(val, false); -#endif - +#endif } else if (type == JavaConstantPool::ConstantLong) { push(llvmContext->getConstantInt(Type::Int64Ty, ctpInfo->LongAt(index)), false); @@ -1141,11 +1134,6 @@ UserCommonClass* cl = 0; Value* res = getResolvedCommonClass(index, false, &cl); -#ifndef ISOLATE - if (cl) res = TheCompiler->getJavaClass(cl); - else -#endif - res = CallInst::Create(module->GetClassDelegateeFunction, res, "", currentBlock); push(res, false); Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Tue Jul 21 07:32:49 2009 @@ -256,7 +256,7 @@ VirtualFieldLookupFunction = module->getFunction("jnjvmVirtualFieldLookup"); StaticFieldLookupFunction = module->getFunction("jnjvmStaticFieldLookup"); - + StringLookupFunction = module->getFunction("jnjvmStringLookup"); JniProceedPendingExceptionFunction = module->getFunction("jnjvmJNIProceedPendingException"); GetSJLJBufferFunction = module->getFunction("jnjvmGetSJLJBuffer"); @@ -291,8 +291,6 @@ GetFinalDoubleFieldFunction = module->getFunction("getFinalDoubleField"); GetFinalObjectFieldFunction = module->getFunction("getFinalObjectField"); -#ifdef ISOLATE - StringLookupFunction = module->getFunction("jnjvmStringLookup"); #ifdef ISOLATE_SHARING EnveloppeLookupFunction = module->getFunction("jnjvmEnveloppeLookup"); GetCtpCacheNodeFunction = module->getFunction("getCtpCacheNode"); @@ -303,7 +301,6 @@ StaticCtpLookupFunction = module->getFunction("jnjvmStaticCtpLookup"); SpecialCtpLookupFunction = module->getFunction("jnjvmSpecialCtpLookup"); #endif -#endif #ifdef SERVICE ServiceCallStartFunction = module->getFunction("jnjvmServiceCallStart"); Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Tue Jul 21 07:32:49 2009 @@ -165,6 +165,10 @@ ;;; jnjvmStaticFieldLookup - Look up a specific static field. declare i8* @jnjvmStaticFieldLookup(%JavaClass*, i32, ...) +;;; jnjvmStringLookup - Find the isolate-specific string at the given offset in +;;; the constant pool. +declare i8* @jnjvmStringLookup(%JavaClass*, i32, ...) readnone + ;;; jnjvmJavaObjectAquire - This function is called when starting a synchronized ;;; block or method. declare void @jnjvmJavaObjectAquire(%JavaObject*) Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-isolate.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-isolate.ll?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-isolate.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-isolate.ll Tue Jul 21 07:32:49 2009 @@ -22,10 +22,6 @@ ;;; jnjvmEnveloppeLookup - Find the enveloppe for the current user class. declare i8* @jnjvmEnveloppeLookup(%JavaClass*, i32, ...) readnone -;;; jnjvmStringLookup - Find the isolate-specific string at the given offset in -;;; the constant pool. -declare i8* @jnjvmStringLookup(%JavaClass*, i32, ...) readnone - ;;; jnjvmStaticCtpLookup - Find the user constant pool at the given offset in ;;; the constant pool. declare i8* @jnjvmStaticCtpLookup(%JavaClass*, i32, ...) readnone Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Tue Jul 21 07:32:49 2009 @@ -632,6 +632,16 @@ } +extern "C" void* jnjvmStringLookup(UserClass* cl, uint32 index) { + UserConstantPool* ctpInfo = cl->getConstantPool(); + const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]); + JavaString* str = cl->classLoader->UTF8ToStr(utf8); +#if defined(ISOLATE_SHARING) || !defined(ISOLATE) + ctpInfo->ctpRes[index] = str; +#endif + return (void*)str; +} + extern "C" void jnjvmPrintMethodStart(JavaMethod* meth) { fprintf(stderr, "[%p] executing %s.%s\n", (void*)mvm::Thread::get(), UTF8Buffer(meth->classDef->name).cString(), @@ -669,16 +679,6 @@ #endif -#ifdef ISOLATE -extern "C" void* jnjvmStringLookup(UserClass* cl, uint32 index) { - UserConstantPool* ctpInfo = cl->getConstantPool(); - const UTF8* utf8 = ctpInfo->UTF8AtForString(index); - JavaString* str = JavaThread::get()->getJVM()->internalUTF8ToStr(utf8); -#ifdef ISOLATE_SHARING - ctpInfo->ctpRes[index] = str; -#endif - return (void*)str; -} #ifdef ISOLATE_SHARING extern "C" void* jnjvmEnveloppeLookup(UserClass* cl, uint32 index) { @@ -728,5 +728,3 @@ } #endif - -#endif Modified: vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h Tue Jul 21 07:32:49 2009 @@ -30,6 +30,7 @@ extern "C" void* jnjvmVirtualFieldLookup(UserClass* caller, uint32 index); extern "C" void* jnjvmStaticFieldLookup(UserClass* caller, uint32 index); extern "C" void* jnjvmVirtualTableLookup(UserClass* caller, uint32 index, ...); +extern "C" void* jnjvmStringLookup(UserClass* cl, uint32 index); extern "C" void* jnjvmClassLookup(UserClass* caller, uint32 index); extern "C" UserCommonClass* jnjvmRuntimeInitialiseClass(UserClass* cl); extern "C" JavaObject* jnjvmRuntimeDelegatee(UserCommonClass* cl); @@ -68,8 +69,6 @@ -#ifdef ISOLATE -extern "C" void* jnjvmStringLookup(UserClass* cl, uint32 index); #ifdef ISOLATE_SHARING extern "C" void* jnjvmEnveloppeLookup(UserClass* cl, uint32 index); @@ -79,8 +78,6 @@ UserConstantPool** res); #endif -#endif - namespace { struct ForceRuntimeLinking { @@ -119,21 +116,18 @@ (void) jnjvmPrintMethodStart(0); (void) jnjvmPrintMethodEnd(0); (void) jnjvmPrintExecution(0, 0, 0); + (void) jnjvmStringLookup(0, 0); #ifdef SERVICE (void) jnjvmServiceCallStart(0, 0); (void) jnjvmServiceCallStop(0, 0); #endif -#ifdef ISOLATE - (void) jnjvmStringLookup(0, 0); - #ifdef ISOLATE_SHARING (void) jnjvmEnveloppeLookup(0, 0); (void) jnjvmStaticCtpLookup(0, 0); (void) jnjvmSpecialCtpLookup(0, 0, 0); #endif -#endif } } ForcePassLinking; // Force link by creating a global definition. } Modified: vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp?rev=76573&r1=76572&r2=76573&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Tue Jul 21 07:32:49 2009 @@ -174,7 +174,8 @@ void Class::tracer() { CommonClass::tracer(); - bytes->markAndTrace(); + if (classLoader != classLoader->bootstrapLoader) + bytes->markAndTrace(); for (uint32 i =0; i < NR_ISOLATES; ++i) { TaskClassMirror &M = IsolateInfo[i]; From nicolas.geoffray at lip6.fr Tue Jul 21 06:48:11 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 13:48:11 -0000 Subject: [vmkit-commits] [vmkit] r76574 - /vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Message-ID: <200907211348.n6LDmGsS027943@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 08:47:44 2009 New Revision: 76574 URL: http://llvm.org/viewvc/llvm-project?rev=76574&view=rev Log: Fix mindo. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76574&r1=76573&r2=76574&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 21 08:47:44 2009 @@ -1111,11 +1111,12 @@ JavaString* str = compilingClass->classLoader->UTF8ToStr(utf8); Value* val = TheCompiler->getString(str); push(val, false); + } else { + // Lookup the constant pool cache + Value* val = getConstantPoolAt(index, module->StringLookupFunction, + module->JavaObjectType, 0, false); + push(val, false); } - // Lookup the constant pool cache - Value* val = getConstantPoolAt(index, module->StringLookupFunction, - module->JavaObjectType, 0, false); - push(val, false); } #endif } else if (type == JavaConstantPool::ConstantLong) { From nicolas.geoffray at lip6.fr Tue Jul 21 06:51:07 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 13:51:07 -0000 Subject: [vmkit-commits] [vmkit] r76575 - /vmkit/trunk/tools/vmjc/vmjc.cpp Message-ID: <200907211351.n6LDp7JH028079@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 08:50:57 2009 New Revision: 76575 URL: http://llvm.org/viewvc/llvm-project?rev=76575&view=rev Log: Disable cross-compiling until I figure out how to use this TargetSelect thing. Modified: vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=76575&r1=76574&r2=76575&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Tue Jul 21 08:50:57 2009 @@ -97,9 +97,6 @@ static cl::opt TargetTriple("mtriple", cl::desc("Override target triple for module")); -static cl::opt -MArch("march", cl::desc("Architecture to generate code for (see --version)")); - static cl::opt DisableExceptions("disable-exceptions", cl::desc("Disable Java exceptions")); @@ -185,14 +182,16 @@ return 0; } - if (WithClinit.empty()) { + // Disable cross-compiling for now. + if (false) { Module* TheModule = new Module("bootstrap module", *(new llvm::LLVMContext())); if (!TargetTriple.empty()) TheModule->setTargetTriple(TargetTriple); else TheModule->setTargetTriple(mvm::MvmModule::getHostTriple()); - + +#if 0 // explicitly specified an architecture to compile for. const Target *TheTarget = 0; if (!MArch.empty()) { @@ -233,6 +232,7 @@ mvm::MvmModule::initialise(CodeGenOpt::Default, TheModule, &Target); +#endif } else { mvm::MvmModule::initialise(); } From nicolas.geoffray at lip6.fr Tue Jul 21 09:50:06 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 16:50:06 -0000 Subject: [vmkit-commits] [vmkit] r76580 - in /vmkit/trunk/lib/JnJVM/VMCore: Jnjvm.cpp JnjvmClassLoader.cpp JnjvmClassLoader.h VirtualTables.cpp Message-ID: <200907211650.n6LGo7MB001290@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 11:50:05 2009 New Revision: 76580 URL: http://llvm.org/viewvc/llvm-project?rev=76580&view=rev Log: Don't use vectors to sore strings located in class files. Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=76580&r1=76579&r2=76580&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Tue Jul 21 11:50:05 2009 @@ -1283,10 +1283,14 @@ upcalls = bootstrapLoader->upcalls; throwable = upcalls->newThrowable; - - for (std::vector >::iterator i = - loader->strings.begin(), e = loader->strings.end(); i != e; ++i) { - hashStr.insert(*i); + + StringList* end = loader->strings; + while (end) { + for (uint32 i = 0; i < end->length; ++i) { + JavaString* obj = end->strings[i]; + hashStr.insert(obj); + } + end = end->prev; } bootstrapLoader->insertAllMethodsInVM(this); Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=76580&r1=76579&r2=76580&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Tue Jul 21 11:50:05 2009 @@ -50,6 +50,11 @@ #include "Reader.h" #include "Zip.h" + +namespace jnjvm { + +} + using namespace jnjvm; typedef void (*static_init_t)(JnjvmClassLoader*); @@ -64,7 +69,8 @@ hashUTF8 = new(allocator, "UTF8Map") UTF8Map(allocator); classes = new(allocator, "ClassMap") ClassMap(); javaTypes = new(allocator, "TypeMap") TypeMap(); - javaSignatures = new(allocator, "SignMap") SignMap(); + javaSignatures = new(allocator, "SignMap") SignMap(); + strings = new(allocator, "StringList") StringList(); bootClasspathEnv = getenv("JNJVM_BOOTCLASSPATH"); if (!bootClasspathEnv) { @@ -261,6 +267,7 @@ classes = new(allocator, "ClassMap") ClassMap(); javaTypes = new(allocator, "TypeMap") TypeMap(); javaSignatures = new(allocator, "SignMap") SignMap(); + strings = new(allocator, "StringList") StringList(); javaLoader = loader; isolate = I; @@ -928,14 +935,14 @@ JavaString* JnjvmClassLoader::UTF8ToStr(const UTF8* val) { JavaString* res = isolate->internalUTF8ToStr(val); - strings.push_back(res); + strings->addString(this, res); return res; } JavaString* JnjvmBootstrapLoader::UTF8ToStr(const UTF8* val) { Jnjvm* vm = JavaThread::get()->getJVM(); JavaString* res = vm->internalUTF8ToStr(val); - strings.push_back(res); + strings->addString(this, res); return res; } @@ -1185,7 +1192,7 @@ } extern "C" void vmjcAddString(JnjvmClassLoader* JCL, JavaString* val) { - JCL->strings.push_back(val); + JCL->strings->addString(JCL, val); } extern "C" intptr_t vmjcNativeLoader(JavaMethod* meth) { Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h?rev=76580&r1=76579&r2=76580&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h Tue Jul 21 11:50:05 2009 @@ -35,8 +35,10 @@ class JavaString; class Jnjvm; class JnjvmBootstrapLoader; +class JnjvmClassLoader; class Signdef; class SignMap; +class StringList; class Typedef; class TypeMap; class UTF8; @@ -239,7 +241,7 @@ /// Strings hashed by this classloader. /// - std::vector > strings; + StringList* strings; /// nativeLibs - Native libraries (e.g. '.so') loaded by this class loader. /// @@ -455,6 +457,37 @@ }; +#define MAXIMUM_STRINGS 100 + +class StringList : public mvm::PermanentObject { + friend class JnjvmClassLoader; + friend class Jnjvm; + +private: + StringList* prev; + uint32_t length; + JavaString* strings[MAXIMUM_STRINGS]; + +public: + StringList() { + prev = 0; + length = 0; + } + + JavaString** addString(JnjvmClassLoader* JCL, JavaString* obj) { + llvm_gcroot(obj, 0); + if (length == MAXIMUM_STRINGS) { + StringList* next = new(JCL->allocator, "StringList") StringList(); + next->prev = this; + JCL->strings = next; + return next->addString(JCL, obj); + } else { + strings[length] = obj; + return &strings[length++]; + } + } +}; + } // end namespace jnjvm #endif // JNJVM_CLASSLOADER_H Modified: vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp?rev=76580&r1=76579&r2=76580&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Tue Jul 21 11:50:05 2009 @@ -217,15 +217,17 @@ else cl->tracer(); } - for (std::vector >::iterator i = strings.begin(), - e = strings.end(); i!= e; ++i) { - (*i)->markAndTrace(); - // If the string was static allocated, we want to trace its lock. - LockObj* l = (*i)->lockObj(); - if (l) l->markAndTrace(); + StringList* end = strings; + while (end) { + for (uint32 i = 0; i < end->length; ++i) { + JavaObject* obj = end->strings[i]; + obj->markAndTrace(); + // If the string was static allocated, we want to trace its lock. + LockObj* l = obj->lockObj(); + if (l) l->markAndTrace(); + } + end = end->prev; } - } void JnjvmBootstrapLoader::tracer() { From nicolas.geoffray at lip6.fr Tue Jul 21 09:51:30 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 16:51:30 -0000 Subject: [vmkit-commits] [vmkit] r76581 - /vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Message-ID: <200907211651.n6LGpUAo001344@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 11:51:28 2009 New Revision: 76581 URL: http://llvm.org/viewvc/llvm-project?rev=76581&view=rev Log: Don't output an object direclty in the native code. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76581&r1=76580&r2=76581&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 21 11:51:28 2009 @@ -1850,9 +1850,16 @@ abort(); } } else { - JavaObject* val = field->getObjectField(Obj); - Value* V = TheCompiler->getFinalObject(val); - push(V, false); + if (TheCompiler->isStaticCompiling()) { + JavaObject* val = field->getObjectField(Obj); + Value* V = TheCompiler->getFinalObject(val); + push(V, false); + } else { + Value* V = CallInst::Create(module->GetFinalObjectFieldFunction, ptr, + "", currentBlock); + + push(V, false); + } } } } From nicolas.geoffray at lip6.fr Tue Jul 21 09:57:31 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 16:57:31 -0000 Subject: [vmkit-commits] [vmkit] r76582 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907211657.n6LGvb2l001548@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 11:57:00 2009 New Revision: 76582 URL: http://llvm.org/viewvc/llvm-project?rev=76582&view=rev Log: Bugfix when AOT compiling. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=76582&r1=76581&r2=76582&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Tue Jul 21 11:57:00 2009 @@ -218,6 +218,7 @@ getJavaClass(cl); Constant* Cl = getNativeClass(cl); + Cl = ConstantExpr::getBitCast(Cl, JnjvmModule::JavaCommonClassType); Constant* GEP[2] = { getIntrinsics()->constantZero, getIntrinsics()->constantZero }; @@ -721,7 +722,7 @@ Elmts.push_back(getUTF8(val->methodName)); Elmts.push_back(getUTF8(val->methodSign)); - Elmts.push_back(Mod.getContext().getNullValue(Type::Int8Ty)); + Elmts.push_back(Mod.getContext().getNullValue(Type::Int32Ty)); Elmts.push_back(getNativeClass(val->classDef)); Elmts.push_back(firstCache); From nicolas.geoffray at lip6.fr Tue Jul 21 10:16:14 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 17:16:14 -0000 Subject: [vmkit-commits] [vmkit] r76584 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h lib/JnJVM/Compiler/JavaAOTCompiler.cpp lib/JnJVM/Compiler/JavaJIT.cpp lib/JnJVM/Compiler/JavaJITCompiler.cpp lib/JnJVM/VMCore/JavaRuntimeJIT.cpp lib/JnJVM/VMCore/JnjvmClassLoader.cpp lib/JnJVM/VMCore/JnjvmClassLoader.h Message-ID: <200907211716.n6LHGMwV002315@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 12:15:51 2009 New Revision: 76584 URL: http://llvm.org/viewvc/llvm-project?rev=76584&view=rev Log: Don't output strings directly in the native code, but use an indirection. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=76584&r1=76583&r2=76584&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Tue Jul 21 12:15:51 2009 @@ -426,6 +426,7 @@ virtual llvm::Constant* getEnveloppe(Enveloppe* enveloppe) = 0; virtual llvm::Constant* getString(JavaString* str) = 0; + virtual llvm::Constant* getStringPtr(JavaString** str) = 0; virtual llvm::Constant* getConstantPool(JavaConstantPool* ctp) = 0; virtual llvm::Constant* getNativeFunction(JavaMethod* meth, void* natPtr) = 0; @@ -498,6 +499,7 @@ virtual llvm::Constant* getEnveloppe(Enveloppe* enveloppe); virtual llvm::Constant* getString(JavaString* str); + virtual llvm::Constant* getStringPtr(JavaString** str); virtual llvm::Constant* getConstantPool(JavaConstantPool* ctp); virtual llvm::Constant* getNativeFunction(JavaMethod* meth, void* natPtr); @@ -553,6 +555,7 @@ virtual llvm::Constant* getEnveloppe(Enveloppe* enveloppe); virtual llvm::Constant* getString(JavaString* str); + virtual llvm::Constant* getStringPtr(JavaString** str); virtual llvm::Constant* getConstantPool(JavaConstantPool* ctp); virtual llvm::Constant* getNativeFunction(JavaMethod* meth, void* natPtr); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=76584&r1=76583&r2=76584&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Tue Jul 21 12:15:51 2009 @@ -168,6 +168,11 @@ } } +Constant* JavaAOTCompiler::getStringPtr(JavaString** str) { + fprintf(stderr, "Implement me"); + abort(); +} + Constant* JavaAOTCompiler::getEnveloppe(Enveloppe* enveloppe) { enveloppe_iterator SI = enveloppes.find(enveloppe); if (SI != enveloppes.end()) { Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76584&r1=76583&r2=76584&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 21 12:15:51 2009 @@ -1101,20 +1101,23 @@ abort(); #else - JavaString* str = (JavaString*)ctpInfo->ctpRes[index]; - if (str) { + if (TheCompiler->isStaticCompiling()) { + const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]); + JavaString* str = *(compilingClass->classLoader->UTF8ToStr(utf8)); Value* val = TheCompiler->getString(str); push(val, false); } else { - if (TheCompiler->isStaticCompiling()) { - const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]); - JavaString* str = compilingClass->classLoader->UTF8ToStr(utf8); - Value* val = TheCompiler->getString(str); + JavaString** str = (JavaString**)ctpInfo->ctpRes[index]; + if (str) { + Value* val = TheCompiler->getStringPtr(str); + val = new LoadInst(val, "", currentBlock); push(val, false); } else { // Lookup the constant pool cache + const llvm::Type* Ty = PointerType::getUnqual(module->JavaObjectType); Value* val = getConstantPoolAt(index, module->StringLookupFunction, - module->JavaObjectType, 0, false); + Ty, 0, false); + val = new LoadInst(val, "", currentBlock); push(val, false); } } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=76584&r1=76583&r2=76584&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Tue Jul 21 12:15:51 2009 @@ -58,6 +58,14 @@ return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } +Constant* JavaJITCompiler::getStringPtr(JavaString** str) { + assert(str && "No string given"); + LLVMContext& Context = getLLVMModule()->getContext(); + const llvm::Type* Ty = PointerType::getUnqual(JnjvmModule::JavaObjectType); + ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64(str)); + return ConstantExpr::getIntToPtr(CI, Ty); +} + Constant* JavaJITCompiler::getEnveloppe(Enveloppe* enveloppe) { assert(enveloppe && "No enveloppe given"); LLVMContext& Context = getLLVMModule()->getContext(); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=76584&r1=76583&r2=76584&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Tue Jul 21 12:15:51 2009 @@ -635,7 +635,7 @@ extern "C" void* jnjvmStringLookup(UserClass* cl, uint32 index) { UserConstantPool* ctpInfo = cl->getConstantPool(); const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]); - JavaString* str = cl->classLoader->UTF8ToStr(utf8); + JavaString** str = cl->classLoader->UTF8ToStr(utf8); #if defined(ISOLATE_SHARING) || !defined(ISOLATE) ctpInfo->ctpRes[index] = str; #endif Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=76584&r1=76583&r2=76584&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Tue Jul 21 12:15:51 2009 @@ -933,17 +933,15 @@ JnjvmBootstrapLoader::~JnjvmBootstrapLoader() { } -JavaString* JnjvmClassLoader::UTF8ToStr(const UTF8* val) { +JavaString** JnjvmClassLoader::UTF8ToStr(const UTF8* val) { JavaString* res = isolate->internalUTF8ToStr(val); - strings->addString(this, res); - return res; + return strings->addString(this, res); } -JavaString* JnjvmBootstrapLoader::UTF8ToStr(const UTF8* val) { +JavaString** JnjvmBootstrapLoader::UTF8ToStr(const UTF8* val) { Jnjvm* vm = JavaThread::get()->getJVM(); JavaString* res = vm->internalUTF8ToStr(val); - strings->addString(this, res); - return res; + return strings->addString(this, res); } void JnjvmBootstrapLoader::analyseClasspathEnv(const char* str) { Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h?rev=76584&r1=76583&r2=76584&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.h Tue Jul 21 12:15:51 2009 @@ -237,7 +237,7 @@ /// UTF8ToStr - Constructs a Java string out of the UTF8. /// - virtual JavaString* UTF8ToStr(const UTF8* utf8); + virtual JavaString** UTF8ToStr(const UTF8* utf8); /// Strings hashed by this classloader. /// @@ -337,7 +337,7 @@ JnjvmBootstrapLoader(mvm::BumpPtrAllocator& Alloc, JavaCompiler* Comp, bool dlLoad = true); - virtual JavaString* UTF8ToStr(const UTF8* utf8); + virtual JavaString** UTF8ToStr(const UTF8* utf8); /// nativeHandle - Non-null handle if boot classes were static compiled in /// a dynamic library From nicolas.geoffray at lip6.fr Tue Jul 21 10:26:42 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 21 Jul 2009 17:26:42 -0000 Subject: [vmkit-commits] [vmkit] r76589 - /vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Message-ID: <200907211726.n6LHQgHW002742@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 21 12:26:41 2009 New Revision: 76589 URL: http://llvm.org/viewvc/llvm-project?rev=76589&view=rev Log: Set the target triple of the module. Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=76589&r1=76588&r2=76589&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Tue Jul 21 12:26:41 2009 @@ -67,6 +67,7 @@ std::string str = executionEngine->getTargetData()->getStringRepresentation(); globalModule->setDataLayout(str); + globalModule->setTargetTriple(getHostTriple()); TheTargetData = executionEngine->getTargetData(); } else { From nicolas.geoffray at lip6.fr Wed Jul 22 02:14:18 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 22 Jul 2009 09:14:18 -0000 Subject: [vmkit-commits] [vmkit] r76731 - in /vmkit/trunk: include/mvm/JIT.h lib/JnJVM/Compiler/JavaJIT.cpp lib/JnJVM/Compiler/JavaJIT.h lib/Mvm/Compiler/JIT.cpp lib/Mvm/Compiler/LLVMRuntime.ll Message-ID: <200907220914.n6M9ELKx015407@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 22 04:14:00 2009 New Revision: 76731 URL: http://llvm.org/viewvc/llvm-project?rev=76731&view=rev Log: Add llvm_gcroot's in Java code. Modified: vmkit/trunk/include/mvm/JIT.h vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h vmkit/trunk/lib/Mvm/Compiler/JIT.cpp vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll Modified: vmkit/trunk/include/mvm/JIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=76731&r1=76730&r2=76731&view=diff ============================================================================== --- vmkit/trunk/include/mvm/JIT.h (original) +++ vmkit/trunk/include/mvm/JIT.h Wed Jul 22 04:14:00 2009 @@ -113,6 +113,7 @@ llvm::Function* llvm_atomic_lcs_i32; llvm::Function* llvm_atomic_lcs_i64; llvm::Function* llvm_atomic_lcs_ptr; + llvm::Function* llvm_gc_gcroot; llvm::Constant* constantInt8Zero; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76731&r1=76730&r2=76731&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Wed Jul 22 04:14:00 2009 @@ -364,6 +364,12 @@ Value* temp = new AllocaInst(module->JavaObjectType, "", currentBlock); + Value* GCArgs[2] = { + new BitCastInst(temp, module->ptrPtrType, "", currentBlock), + module->constantPtrNull + }; + CallInst::Create(module->llvm_gc_gcroot, GCArgs, GCArgs + 2, "", + currentBlock); new StoreInst(i, temp, false, currentBlock); node->addIncoming(temp, currentBlock); BranchInst::Create(BB, currentBlock); @@ -651,6 +657,16 @@ } +static void removeUnusedLocals(std::vector& locals) { + for (std::vector::iterator i = locals.begin(), + e = locals.end(); i != e; ++i) { + AllocaInst* temp = *i; + if (!temp->getNumUses()) { + temp->eraseFromParent(); + } + } +} + Instruction* JavaJIT::inlineCompile(BasicBlock*& curBB, BasicBlock* endExBlock, std::vector& args) { @@ -706,6 +722,7 @@ objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", firstInstruction)); } + } else { for (int i = 0; i < maxLocals; i++) { intLocals.push_back(new AllocaInst(Type::Int32Ty, "", firstBB)); @@ -716,6 +733,7 @@ firstBB)); } } + uint32 index = 0; uint32 count = 0; @@ -780,6 +798,28 @@ UTF8Buffer(compilingMethod->name).cString()); curBB = endBlock; + + + for (std::vector::iterator i = objectLocals.begin(), + e = objectLocals.end(); i != e; ++i) { + AllocaInst* temp = *i; + if (temp->getNumUses()) { + Instruction* I = new BitCastInst(temp, module->ptrPtrType, ""); + I->insertAfter(temp); + Value* GCArgs[2] = { I, module->constantPtrNull }; + Instruction* C = CallInst::Create(module->llvm_gc_gcroot, GCArgs, + GCArgs + 2, ""); + C->insertAfter(I); + } else { + temp->eraseFromParent(); + } + } + removeUnusedLocals(intLocals); + removeUnusedLocals(doubleLocals); + removeUnusedLocals(floatLocals); + removeUnusedLocals(longLocals); + + return endNode; } @@ -843,7 +883,6 @@ objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", currentBlock)); } - uint32 index = 0; uint32 count = 0; @@ -1062,6 +1101,26 @@ finishExceptions(); + for (std::vector::iterator i = objectLocals.begin(), + e = objectLocals.end(); i != e; ++i) { + AllocaInst* temp = *i; + if (temp->getNumUses()) { + Instruction* I = new BitCastInst(temp, module->ptrPtrType, ""); + I->insertAfter(temp); + Value* GCArgs[2] = { I, module->constantPtrNull }; + Instruction* C = CallInst::Create(module->llvm_gc_gcroot, GCArgs, + GCArgs + 2, ""); + C->insertAfter(I); + } else { + temp->eraseFromParent(); + } + } + + removeUnusedLocals(intLocals); + removeUnusedLocals(doubleLocals); + removeUnusedLocals(floatLocals); + removeUnusedLocals(longLocals); + func->setLinkage(GlobalValue::ExternalLinkage); PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "--> end compiling %s.%s\n", Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h?rev=76731&r1=76730&r2=76731&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Wed Jul 22 04:14:00 2009 @@ -97,11 +97,11 @@ JavaLLVMCompiler* TheCompiler; /// locals - The locals of the method. - std::vector intLocals; - std::vector longLocals; - std::vector floatLocals; - std::vector doubleLocals; - std::vector objectLocals; + std::vector intLocals; + std::vector longLocals; + std::vector floatLocals; + std::vector doubleLocals; + std::vector objectLocals; /// endBlock - The block that returns. llvm::BasicBlock* endBlock; Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=76731&r1=76730&r2=76731&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Wed Jul 22 04:14:00 2009 @@ -202,6 +202,7 @@ llvm_memcpy_i32 = module->getFunction("llvm.memcpy.i32"); llvm_memset_i32 = module->getFunction("llvm.memset.i32"); llvm_frameaddress = module->getFunction("llvm.frameaddress"); + llvm_gc_gcroot = module->getFunction("llvm.gcroot"); llvm_atomic_lcs_i8 = module->getFunction("llvm.atomic.cmp.swap.i8.p0i8"); llvm_atomic_lcs_i16 = module->getFunction("llvm.atomic.cmp.swap.i16.p0i16"); Modified: vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll?rev=76731&r1=76730&r2=76731&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll (original) +++ vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll Wed Jul 22 04:14:00 2009 @@ -73,3 +73,9 @@ declare i16 @llvm.atomic.cmp.swap.i16.p0i16(i16*, i16, i16) nounwind declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64*, i64, i64) nounwind + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +declare void @llvm.gcroot(i8**, i8*) From nicolas.geoffray at lip6.fr Wed Jul 22 02:35:34 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 22 Jul 2009 09:35:34 -0000 Subject: [vmkit-commits] [vmkit] r76732 - in /vmkit/trunk/lib: JnJVM/Compiler/JavaAOTCompiler.cpp JnJVM/Compiler/JavaJIT.h JnJVM/Compiler/JavaJITOpcodes.cpp JnJVM/Compiler/LowerConstantCalls.cpp N3/VMCore/CLIJit.cpp N3/VMCore/LowerArrayLength.cpp N3/VMCore/Opcodes.cpp N3/VMCore/VMCache.cpp Message-ID: <200907220935.n6M9ZbVA016155@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 22 04:35:27 2009 New Revision: 76732 URL: http://llvm.org/viewvc/llvm-project?rev=76732&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp vmkit/trunk/lib/N3/VMCore/CLIJit.cpp vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp vmkit/trunk/lib/N3/VMCore/Opcodes.cpp vmkit/trunk/lib/N3/VMCore/VMCache.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Wed Jul 22 04:35:27 2009 @@ -783,7 +783,7 @@ } ATy = ArrayType::get(JnjvmModule::JavaClassType, cl->nbInterfaces); - Constant* interfaces = ConstantArray::get(ATy, TempElmts); + Constant* interfaces = Context.getConstantArray(ATy, TempElmts); interfaces = new GlobalVariable(Mod, ATy, true, GlobalValue::InternalLinkage, interfaces, ""); @@ -855,7 +855,7 @@ TempElts.push_back(CreateConstantFromAttribut(field.attributs[i])); } - Constant* attributs = ConstantArray::get(ATy, TempElts); + Constant* attributs = Context.getConstantArray(ATy, TempElts); TempElts.clear(); attributs = new GlobalVariable(*getLLVMModule(), ATy, true, GlobalValue::InternalLinkage, @@ -909,7 +909,7 @@ TempElts.push_back(CreateConstantFromAttribut(method.attributs[i])); } - Constant* attributs = ConstantArray::get(ATy, TempElts); + Constant* attributs = Context.getConstantArray(ATy, TempElts); TempElts.clear(); attributs = new GlobalVariable(Mod, ATy, true, GlobalValue::InternalLinkage, @@ -1061,7 +1061,7 @@ Constant* fields = 0; if (cl->nbStaticFields + cl->nbVirtualFields) { - fields = ConstantArray::get(ATy, TempElts); + fields = Context.getConstantArray(ATy, TempElts); TempElts.clear(); fields = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, @@ -1108,7 +1108,7 @@ Constant* methods = 0; if (cl->nbVirtualMethods + cl->nbStaticMethods) { - methods = ConstantArray::get(ATy, TempElts); + methods = Context.getConstantArray(ATy, TempElts); TempElts.clear(); GlobalVariable* GV = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, @@ -1153,7 +1153,7 @@ TempElts.push_back(CreateConstantFromAttribut(cl->attributs[i])); } - Constant* attributs = ConstantArray::get(ATy, TempElts); + Constant* attributs = Context.getConstantArray(ATy, TempElts); TempElts.clear(); attributs = new GlobalVariable(*getLLVMModule(), ATy, true, GlobalValue::InternalLinkage, @@ -1176,7 +1176,7 @@ const llvm::Type* TempTy = JnjvmModule::JavaClassType; ATy = ArrayType::get(TempTy, cl->nbInnerClasses); - Constant* innerClasses = ConstantArray::get(ATy, TempElts); + Constant* innerClasses = Context.getConstantArray(ATy, TempElts); innerClasses = new GlobalVariable(*getLLVMModule(), ATy, true, GlobalValue::InternalLinkage, innerClasses, ""); @@ -1253,7 +1253,7 @@ } } - Cts.push_back(ConstantArray::get(ATy, Vals)); + Cts.push_back(Context.getConstantArray(ATy, Vals)); return ConstantStruct::get(STy, Cts); } @@ -1277,7 +1277,7 @@ Vals.push_back(Context.getConstantInt(Type::Int16Ty, val->elements[i])); } - Cts.push_back(ConstantArray::get(ATy, Vals)); + Cts.push_back(Context.getConstantArray(ATy, Vals)); return ConstantStruct::get(STy, Cts); @@ -1389,7 +1389,7 @@ Constant* Cl = getVirtualTable(VT->secondaryTypes[i]); TempElmts.push_back(Cl); } - Constant* display = ConstantArray::get(DTy, TempElmts); + Constant* display = Context.getConstantArray(DTy, TempElmts); TempElmts.clear(); display = new GlobalVariable(*getLLVMModule(), DTy, true, @@ -1422,7 +1422,7 @@ } } - Constant* Array = ConstantArray::get(ATy, Elemts); + Constant* Array = Context.getConstantArray(ATy, Elemts); return Array; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Wed Jul 22 04:35:27 2009 @@ -63,7 +63,7 @@ TheCompiler = C; module = TheCompiler->getIntrinsics(); llvmFunction = func; - llvmContext = func->getContext(); + llvmContext = &func->getContext(); inlining = false; callsStackWalker = false; endNode = 0; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Wed Jul 22 04:35:27 2009 @@ -2056,7 +2056,7 @@ } else { BasicBlock* ifFalse = createBasicBlock("false type compare"); BranchInst::Create(endBlock, ifFalse, cmp, currentBlock); - node->addIncoming(llvmContext->getConstantIntFalse(), currentBlock); + node->addIncoming(llvmContext->getFalse(), currentBlock); currentBlock = ifFalse; } Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Wed Jul 22 04:35:27 2009 @@ -119,7 +119,7 @@ JavaLLVMCompiler* TheCompiler = (JavaLLVMCompiler*)meth->classDef->classLoader->getCompiler(); JnjvmModule* module = TheCompiler->getIntrinsics(); - LLVMContext* Context = F.getContext(); + LLVMContext* Context = &F.getContext(); bool Changed = false; for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { BasicBlock *Cur = BI; @@ -132,7 +132,7 @@ Value* Arg = Cmp->getOperand(0); if (isVirtual(meth->access) && Arg == F.arg_begin()) { Changed = true; - Cmp->replaceAllUsesWith(Context->getConstantIntFalse()); + Cmp->replaceAllUsesWith(Context->getFalse()); Cmp->eraseFromParent(); break; } @@ -141,7 +141,7 @@ Instruction* CI = Ca.getInstruction(); if (CI && Ca.getCalledValue() == module->JavaObjectAllocateFunction) { Changed = true; - Cmp->replaceAllUsesWith(Context->getConstantIntFalse()); + Cmp->replaceAllUsesWith(Context->getFalse()); Cmp->eraseFromParent(); break; } @@ -472,14 +472,13 @@ } else if (V == module->GetArrayClassFunction) { const llvm::Type* Ty = PointerType::getUnqual(module->JavaCommonClassType); - Constant* nullValue = F.getContext()->getNullValue(Ty); + Constant* nullValue = Context->getNullValue(Ty); // Check if we have already proceed this call. if (Call.getArgument(1) == nullValue) { BasicBlock* NBB = II->getParent()->splitBasicBlock(II); I->getParent()->getTerminator()->eraseFromParent(); - Constant* init = - F.getContext()->getNullValue(module->JavaClassArrayType); + Constant* init = Context->getNullValue(module->JavaClassArrayType); GlobalVariable* GV = new GlobalVariable(*(F.getParent()), module->JavaClassArrayType, false, GlobalValue::ExternalLinkage, @@ -551,7 +550,7 @@ Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, CurVT, VT2, ""); - node->addIncoming(Context->getConstantIntTrue(), CI->getParent()); + node->addIncoming(Context->getTrue(), CI->getParent()); BranchInst::Create(CurEndBlock, FailedBlock, res, CI); Value* Args[2] = { VT1, VT2 }; @@ -670,9 +669,9 @@ // Final block, that gets the result. PHINode* node = PHINode::Create(Type::Int1Ty, "", BB9); node->reserveOperandSpace(3); - node->addIncoming(Context->getConstantIntTrue(), CI->getParent()); - node->addIncoming(Context->getConstantIntFalse(), BB7); - node->addIncoming(Context->getConstantIntTrue(), BB5); + node->addIncoming(Context->getTrue(), CI->getParent()); + node->addIncoming(Context->getFalse(), BB7); + node->addIncoming(Context->getTrue(), BB5); // Don't forget to jump to the next block. BranchInst::Create(EndBlock, BB9); Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Wed Jul 22 04:35:27 2009 @@ -113,7 +113,7 @@ args.push_back(zero); if (boxed) { ConstantInt* CI = dyn_cast(field->offset); - args.push_back(llvmFunction->getContext()->getConstantInt(CI->getValue() + 1)); + args.push_back(llvmFunction->getContext().getConstantInt(CI->getValue() + 1)); } else { args.push_back(field->offset); } @@ -125,7 +125,7 @@ args.push_back(zero); if (boxed) { ConstantInt* CI = dyn_cast(field->offset); - args.push_back(llvmFunction->getContext()->getConstantInt(CI->getValue() + 1)); + args.push_back(llvmFunction->getContext().getConstantInt(CI->getValue() + 1)); } else { args.push_back(field->offset); } @@ -631,7 +631,7 @@ std::vector params; params.push_back(new BitCastInst(obj, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); @@ -738,14 +738,14 @@ std::vector params; params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); } else { type = field->signature->naturalType; if (val == constantVMObjectNull) { - val = llvmFunction->getContext()->getNullValue(type); + val = llvmFunction->getContext().getNullValue(type); } else if (type != valType) { val = changeType(val, type); } @@ -771,7 +771,7 @@ const Type* type = field->signature->naturalType; const Type* valType = val->getType(); if (val == constantVMObjectNull) { - val = llvmFunction->getContext()->getNullValue(type); + val = llvmFunction->getContext().getNullValue(type); } else if (type != valType) { val = changeType(val, type); } @@ -780,7 +780,7 @@ void CLIJit::JITVerifyNull(Value* obj) { CLIJit* jit = this; - Constant* zero = llvmFunction->getContext()->getNullValue(obj->getType()); + Constant* zero = llvmFunction->getContext().getNullValue(obj->getType()); Value* test = new ICmpInst(*jit->currentBlock, ICmpInst::ICMP_EQ, obj, zero, ""); @@ -950,7 +950,7 @@ void* natPtr = NativeUtil::nativeLookup(compilingClass, compilingMethod); Value* valPtr = - ConstantExpr::getIntToPtr(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, (uint64)natPtr), + ConstantExpr::getIntToPtr(llvmFunction->getContext().getConstantInt(Type::Int64Ty, (uint64)natPtr), PointerType::getUnqual(funcType)); Value* result = CallInst::Create(valPtr, nativeArgs.begin(), @@ -1225,7 +1225,7 @@ cl->resolveType(false, false, genMethod); AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { - new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, + new StoreInst(llvmFunction->getContext().getNullValue(cl->naturalType), alloc, false, currentBlock); } else { uint64 size = module->getTypeSize(cl->naturalType); @@ -1234,7 +1234,7 @@ params.push_back(new BitCastInst(alloc, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); @@ -1282,7 +1282,7 @@ currentBlock)); params.push_back(new BitCastInst(endNode, module->ptrType, "", currentBlock)); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantFour); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1402,7 +1402,7 @@ cl->resolveType(false, false, genMethod); AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock); if (cl->naturalType->isSingleValueType()) { - new StoreInst(llvmFunction->getContext()->getNullValue(cl->naturalType), alloc, false, + new StoreInst(llvmFunction->getContext().getNullValue(cl->naturalType), alloc, false, currentBlock); } else { uint64 size = module->getTypeSize(cl->naturalType); @@ -1411,7 +1411,7 @@ params.push_back(new BitCastInst(alloc, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); Modified: vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp Wed Jul 22 04:35:27 2009 @@ -46,7 +46,7 @@ Changed = true; Value* val = CI->getOperand(1); // get the array std::vector args; //size= 2 - args.push_back(F.getContext()->getConstantInt(Type::Int32Ty, 0)); + args.push_back(F.getContext().getConstantInt(Type::Int32Ty, 0)); args.push_back(n3::VMArray::sizeOffset()); Value* ptr = GetElementPtrInst::Create(val, args.begin(), args.end(), "", CI); Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Wed Jul 22 04:35:27 2009 @@ -176,7 +176,7 @@ std::vector params; params.push_back(new BitCastInst(local, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); } else { @@ -195,7 +195,7 @@ std::vector params; params.push_back(new BitCastInst(ret, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); return ret; @@ -230,13 +230,13 @@ #if N3_EXECUTE > 1 if (bytecodes[i] == 0xFE) { std::vector args; - args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)OpcodeNamesFE[bytecodes[i + 1]])); - args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); + args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)OpcodeNamesFE[bytecodes[i + 1]])); + args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); CallInst::Create(printExecutionLLVM, args.begin(), args.end(), "", currentBlock); } else { std::vector args; - args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]])); - args.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); + args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]])); + args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); CallInst::Create(printExecutionLLVM, args.begin(), args.end(), "", currentBlock); } #endif @@ -343,7 +343,7 @@ #define TEST(name, read, cmpf, cmpi, offset) case name : { \ uint32 tmp = i; \ Value* val2 = pop(); \ - Value* val1 = llvmFunction->getContext()->getNullValue(val2->getType()); \ + Value* val1 = llvmFunction->getContext().getNullValue(val2->getType()); \ BasicBlock* ifTrue = opcodeInfos[tmp + offset + read(bytecodes, i)].newBlock; \ Value* test = 0; \ if (val1->getType()->isFloatingPoint()) { \ @@ -705,7 +705,7 @@ uint32 index = 0; for (std::vector::iterator i = leaves.begin(), e = leaves.end(); i!= e; ++i, ++index) { - inst->addCase(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, index), *i); + inst->addCase(llvmFunction->getContext().getConstantInt(Type::Int32Ty, index), *i); } //currentBlock = bb2; @@ -749,22 +749,22 @@ } case LDC_I4 : { - push(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, readS4(bytecodes, i))); + push(llvmFunction->getContext().getConstantInt(Type::Int32Ty, readS4(bytecodes, i))); break; } case LDC_I8 : { - push(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, readS8(bytecodes, i))); + push(llvmFunction->getContext().getConstantInt(Type::Int64Ty, readS8(bytecodes, i))); break; } case LDC_R4 : { - push(llvmFunction->getContext()->getConstantFP(Type::FloatTy, readFloat(bytecodes, i))); + push(llvmFunction->getContext().getConstantFP(Type::FloatTy, readFloat(bytecodes, i))); break; } case LDC_R8 : { - push(llvmFunction->getContext()->getConstantFP(Type::DoubleTy, readDouble(bytecodes, i))); + push(llvmFunction->getContext().getConstantFP(Type::DoubleTy, readDouble(bytecodes, i))); break; } @@ -819,7 +819,7 @@ } case LDC_I4_S : { - push(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, readS1(bytecodes, i))); + push(llvmFunction->getContext().getConstantInt(Type::Int32Ty, readS1(bytecodes, i))); break; } @@ -954,7 +954,7 @@ } if (res) { Value* expr = ConstantExpr::getIntToPtr( - llvmFunction->getContext()->getConstantInt(Type::Int64Ty, + llvmFunction->getContext().getConstantInt(Type::Int64Ty, uint64_t (leaveIndex++)), VMObject::llvmType); @@ -986,7 +986,7 @@ } if (res) { Value* expr = ConstantExpr::getIntToPtr( - llvmFunction->getContext()->getConstantInt(Type::Int64Ty, + llvmFunction->getContext().getConstantInt(Type::Int64Ty, uint64_t (leaveIndex++)), VMObject::llvmType); @@ -1022,7 +1022,7 @@ case NEG : { Value* val = pop(); push(BinaryOperator::CreateSub( - llvmFunction->getContext()->getNullValue(val->getType()), + llvmFunction->getContext().getNullValue(val->getType()), val, "", currentBlock)); break; } @@ -1030,7 +1030,7 @@ case NOP : break; case NOT : { - push(BinaryOperator::CreateNot(*(llvmFunction->getContext()), pop(), "", currentBlock)); + push(BinaryOperator::CreateNot(llvmFunction->getContext(), pop(), "", currentBlock)); break; } @@ -1262,7 +1262,7 @@ sint32 index = next + offset; assert(index > 0); BasicBlock* BB = opcodeInfos[index].newBlock; - SI->addCase(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, t), BB); + SI->addCase(llvmFunction->getContext().getConstantInt(Type::Int32Ty, t), BB); } break; } @@ -1313,7 +1313,7 @@ std::vector params; params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1385,8 +1385,8 @@ Value* obj = pop(); Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, obj, - llvmFunction->getContext()->getNullValue(obj->getType()), ""); - Constant* nullVirtual = llvmFunction->getContext()->getNullValue(dcl->virtualType); + llvmFunction->getContext().getNullValue(obj->getType()), ""); + Constant* nullVirtual = llvmFunction->getContext().getNullValue(dcl->virtualType); BasicBlock* isInstEndBlock = createBasicBlock("end isinst"); @@ -1580,7 +1580,7 @@ uint32 value = readU4(bytecodes, i); uint32 index = value & 0xfffffff; const UTF8* utf8 = compilingClass->assembly->readUserString(index); - Value* val = ConstantExpr::getIntToPtr(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, (int64_t)utf8), + Value* val = ConstantExpr::getIntToPtr(llvmFunction->getContext().getConstantInt(Type::Int64Ty, (int64_t)utf8), module->ptrType); Value* res = CallInst::Create(newStringLLVM, val, "", currentBlock); /*CLIString * str = @@ -1812,7 +1812,7 @@ std::vector params; params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1963,7 +1963,7 @@ params.push_back(new BitCastInst(pop(), module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext()->getConstantInt(Type::Int32Ty, size)); + params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); Modified: vmkit/trunk/lib/N3/VMCore/VMCache.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMCache.cpp?rev=76732&r1=76731&r2=76732&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMCache.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMCache.cpp Wed Jul 22 04:35:27 2009 @@ -92,7 +92,7 @@ Value* five = module->constantFive; Value* llvmEnv = - ConstantExpr::getIntToPtr(llvmFunction->getContext()->getConstantInt(Type::Int64Ty, uint64_t (enveloppe)), + ConstantExpr::getIntToPtr(llvmFunction->getContext().getConstantInt(Type::Int64Ty, uint64_t (enveloppe)), Enveloppe::llvmType); std::vector args1; From nicolas.geoffray at lip6.fr Wed Jul 22 06:52:31 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 22 Jul 2009 13:52:31 -0000 Subject: [vmkit-commits] [vmkit] r76737 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h include/mvm/Threads/Thread.h lib/JnJVM/Compiler/JavaJIT.cpp lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/Compiler/LowerConstantCalls.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll Message-ID: <200907221352.n6MDqYxX024636@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 22 08:52:07 2009 New Revision: 76737 URL: http://llvm.org/viewvc/llvm-project?rev=76737&view=rev Log: Create constants for accessing thread fields instead of using directly the offset, and add a new field doYield to the thread. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/include/mvm/Threads/Thread.h vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=76737&r1=76736&r2=76737&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Wed Jul 22 08:52:07 2009 @@ -324,6 +324,9 @@ llvm::Constant* OffsetInitializedInTaskClassMirrorConstant; llvm::Constant* OffsetStatusInTaskClassMirrorConstant; + llvm::Constant* OffsetDoYieldInThreadConstant; + llvm::Constant* OffsetIsolateInThreadConstant; + llvm::Constant* OffsetJNIInThreadConstant; llvm::Constant* OffsetJavaExceptionInThreadConstant; llvm::Constant* OffsetCXXExceptionInThreadConstant; Modified: vmkit/trunk/include/mvm/Threads/Thread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=76737&r1=76736&r2=76737&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Threads/Thread.h (original) +++ vmkit/trunk/include/mvm/Threads/Thread.h Wed Jul 22 08:52:07 2009 @@ -138,7 +138,11 @@ /// baseSP - The base stack pointer. /// void* baseSP; - + + /// doYield - Flag to tell the thread to yield for GC reasons. + /// + bool doYield; + /// get - Get the thread specific data of the current thread. /// static Thread* get() { Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=76737&r1=76736&r2=76737&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Wed Jul 22 08:52:07 2009 @@ -322,7 +322,7 @@ Value* threadId = getCurrentThread(); - Value* geps[2] = { module->constantZero, module->constantEight }; + Value* geps[2] = { module->constantZero, module->OffsetJNIInThreadConstant }; Value* jniEnv = GetElementPtrInst::Create(threadId, geps, geps + 2, "", currentBlock); Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=76737&r1=76736&r2=76737&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Wed Jul 22 08:52:07 2009 @@ -196,8 +196,11 @@ OffsetStatusInTaskClassMirrorConstant = constantZero; OffsetInitializedInTaskClassMirrorConstant = constantOne; - OffsetJavaExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 9); - OffsetCXXExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 10); + OffsetIsolateInThreadConstant = Context.getConstantInt(Type::Int32Ty, 3); + OffsetDoYieldInThreadConstant = Context.getConstantInt(Type::Int32Ty, 6); + OffsetJNIInThreadConstant = Context.getConstantInt(Type::Int32Ty, 9); + OffsetJavaExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 10); + OffsetCXXExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 11); ClassReadyConstant = Context.getConstantInt(Type::Int8Ty, ready); Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp?rev=76737&r1=76736&r2=76737&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Wed Jul 22 08:52:07 2009 @@ -50,8 +50,9 @@ threadId = new IntToPtrInst(threadId, module->ptr32Type, "", CI); - Value* IsolateID = GetElementPtrInst::Create(threadId, module->constantThree, - "", CI); + Value* IsolateID = GetElementPtrInst::Create(threadId, + module->OffsetIsolateInThreadConstant, "", CI); + IsolateID = new LoadInst(IsolateID, "", CI); Value* GEP2[2] = { module->constantZero, IsolateID }; @@ -74,8 +75,9 @@ threadId = new IntToPtrInst(threadId, module->ptr32Type, "", CI); - Value* IsolateID = GetElementPtrInst::Create(threadId, module->constantThree, - "", CI); + Value* IsolateID = GetElementPtrInst::Create(threadId, + module->OffsetIsolateInThreadConstant, "", CI); + IsolateID = new LoadInst(IsolateID, "", CI); Value* GEP2[2] = { module->constantZero, IsolateID }; Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=76737&r1=76736&r2=76737&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Wed Jul 22 08:52:07 2009 @@ -40,13 +40,14 @@ ;;; Field 3: IsolateID ;;; Field 4: MyVM ;;; Field 5: baseSP -;;; Field 6: internalThreadID -;;; field 7: routine -;;; field 8: jnienv -;;; field 9: Java pendingException -;;; field 10: CXX pendingException -%JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i8*, i8*, - i8*, %JavaObject*, i8* } +;;; Field 6: doYield +;;; Field 7: internalThreadID +;;; field 8: routine +;;; field 9: jnienv +;;; field 10: Java pendingException +;;; field 11: CXX pendingException +%JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i1, i8*, + i8*, i8*, %JavaObject*, i8* } %Attribut = type { %UTF8*, i32, i32 } From sanxiyn at gmail.com Fri Jul 24 05:22:27 2009 From: sanxiyn at gmail.com (Seo Sanghyeon) Date: Fri, 24 Jul 2009 12:22:27 -0000 Subject: [vmkit-commits] [vmkit] r76968 - /vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Message-ID: <200907241222.n6OCMRKo015147@zion.cs.uiuc.edu> Author: sanxiyn Date: Fri Jul 24 07:22:25 2009 New Revision: 76968 URL: http://llvm.org/viewvc/llvm-project?rev=76968&view=rev Log: Build fix Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc?rev=76968&r1=76967&r2=76968&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Fri Jul 24 07:22:25 2009 @@ -83,7 +83,7 @@ typedef int (*onLoad_t)(const void**, void*); extern "C" void jnjvmJNIProceedPendingException(uint32** old, void** oldBuf); extern "C" void jnjvmGetSJLJBuffer(uint32* num, uint32** old, void* newBuf, - void** newBuf); + void** oldBuf); // Calls the JNI_OnLoad function of a dynamic library. void callOnLoad(void* res, JnjvmClassLoader* loader, Jnjvm* vm) { From nicolas.geoffray at lip6.fr Mon Jul 27 10:13:15 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 27 Jul 2009 17:13:15 -0000 Subject: [vmkit-commits] [vmkit] r77206 - /vmkit/trunk/tools/vmjc/vmjc.cpp Message-ID: <200907271713.n6RHDF8t013427@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 27 12:13:10 2009 New Revision: 77206 URL: http://llvm.org/viewvc/llvm-project?rev=77206&view=rev Log: Set the JIT target, for now. Modified: vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=77206&r1=77205&r2=77206&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Mon Jul 27 12:13:10 2009 @@ -130,6 +130,7 @@ void addCommandLinePass(char** argv) { FunctionPassManager* Passes = mvm::MvmModule::globalFunctionPasses; + Passes->add(new TargetData(*mvm::MvmModule::TheTargetData)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { From nicolas.geoffray at lip6.fr Mon Jul 27 10:14:27 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 27 Jul 2009 17:14:27 -0000 Subject: [vmkit-commits] [vmkit] r77207 - in /vmkit/trunk/lib/JnJVM/Compiler: ExceptionsCheck.inc ExceptionsDwarf.inc JavaJIT.cpp JavaJIT.h JavaJITOpcodes.cpp Message-ID: <200907271714.n6RHER0i013471@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 27 12:14:26 2009 New Revision: 77207 URL: http://llvm.org/viewvc/llvm-project?rev=77207&view=rev Log: Java stacks are now handled with Allocas instead of direcly. This allows to declare values as being gc_root. Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc?rev=77207&r1=77206&r2=77207&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc Mon Jul 27 12:14:26 2009 @@ -353,6 +353,7 @@ // Set the Java handler for this exception. ex->javaHandler = opcodeInfos[ex->handlerpc].newBlock; + opcodeInfos[ex->handlerpc].handler = true; if (ex->javaHandler->empty()) { PHINode::Create(JnjvmModule::JavaObjectType, "", ex->javaHandler); Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc?rev=77207&r1=77206&r2=77207&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc Mon Jul 27 12:14:26 2009 @@ -267,6 +267,7 @@ // Set the Java handler for this exception. ex->javaHandler = opcodeInfos[ex->handlerpc].newBlock; + opcodeInfos[ex->handlerpc].handler = true; // Set the native handler of this exception, which will catch the exception // object. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=77207&r1=77206&r2=77207&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Mon Jul 27 12:14:26 2009 @@ -94,7 +94,7 @@ const UTF8* name = 0; Signdef* signature = ctpInfo->infoOfInterfaceOrVirtualMethod(index, name); - Value* obj = stack[stack.size() - signature->nbArguments - 1].first; + Value* obj = objectStack[stack.size() - signature->nbArguments - 1]; JavaObject* source = TheCompiler->getFinalObject(obj); if (source) { return invokeSpecial(index, source->getClass()); @@ -666,6 +666,24 @@ } } } + +static void removeUnusedObjects(std::vector& objects, + JnjvmModule* module) { + for (std::vector::iterator i = objects.begin(), + e = objects.end(); i != e; ++i) { + AllocaInst* temp = *i; + if (temp->getNumUses()) { + Instruction* I = new BitCastInst(temp, module->ptrPtrType, ""); + I->insertAfter(temp); + Value* GCArgs[2] = { I, module->constantPtrNull }; + Instruction* C = CallInst::Create(module->llvm_gc_gcroot, GCArgs, + GCArgs + 2, ""); + C->insertAfter(I); + } else { + temp->eraseFromParent(); + } + } +} Instruction* JavaJIT::inlineCompile(BasicBlock*& curBB, BasicBlock* endExBlock, @@ -685,7 +703,7 @@ } Reader reader(codeAtt, &(compilingClass->bytes)); - /* uint16 maxStack = */ reader.readU2(); + uint16 maxStack = reader.readU2(); uint16 maxLocals = reader.readU2(); uint32 codeLen = reader.readU4(); uint32 start = reader.cursor; @@ -722,6 +740,15 @@ objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", firstInstruction)); } + for (int i = 0; i < maxStack; i++) { + objectStack.push_back(new AllocaInst(module->JavaObjectType, "", + firstInstruction)); + intStack.push_back(new AllocaInst(Type::Int32Ty, "", firstInstruction)); + doubleStack.push_back(new AllocaInst(Type::DoubleTy, "", + firstInstruction)); + longStack.push_back(new AllocaInst(Type::Int64Ty, "", firstInstruction)); + floatStack.push_back(new AllocaInst(Type::FloatTy, "", firstInstruction)); + } } else { for (int i = 0; i < maxLocals; i++) { @@ -732,6 +759,15 @@ objectLocals.push_back(new AllocaInst(module->JavaObjectType, "", firstBB)); } + + for (int i = 0; i < maxStack; i++) { + objectStack.push_back(new AllocaInst(module->JavaObjectType, "", + firstBB)); + intStack.push_back(new AllocaInst(Type::Int32Ty, "", firstBB)); + doubleStack.push_back(new AllocaInst(Type::DoubleTy, "", firstBB)); + longStack.push_back(new AllocaInst(Type::Int64Ty, "", firstBB)); + floatStack.push_back(new AllocaInst(Type::FloatTy, "", firstBB)); + } } @@ -800,24 +836,17 @@ curBB = endBlock; - for (std::vector::iterator i = objectLocals.begin(), - e = objectLocals.end(); i != e; ++i) { - AllocaInst* temp = *i; - if (temp->getNumUses()) { - Instruction* I = new BitCastInst(temp, module->ptrPtrType, ""); - I->insertAfter(temp); - Value* GCArgs[2] = { I, module->constantPtrNull }; - Instruction* C = CallInst::Create(module->llvm_gc_gcroot, GCArgs, - GCArgs + 2, ""); - C->insertAfter(I); - } else { - temp->eraseFromParent(); - } - } removeUnusedLocals(intLocals); removeUnusedLocals(doubleLocals); removeUnusedLocals(floatLocals); removeUnusedLocals(longLocals); + removeUnusedLocals(intStack); + removeUnusedLocals(doubleStack); + removeUnusedLocals(floatStack); + removeUnusedLocals(longStack); + + removeUnusedObjects(objectLocals, module); + removeUnusedObjects(objectStack, module); return endNode; @@ -842,7 +871,7 @@ } Reader reader(codeAtt, &(compilingClass->bytes)); - /* uint16 maxStack = */ reader.readU2(); + uint16 maxStack = reader.readU2(); uint16 maxLocals = reader.readU2(); uint32 codeLen = reader.readU4(); uint32 start = reader.cursor; @@ -884,6 +913,15 @@ currentBlock)); } + for (int i = 0; i < maxStack; i++) { + objectStack.push_back(new AllocaInst(module->JavaObjectType, "", + currentBlock)); + intStack.push_back(new AllocaInst(Type::Int32Ty, "", currentBlock)); + doubleStack.push_back(new AllocaInst(Type::DoubleTy, "", currentBlock)); + longStack.push_back(new AllocaInst(Type::Int64Ty, "", currentBlock)); + floatStack.push_back(new AllocaInst(Type::FloatTy, "", currentBlock)); + } + uint32 index = 0; uint32 count = 0; #if defined(ISOLATE_SHARING) @@ -1100,26 +1138,18 @@ currentBlock = endExceptionBlock; finishExceptions(); - - for (std::vector::iterator i = objectLocals.begin(), - e = objectLocals.end(); i != e; ++i) { - AllocaInst* temp = *i; - if (temp->getNumUses()) { - Instruction* I = new BitCastInst(temp, module->ptrPtrType, ""); - I->insertAfter(temp); - Value* GCArgs[2] = { I, module->constantPtrNull }; - Instruction* C = CallInst::Create(module->llvm_gc_gcroot, GCArgs, - GCArgs + 2, ""); - C->insertAfter(I); - } else { - temp->eraseFromParent(); - } - } - + removeUnusedLocals(intLocals); removeUnusedLocals(doubleLocals); removeUnusedLocals(floatLocals); removeUnusedLocals(longLocals); + removeUnusedLocals(intStack); + removeUnusedLocals(doubleStack); + removeUnusedLocals(floatStack); + removeUnusedLocals(longStack); + + removeUnusedObjects(objectLocals, module); + removeUnusedObjects(objectStack, module); func->setLinkage(GlobalValue::ExternalLinkage); @@ -1243,7 +1273,7 @@ BasicBlock* ifTrue = createBasicBlock("true verifyAndComputePtr"); BasicBlock* ifFalse = createBasicBlock("false verifyAndComputePtr"); - branch(cmp, ifTrue, ifFalse, currentBlock); + BranchInst::Create(ifTrue, ifFalse, cmp, currentBlock); currentBlock = ifFalse; Value* args[2] = { obj, index }; @@ -1262,51 +1292,6 @@ } -void JavaJIT::testPHINodes(BasicBlock* dest, BasicBlock* insert) { - if(dest->empty()) { - for (std::vector< std::pair >::iterator i = stack.begin(), - e = stack.end(); i!= e; ++i) { - Value* cur = i->first; - bool unsign = i->second; - PHINode* node = 0; - const Type* type = cur->getType(); - if (unsign) { - node = llvm::PHINode::Create(Type::Int32Ty, "", dest); - cur = new ZExtInst(cur, Type::Int32Ty, "", currentBlock); - } else if (type == Type::Int8Ty || type == Type::Int16Ty) { - node = llvm::PHINode::Create(Type::Int32Ty, "", dest); - cur = new SExtInst(cur, Type::Int32Ty, "", currentBlock); - } else { - node = llvm::PHINode::Create(cur->getType(), "", dest); - } - assert(node->getType() == cur->getType() && "wrong 1"); - node->addIncoming(cur, insert); - } - } else { - std::vector< std::pair >::iterator stackit = stack.begin(); - for (BasicBlock::iterator i = dest->begin(), e = dest->end(); i != e; - ++i) { - if (!(isa(i))) { - break; - } else { - Instruction* ins = i; - Value* cur = stackit->first; - const Type* type = cur->getType(); - bool unsign = stackit->second; - - if (unsign) { - cur = new ZExtInst(cur, Type::Int32Ty, "", currentBlock); - } else if (type == Type::Int8Ty || type == Type::Int16Ty) { - cur = new SExtInst(cur, Type::Int32Ty, "", currentBlock); - } - assert(ins->getType() == cur->getType() && "wrong 2"); - ((PHINode*)ins)->addIncoming(cur, insert); - ++stackit; - } - } - } -} - void JavaJIT::makeArgs(FunctionType::param_iterator it, uint32 index, std::vector& Args, uint32 nb) { #if defined(ISOLATE_SHARING) @@ -1327,7 +1312,7 @@ if (it->get() == Type::Int64Ty || it->get() == Type::DoubleTy) { pop(); } - bool unsign = topSign(); + bool unsign = topIsUnsigned(); Value* tmp = pop(); const Type* type = it->get(); @@ -1344,6 +1329,53 @@ } +void JavaJIT::addFakePHINodes(BasicBlock* dest, BasicBlock* insert) { + if(dest->empty()) { + for (std::vector::iterator i = stack.begin(), + e = stack.end(); i!= e; ++i) { + switch (*i) { + case Int : { + PHINode* node = PHINode::Create(Type::Int32Ty, "", dest); + node->addIncoming(llvmContext->getNullValue(Type::Int32Ty), insert); + break; + } + case Float : { + PHINode* node = PHINode::Create(Type::FloatTy, "", dest); + node->addIncoming(llvmContext->getNullValue(Type::FloatTy), insert); + break; + } + case Double : { + PHINode* node = PHINode::Create(Type::DoubleTy, "", dest); + node->addIncoming(llvmContext->getNullValue(Type::DoubleTy), insert); + break; + } + case Long : { + PHINode* node = PHINode::Create(Type::Int64Ty, "", dest); + node->addIncoming(llvmContext->getNullValue(Type::Int64Ty), insert); + break; + } + case Object : { + PHINode* node = PHINode::Create(module->JavaObjectType, "", dest); + node->addIncoming(llvmContext->getNullValue(module->JavaObjectType), + insert); + break; + } + default : + abort(); + } + } + } else { + for (BasicBlock::iterator i = dest->begin(), e = dest->end(); i != e; ++i) { + if (PHINode* node = dyn_cast(i)) { + node->addIncoming(llvmContext->getNullValue(node->getType()), insert); + } else { + break; + } + } + } +} + + Instruction* JavaJIT::lowerMathOps(const UTF8* name, std::vector& args) { JnjvmBootstrapLoader* loader = compilingClass->classLoader->bootstrapLoader; @@ -1847,7 +1879,7 @@ void JavaJIT::setStaticField(uint16 index) { - bool unsign = topSign(); + bool unsign = topIsUnsigned(); Value* val = pop(); Typedef* sign = compilingClass->ctpInfo->infoOfField(index); @@ -1934,7 +1966,7 @@ } void JavaJIT::setVirtualField(uint16 index) { - bool unsign = topSign(); + bool unsign = topIsUnsigned(); Value* val = pop(); Typedef* sign = compilingClass->ctpInfo->infoOfField(index); LLVMAssessorInfo& LAI = TheCompiler->getTypedefInfo(sign); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h?rev=77207&r1=77206&r2=77207&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Mon Jul 27 12:14:26 2009 @@ -45,7 +45,12 @@ /// exceptionBlock - Never null, the exception destination of the /// instruction. /// - llvm::BasicBlock* exceptionBlock; + llvm::BasicBlock* exceptionBlock; + + /// handler - If the instruction is the first instruction of a Java exception + /// handler. + /// + bool handler; }; @@ -67,6 +72,7 @@ inlining = false; callsStackWalker = false; endNode = 0; + currentStackIndex = 0; } /// javaCompile - Compile the Java method. @@ -180,37 +186,105 @@ //===------------------------- Stack manipulation -------------------------===// - - /// stack - The compiler stack. We store the value and its sign. - std::vector< std::pair > stack; + + typedef enum { + Int = 0, + Float, + Double, + Long, + Object + } StackTypeInfo; + + + std::map* > StackBlockInfo; + + /// stack - The compiler stack. + std::vector stack; + uint32 currentStackIndex; + std::vector objectStack; + std::vector intStack; + std::vector longStack; + std::vector floatStack; + std::vector doubleStack; /// push - Push a new value in the stack. void push(llvm::Value* val, bool unsign) { - stack.push_back(std::make_pair(val, unsign)); + const llvm::Type* type = val->getType(); + if (unsign) { + val = new llvm::ZExtInst(val, llvm::Type::Int32Ty, "", currentBlock); + new llvm::StoreInst(val, intStack[currentStackIndex++], false, + currentBlock); + stack.push_back(Int); + } else if (type == llvm::Type::Int8Ty || type == llvm::Type::Int16Ty) { + val = new llvm::SExtInst(val, llvm::Type::Int32Ty, "", currentBlock); + new llvm::StoreInst(val, intStack[currentStackIndex++], false, + currentBlock); + stack.push_back(Int); + } else if (type == llvm::Type::Int32Ty) { + new llvm::StoreInst(val, intStack[currentStackIndex++], false, + currentBlock); + stack.push_back(Int); + } else if (type == llvm::Type::Int64Ty) { + new llvm::StoreInst(val, longStack[currentStackIndex++], false, + currentBlock); + stack.push_back(Long); + } else if (type == llvm::Type::FloatTy) { + new llvm::StoreInst(val, floatStack[currentStackIndex++], false, + currentBlock); + stack.push_back(Float); + } else if (type == llvm::Type::DoubleTy) { + new llvm::StoreInst(val, doubleStack[currentStackIndex++], false, + currentBlock); + stack.push_back(Double); + } else { + assert(type == module->JavaObjectType && "Can't handle this type"); + new llvm::StoreInst(val, objectStack[currentStackIndex++], false, + currentBlock); + stack.push_back(Object); + } } - /// push - Push a new value in the stack. - void push(std::pair pair) { - stack.push_back(pair); - } - /// pop - Pop a value from the stack and return it. llvm::Value* pop() { - llvm::Value * ret = top(); + llvm::Value* res = top(); + --currentStackIndex; stack.pop_back(); - return ret; + return res; } /// top - Return the value on top of the stack. llvm::Value* top() { - return stack.back().first; + StackTypeInfo STI = stack.back(); + switch (STI) { + case Int: + return new llvm::LoadInst(intStack[currentStackIndex - 1], false, + currentBlock); + case Float: + return new llvm::LoadInst(floatStack[currentStackIndex - 1], false, + currentBlock); + case Double: + return new llvm::LoadInst(doubleStack[currentStackIndex - 1], false, + currentBlock); + case Long: + return new llvm::LoadInst(longStack[currentStackIndex - 1], false, + currentBlock); + case Object: + return new llvm::LoadInst(objectStack[currentStackIndex - 1], false, + currentBlock); + default: + assert(0 && "Can not be here"); + } } - /// topSign - Return the sign of the value on top of the stack. - bool topSign() { - return stack.back().second; + /// topTypeInfo - Return the type of the value on top of the stack. + StackTypeInfo topTypeInfo() { + return stack.back(); } + bool topIsUnsigned() { + return false; + } + /// stackSize - Return the size of the stack. uint32 stackSize() { return stack.size(); @@ -219,25 +293,7 @@ /// popAsInt - Pop a value from the stack and returns it as a Java /// int, ie signed int32. llvm::Value* popAsInt() { - llvm::Value * ret = top(); - bool unsign = topSign(); - stack.pop_back(); - - if (ret->getType() != llvm::Type::Int32Ty) { - if (unsign) { - ret = new llvm::ZExtInst(ret, llvm::Type::Int32Ty, "", currentBlock); - } else { - ret = new llvm::SExtInst(ret, llvm::Type::Int32Ty, "", currentBlock); - } - } - return ret; - } - - /// popPair - Pop the pair on the stack and return it. - std::pair popPair() { - std::pair ret = stack.back(); - stack.pop_back(); - return ret; + return pop(); } //===------------------------- Exception support --------------------------===// @@ -278,25 +334,24 @@ llvm::BasicBlock* createBasicBlock(const char* name = "") { return llvm::BasicBlock::Create(name, llvmFunction); } - + /// branch - Branch based on a boolean value. Update PHI nodes accordingly. void branch(llvm::Value* test, llvm::BasicBlock* ifTrue, llvm::BasicBlock* ifFalse, llvm::BasicBlock* insert) { - testPHINodes(ifTrue, insert); - testPHINodes(ifFalse, insert); + addFakePHINodes(ifTrue, insert); + addFakePHINodes(ifFalse, insert); llvm::BranchInst::Create(ifTrue, ifFalse, test, insert); } /// branch - Branch to a new block. Update PHI nodes accordingly. void branch(llvm::BasicBlock* dest, llvm::BasicBlock* insert) { - testPHINodes(dest, insert); + addFakePHINodes(dest, insert); llvm::BranchInst::Create(dest, insert); } /// testPHINodes - Update PHI nodes when branching to a new block. - void testPHINodes(llvm::BasicBlock* dest, llvm::BasicBlock* insert); - - + void addFakePHINodes(llvm::BasicBlock* dest, llvm::BasicBlock* insert); + //===-------------------------- Synchronization --------------------------===// /// beginSynchronize - Emit synchronization code to acquire the instance @@ -404,6 +459,9 @@ /// method. uint32 nbEnveloppes; +//===--------------------- Yield point support ---------------------------===// + + void checkYieldPoint(); #if defined(ISOLATE_SHARING) Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=77207&r1=77206&r2=77207&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Mon Jul 27 12:14:26 2009 @@ -135,22 +135,43 @@ PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "\n"); Opinfo* opinfo = &(opcodeInfos[i]); + if (opinfo->newBlock) { if (currentBlock->getTerminator() == 0) { branch(opinfo->newBlock, currentBlock); } + currentBlock = opinfo->newBlock; + stack.clear(); + currentStackIndex = 0; for (BasicBlock::iterator i = opinfo->newBlock->begin(), e = opinfo->newBlock->end(); i != e; ++i) { if (!(isa(i))) { break; } else { - stack.push_back(std::make_pair(i, false)); + ++currentStackIndex; + const Type* Ty = i->getType(); + if (Ty == Type::Int32Ty) { + stack.push_back(Int); + } else if (Ty == Type::Int64Ty) { + stack.push_back(Long); + } else if (Ty == Type::FloatTy) { + stack.push_back(Float); + } else if (Ty == Type::DoubleTy) { + stack.push_back(Double); + } else if (Ty == module->JavaObjectType) { + stack.push_back(Object); + if (opinfo->handler) { + // If it's a handler, put the exception object in the stack. + new StoreInst(i, objectStack[currentStackIndex - 1], "", + currentBlock); + } + } else { + abort(); + } } } - - currentBlock = opinfo->newBlock; } currentExceptionBlock = opinfo->exceptionBlock; @@ -749,71 +770,78 @@ break; case DUP : - push(top(), topSign()); + push(top(), topIsUnsigned()); break; case DUP_X1 : { - std::pair one = popPair(); - std::pair two = popPair(); - push(one); - push(two); - push(one); + Value* one = pop(); + Value* two = pop(); + + push(one, false); + push(two, false); + push(one, false); break; } case DUP_X2 : { - std::pair one = popPair(); - std::pair two = popPair(); - std::pair three = popPair(); - push(one); - push(three); - push(two); - push(one); + Value* one = pop(); + Value* two = pop(); + Value* three = pop(); + push(one, false); + push(three, false); + push(two, false); + push(one, false); break; } - case DUP2 : - push(stack[stackSize() - 2]); - push(stack[stackSize() - 2]); + case DUP2 : { + Value* one = pop(); + Value* two = pop(); + + push(two, false); + push(one, false); + push(two, false); + push(one, false); break; + } case DUP2_X1 : { - std::pair one = popPair(); - std::pair two = popPair(); - std::pair three = popPair(); - - push(two); - push(one); - - push(three); - push(two); - push(one); + Value* one = pop(); + Value* two = pop(); + Value* three = pop(); + + push(two, false); + push(one, false); + + push(three, false); + push(two, false); + push(one, false); break; } case DUP2_X2 : { - std::pair one = popPair(); - std::pair two = popPair(); - std::pair three = popPair(); - std::pair four = popPair(); - - push(two); - push(one); - - push(four); - push(three); - push(two); - push(one); + Value* one = pop(); + Value* two = pop(); + Value* three = pop(); + Value* four = pop(); + + push(two, false); + push(one, false); + + push(four, false); + push(three, false); + push(two, false); + push(one, false); break; } case SWAP : { - std::pair one = popPair(); - std::pair two = popPair(); - push(one); - push(two); + Value* one = pop(); + Value* two = pop(); + push(one, false); + push(two, false); break; } @@ -1776,7 +1804,7 @@ BasicBlock* def = opcodeInfos[tmp + readU4(bytecodes, i)].newBlock; uint32 nbs = readU4(bytecodes, i); - bool unsign = topSign(); + bool unsign = topIsUnsigned(); Value* key = pop(); const Type* type = key->getType(); if (unsign) { @@ -1798,7 +1826,7 @@ break; } case IRETURN : { - bool unsign = topSign(); + bool unsign = topIsUnsigned(); Value* val = pop(); assert(val->getType()->isInteger()); convertValue(val, endNode->getType(), currentBlock, unsign); From nicolas.geoffray at lip6.fr Mon Jul 27 10:24:17 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 27 Jul 2009 17:24:17 -0000 Subject: [vmkit-commits] [vmkit] r77209 - /vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Message-ID: <200907271724.n6RHOIBp013743@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 27 12:24:17 2009 New Revision: 77209 URL: http://llvm.org/viewvc/llvm-project?rev=77209&view=rev Log: Fix compiler warning. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h?rev=77209&r1=77208&r2=77209&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Mon Jul 27 12:24:17 2009 @@ -274,6 +274,8 @@ default: assert(0 && "Can not be here"); } + abort(); + return 0; } /// topTypeInfo - Return the type of the value on top of the stack. From nicolas.geoffray at lip6.fr Mon Jul 27 10:54:52 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 27 Jul 2009 17:54:52 -0000 Subject: [vmkit-commits] [vmkit] r77212 - in /vmkit/trunk/lib: JnJVM/Compiler/ Mvm/Compiler/ N3/Mono/ N3/VMCore/ Message-ID: <200907271754.n6RHssii014692@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 27 12:54:50 2009 New Revision: 77212 URL: http://llvm.org/viewvc/llvm-project?rev=77212&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp vmkit/trunk/lib/N3/Mono/MonoString.cpp vmkit/trunk/lib/N3/VMCore/CLIJit.cpp vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp vmkit/trunk/lib/N3/VMCore/Opcodes.cpp vmkit/trunk/lib/N3/VMCore/VMCache.cpp vmkit/trunk/lib/N3/VMCore/VMClass.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsCheck.inc Mon Jul 27 12:54:50 2009 @@ -432,7 +432,7 @@ currentBlock); uint32 depth = cur->catchClass->virtualVT->depth; - Value* depthCl = llvmContext->getConstantInt(Type::Int32Ty, depth); + Value* depthCl = ConstantInt::get(Type::Int32Ty, depth); Value* cmp = 0; if (depth >= JavaVirtualTable::getDisplayLength()) { Modified: vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc (original) +++ vmkit/trunk/lib/JnJVM/Compiler/ExceptionsDwarf.inc Mon Jul 27 12:54:50 2009 @@ -427,7 +427,7 @@ Value* objCl = CallInst::Create(module->GetClassFunction, obj, "", currentBlock); - Value* depthCl = llvmContext->getConstantInt(Type::Int32Ty, cur->catchClass->depth); + Value* depthCl = ConstantInt::get(Type::Int32Ty, cur->catchClass->depth); Value* depthClObj = CallInst::Create(module->GetDepthFunction, objCl, "", currentBlock); @@ -530,7 +530,7 @@ cur->javaHandler); OldIsolateID = new LoadInst(IsolateIDPtr, "", cur->javaHandler); - Value* MyID = llvmContext->getConstantInt(module->pointerSizeType, + Value* MyID = ConstantInt::get(module->pointerSizeType, loader->getIsolate()->IsolateID); new StoreInst(MyID, IsolateIDPtr, cur->javaHandler); Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Mon Jul 27 12:54:50 2009 @@ -44,8 +44,6 @@ const StructType* structType = 0; JavaLLVMCompiler* Mod = (JavaLLVMCompiler*)classDef->classLoader->getCompiler(); - Module* LMod = Mod->getLLVMModule(); - LLVMContext& Context = LMod->getContext(); if (classDef->super) { LLVMClassInfo* CLI = JavaLLVMCompiler::getClassInfo(classDef->super); @@ -80,7 +78,7 @@ uint64 size = JnjvmModule::getTypeSize(structType); classDef->virtualSize = (uint32)size; - virtualSizeConstant = Context.getConstantInt(Type::Int32Ty, size); + virtualSizeConstant = ConstantInt::get(Type::Int32Ty, size); Mod->makeVT(classDef); } @@ -121,15 +119,10 @@ Value* LLVMClassInfo::getVirtualSize() { if (!virtualSizeConstant) { - JavaLLVMCompiler* Mod = - (JavaLLVMCompiler*)classDef->classLoader->getCompiler(); - Module* LMod = Mod->getLLVMModule(); - LLVMContext& Context = LMod->getContext(); - getVirtualType(); assert(classDef->virtualSize && "Zero size for a class?"); virtualSizeConstant = - Context.getConstantInt(Type::Int32Ty, classDef->virtualSize); + ConstantInt::get(Type::Int32Ty, classDef->virtualSize); } return virtualSizeConstant; } @@ -195,11 +188,9 @@ if (!offsetConstant) { JnjvmClassLoader* JCL = methodDef->classDef->classLoader; JavaLLVMCompiler* Mod = (JavaLLVMCompiler*)JCL->getCompiler(); - Module* LMod = Mod->getLLVMModule(); - LLVMContext& Context = LMod->getContext(); Mod->resolveVirtualClass(methodDef->classDef); - offsetConstant = Context.getConstantInt(Type::Int32Ty, methodDef->offset); + offsetConstant = ConstantInt::get(Type::Int32Ty, methodDef->offset); } return offsetConstant; } @@ -208,8 +199,6 @@ if (!offsetConstant) { JnjvmClassLoader* JCL = fieldDef->classDef->classLoader; JavaLLVMCompiler* Mod = (JavaLLVMCompiler*)JCL->getCompiler(); - Module* LMod = Mod->getLLVMModule(); - LLVMContext& Context = LMod->getContext(); if (isStatic(fieldDef->access)) { Mod->resolveStaticClass(fieldDef->classDef); @@ -217,7 +206,7 @@ Mod->resolveVirtualClass(fieldDef->classDef); } - offsetConstant = Context.getConstantInt(Type::Int32Ty, fieldDef->num); + offsetConstant = ConstantInt::get(Type::Int32Ty, fieldDef->num); } return offsetConstant; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Mon Jul 27 12:54:50 2009 @@ -130,14 +130,13 @@ } Constant* JavaAOTCompiler::getMethodInClass(JavaMethod* meth) { - LLVMContext& Context = getLLVMModule()->getContext(); Class* cl = meth->classDef; Constant* MOffset = 0; Constant* Array = 0; method_iterator SI = virtualMethods.find(cl); for (uint32 i = 0; i < cl->nbVirtualMethods + cl->nbStaticMethods; ++i) { if (&cl->virtualMethods[i] == meth) { - MOffset = Context.getConstantInt(Type::Int32Ty, i); + MOffset = ConstantInt::get(Type::Int32Ty, i); break; } } @@ -312,8 +311,7 @@ varGV->setInitializer(CreateConstantFromJavaObject(obj)); return C; } else { - LLVMContext& Context = getLLVMModule()->getContext(); - Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(obj)); + Constant* CI = ConstantInt::get(Type::Int64Ty, uint64_t(obj)); CI = ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); finalObjects.insert(std::make_pair(obj, CI)); return CI; @@ -346,19 +344,19 @@ if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool() || prim->isByte()) { - ConstantInt* CI = Context.getConstantInt(Type::Int8Ty, + ConstantInt* CI = ConstantInt::get(Type::Int8Ty, field.getInt8Field(obj)); Elts.push_back(CI); } else if (prim->isShort() || prim->isChar()) { - ConstantInt* CI = Context.getConstantInt(Type::Int16Ty, + ConstantInt* CI = ConstantInt::get(Type::Int16Ty, field.getInt16Field(obj)); Elts.push_back(CI); } else if (prim->isInt()) { - ConstantInt* CI = Context.getConstantInt(Type::Int32Ty, + ConstantInt* CI = ConstantInt::get(Type::Int32Ty, field.getInt32Field(obj)); Elts.push_back(CI); } else if (prim->isLong()) { - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, field.getLongField(obj)); Elts.push_back(CI); } else if (prim->isFloat()) { @@ -390,13 +388,13 @@ uint16 idx = reader.readU2(); if (type->isPrimitive()) { if (Ty == Type::Int64Ty) { - Elts.push_back(Context.getConstantInt(Ty, (uint64)ctpInfo->LongAt(idx))); + Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->LongAt(idx))); } else if (Ty == Type::DoubleTy) { Elts.push_back(Context.getConstantFP(Ty, ctpInfo->DoubleAt(idx))); } else if (Ty == Type::FloatTy) { Elts.push_back(Context.getConstantFP(Ty, ctpInfo->FloatAt(idx))); } else { - Elts.push_back(Context.getConstantInt(Ty, (uint64)ctpInfo->IntegerAt(idx))); + Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->IntegerAt(idx))); } } else if (type->isReference()){ const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[idx]); @@ -411,7 +409,7 @@ } } - return ConstantStruct::get(STy, Elts); + return Context.getConstantStruct(STy, Elts); } Constant* JavaAOTCompiler::getStaticInstance(Class* classDef) { @@ -523,10 +521,10 @@ Elmts.push_back(getVirtualTable(cl->virtualVT)); // lock - Constant* L = Context.getConstantInt(Type::Int64Ty, 0); + Constant* L = ConstantInt::get(Type::Int64Ty, 0); Elmts.push_back(ConstantExpr::getIntToPtr(L, JnjvmModule::ptrType)); - return ConstantStruct::get(STy, Elmts); + return Context.getConstantStruct(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromJavaClass(CommonClass* cl) { @@ -535,6 +533,7 @@ Module& Mod = *getLLVMModule(); const StructType* STy = dyn_cast(LCI->getVirtualType()->getContainedType(0)); + LLVMContext& Context = Mod.getContext(); std::vector Elmts; @@ -542,10 +541,10 @@ Elmts.push_back(CreateConstantForBaseObject(javaClass)); // signers - Elmts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaObjectType)); + Elmts.push_back(Context.getNullValue(JnjvmModule::JavaObjectType)); // pd - Elmts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaObjectType)); + Elmts.push_back(Context.getNullValue(JnjvmModule::JavaObjectType)); // vmdata Constant* Cl = getNativeClass(cl); @@ -554,9 +553,9 @@ Elmts.push_back(Cl); // constructor - Elmts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaObjectType)); + Elmts.push_back(Context.getNullValue(JnjvmModule::JavaObjectType)); - return ConstantStruct::get(STy, Elmts); + return Context.getConstantStruct(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromJavaObject(JavaObject* obj) { @@ -621,19 +620,19 @@ if (type->isPrimitive()) { const PrimitiveTypedef* prim = (PrimitiveTypedef*)type; if (prim->isBool() || prim->isByte()) { - ConstantInt* CI = Context.getConstantInt(Type::Int8Ty, + ConstantInt* CI = ConstantInt::get(Type::Int8Ty, field.getInt8Field(obj)); TempElts.push_back(CI); } else if (prim->isShort() || prim->isChar()) { - ConstantInt* CI = Context.getConstantInt(Type::Int16Ty, + ConstantInt* CI = ConstantInt::get(Type::Int16Ty, field.getInt16Field(obj)); TempElts.push_back(CI); } else if (prim->isInt()) { - ConstantInt* CI = Context.getConstantInt(Type::Int32Ty, + ConstantInt* CI = ConstantInt::get(Type::Int32Ty, field.getInt32Field(obj)); TempElts.push_back(CI); } else if (prim->isLong()) { - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, field.getLongField(obj)); TempElts.push_back(CI); } else if (prim->isFloat()) { @@ -658,7 +657,7 @@ } } } - CurConstant = ConstantStruct::get(STy, TempElts); + CurConstant = Context.getConstantStruct(STy, TempElts); } return CurConstant; @@ -688,11 +687,11 @@ Array = ConstantExpr::getBitCast(varGV, JnjvmModule::JavaObjectType); Elmts.push_back(Array); - Elmts.push_back(Context.getConstantInt(Type::Int32Ty, str->count)); - Elmts.push_back(Context.getConstantInt(Type::Int32Ty, str->cachedHashCode)); - Elmts.push_back(Context.getConstantInt(Type::Int32Ty, str->offset)); + Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->count)); + Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->cachedHashCode)); + Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->offset)); - return ConstantStruct::get(STy, Elmts); + return Context.getConstantStruct(STy, Elmts); } @@ -707,7 +706,7 @@ Elmts.push_back(Context.getNullValue(STy->getContainedType(2))); Elmts.push_back(getEnveloppe(CN->enveloppe)); - return ConstantStruct::get(STy, Elmts); + return Context.getConstantStruct(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromEnveloppe(Enveloppe* val) { @@ -717,6 +716,7 @@ const StructType* CNTy = dyn_cast(JnjvmModule::CacheNodeType->getContainedType(0)); Module& Mod = *getLLVMModule(); + LLVMContext& Context = Mod.getContext(); std::vector Elmts; @@ -727,11 +727,11 @@ Elmts.push_back(getUTF8(val->methodName)); Elmts.push_back(getUTF8(val->methodSign)); - Elmts.push_back(Mod.getContext().getNullValue(Type::Int32Ty)); + Elmts.push_back(Context.getNullValue(Type::Int32Ty)); Elmts.push_back(getNativeClass(val->classDef)); Elmts.push_back(firstCache); - return ConstantStruct::get(STy, Elmts); + return Context.getConstantStruct(STy, Elmts); } @@ -747,12 +747,12 @@ Elmts.push_back(getUTF8(attribut.name)); // start - Elmts.push_back(Context.getConstantInt(Type::Int32Ty, attribut.start)); + Elmts.push_back(ConstantInt::get(Type::Int32Ty, attribut.start)); // nbb - Elmts.push_back(Context.getConstantInt(Type::Int32Ty, attribut.nbb)); + Elmts.push_back(ConstantInt::get(Type::Int32Ty, attribut.nbb)); - return ConstantStruct::get(STy, Elmts); + return Context.getConstantStruct(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromCommonClass(CommonClass* cl) { @@ -774,7 +774,7 @@ CommonClassElts.push_back(Context.getConstantArray(ATy, TCM, 1)); // access - CommonClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->access)); + CommonClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->access)); // interfaces if (cl->nbInterfaces) { @@ -797,7 +797,7 @@ } // nbInterfaces - CommonClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbInterfaces)); + CommonClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbInterfaces)); // name CommonClassElts.push_back(getUTF8(cl->name)); @@ -823,7 +823,7 @@ TempTy = JnjvmModule::VTType; CommonClassElts.push_back(Mod.getContext().getNullValue(TempTy)); } - return ConstantStruct::get(STy, CommonClassElts); + return Context.getConstantStruct(STy, CommonClassElts); } Constant* JavaAOTCompiler::CreateConstantFromJavaField(JavaField& field) { @@ -839,7 +839,7 @@ FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); // access - FieldElts.push_back(Context.getConstantInt(Type::Int16Ty, field.access)); + FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.access)); // name FieldElts.push_back(getUTF8(field.name)); @@ -869,21 +869,21 @@ } // nbAttributs - FieldElts.push_back(Context.getConstantInt(Type::Int16Ty, field.nbAttributs)); + FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.nbAttributs)); // classDef FieldElts.push_back(getNativeClass(field.classDef)); // ptrOffset - FieldElts.push_back(Context.getConstantInt(Type::Int32Ty, field.ptrOffset)); + FieldElts.push_back(ConstantInt::get(Type::Int32Ty, field.ptrOffset)); // num - FieldElts.push_back(Context.getConstantInt(Type::Int16Ty, field.num)); + FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.num)); //JInfo FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); - return ConstantStruct::get(STy, FieldElts); + return Context.getConstantStruct(STy, FieldElts); } Constant* JavaAOTCompiler::CreateConstantFromJavaMethod(JavaMethod& method) { @@ -899,7 +899,7 @@ MethodElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); // access - MethodElts.push_back(Context.getConstantInt(Type::Int16Ty, method.access)); + MethodElts.push_back(ConstantInt::get(Type::Int16Ty, method.access)); // attributs if (method.nbAttributs) { @@ -923,7 +923,7 @@ } // nbAttributs - MethodElts.push_back(Context.getConstantInt(Type::Int16Ty, method.nbAttributs)); + MethodElts.push_back(ConstantInt::get(Type::Int16Ty, method.nbAttributs)); // enveloppes // already allocated by the JIT, don't reallocate them. @@ -931,7 +931,7 @@ // nbEnveloppes // 0 because we're not allocating here. - MethodElts.push_back(Context.getConstantInt(Type::Int16Ty, 0)); + MethodElts.push_back(ConstantInt::get(Type::Int16Ty, 0)); // classDef MethodElts.push_back(getNativeClass(method.classDef)); @@ -943,7 +943,7 @@ MethodElts.push_back(getUTF8(method.type)); // canBeInlined - MethodElts.push_back(Context.getConstantInt(Type::Int8Ty, method.canBeInlined)); + MethodElts.push_back(ConstantInt::get(Type::Int8Ty, method.canBeInlined)); // code if (isAbstract(method.access)) { @@ -956,12 +956,12 @@ } // offset - MethodElts.push_back(Context.getConstantInt(Type::Int32Ty, method.offset)); + MethodElts.push_back(ConstantInt::get(Type::Int32Ty, method.offset)); //JInfo MethodElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); - return ConstantStruct::get(STy, MethodElts); + return Context.getConstantStruct(STy, MethodElts); } Constant* JavaAOTCompiler::CreateConstantFromClassPrimitive(ClassPrimitive* cl) { @@ -976,14 +976,15 @@ ClassElts.push_back(CreateConstantFromCommonClass(cl)); // primSize - ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->logSize)); + ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->logSize)); - return ConstantStruct::get(STy, ClassElts); + return Context.getConstantStruct(STy, ClassElts); } Constant* JavaAOTCompiler::CreateConstantFromClassArray(ClassArray* cl) { const StructType* STy = dyn_cast(JnjvmModule::JavaClassArrayType->getContainedType(0)); + LLVMContext& Context = getLLVMModule()->getContext(); std::vector ClassElts; Constant* ClGEPs[2] = { getIntrinsics()->constantZero, @@ -999,7 +1000,7 @@ ClassElts.push_back(Cl); - return ConstantStruct::get(STy, ClassElts); + return Context.getConstantStruct(STy, ClassElts); } Constant* JavaAOTCompiler::CreateConstantFromClass(Class* cl) { @@ -1015,7 +1016,7 @@ ClassElts.push_back(CreateConstantFromCommonClass(cl)); // virtualSize - ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->virtualSize)); + ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->virtualSize)); // IsolateInfo const ArrayType* ATy = dyn_cast(STy->getContainedType(2)); @@ -1025,10 +1026,10 @@ assert(TCMTy && "Malformed type"); uint32 status = cl->needsInitialisationCheck() ? vmjc : ready; - TempElts.push_back(Context.getConstantInt(Type::Int8Ty, status)); - TempElts.push_back(Context.getConstantInt(Type::Int1Ty, status == ready ? 1 : 0)); + TempElts.push_back(ConstantInt::get(Type::Int8Ty, status)); + TempElts.push_back(ConstantInt::get(Type::Int1Ty, status == ready ? 1 : 0)); TempElts.push_back(getStaticInstance(cl)); - Constant* CStr[1] = { ConstantStruct::get(TCMTy, TempElts) }; + Constant* CStr[1] = { Context.getConstantStruct(TCMTy, TempElts) }; TempElts.clear(); ClassElts.push_back(Context.getConstantArray(ATy, CStr, 1)); @@ -1076,7 +1077,7 @@ ClassElts.push_back(fields); ConstantInt* nbVirtualFields = - Context.getConstantInt(Type::Int16Ty, cl->nbVirtualFields); + ConstantInt::get(Type::Int16Ty, cl->nbVirtualFields); // nbVirtualFields ClassElts.push_back(nbVirtualFields); @@ -1086,7 +1087,7 @@ ClassElts.push_back(Context.getNullValue(JnjvmModule::JavaFieldType)); // nbStaticFields - ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbStaticFields)); + ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticFields)); // virtualMethods if (cl->nbVirtualMethods + cl->nbStaticMethods) { @@ -1124,7 +1125,7 @@ ClassElts.push_back(methods); ConstantInt* nbVirtualMethods = - Context.getConstantInt(Type::Int16Ty, cl->nbVirtualMethods); + ConstantInt::get(Type::Int16Ty, cl->nbVirtualMethods); // nbVirtualMethods ClassElts.push_back(nbVirtualMethods); @@ -1133,7 +1134,7 @@ ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::JavaMethodType)); // nbStaticMethods - ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbStaticMethods)); + ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticMethods)); // ownerClass ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); @@ -1166,7 +1167,7 @@ } // nbAttributs - ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbAttributs)); + ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbAttributs)); // innerClasses if (cl->nbInnerClasses) { @@ -1190,7 +1191,7 @@ } // nbInnerClasses - ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->nbInnerClasses)); + ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbInnerClasses)); // outerClass if (cl->outerClass) { @@ -1200,24 +1201,24 @@ } // innerAccess - ClassElts.push_back(Context.getConstantInt(Type::Int16Ty, cl->innerAccess)); + ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->innerAccess)); // innerOuterResolved - ClassElts.push_back(Context.getConstantInt(Type::Int8Ty, cl->innerOuterResolved)); + ClassElts.push_back(ConstantInt::get(Type::Int8Ty, cl->innerOuterResolved)); // isAnonymous - ClassElts.push_back(Context.getConstantInt(Type::Int8Ty, cl->isAnonymous)); + ClassElts.push_back(ConstantInt::get(Type::Int8Ty, cl->isAnonymous)); // virtualTableSize - ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->virtualTableSize)); + ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->virtualTableSize)); // staticSize - ClassElts.push_back(Context.getConstantInt(Type::Int32Ty, cl->staticSize)); + ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->staticSize)); // JInfo ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); - return ConstantStruct::get(STy, ClassElts); + return Context.getConstantStruct(STy, ClassElts); } template @@ -1236,12 +1237,12 @@ std::vector Cts; Cts.push_back(CreateConstantForBaseObject(val->getClass())); - Cts.push_back(Context.getConstantInt(JnjvmModule::pointerSizeType, val->size)); + Cts.push_back(ConstantInt::get(JnjvmModule::pointerSizeType, val->size)); std::vector Vals; for (sint32 i = 0; i < val->size; ++i) { if (Ty->isInteger()) { - Vals.push_back(Context.getConstantInt(Ty, (uint64)val->elements[i])); + Vals.push_back(ConstantInt::get(Ty, (uint64)val->elements[i])); } else if (Ty->isFloatingPoint()) { Vals.push_back(Context.getConstantFP(Ty, (double)(size_t)val->elements[i])); } else { @@ -1255,7 +1256,7 @@ Cts.push_back(Context.getConstantArray(ATy, Vals)); - return ConstantStruct::get(STy, Cts); + return Context.getConstantStruct(STy, Cts); } Constant* JavaAOTCompiler::CreateConstantFromUTF8(const UTF8* val) { @@ -1270,16 +1271,16 @@ const StructType* STy = StructType::get(Elemts); std::vector Cts; - Cts.push_back(Context.getConstantInt(JnjvmModule::pointerSizeType, val->size)); + Cts.push_back(ConstantInt::get(JnjvmModule::pointerSizeType, val->size)); std::vector Vals; for (sint32 i = 0; i < val->size; ++i) { - Vals.push_back(Context.getConstantInt(Type::Int16Ty, val->elements[i])); + Vals.push_back(ConstantInt::get(Type::Int16Ty, val->elements[i])); } Cts.push_back(Context.getConstantArray(ATy, Vals)); - return ConstantStruct::get(STy, Cts); + return Context.getConstantStruct(STy, Cts); } @@ -1355,11 +1356,11 @@ // depth Elemts.push_back(ConstantExpr::getIntToPtr( - Context.getConstantInt(Type::Int64Ty, VT->depth), PTy)); + ConstantInt::get(Type::Int64Ty, VT->depth), PTy)); // offset Elemts.push_back(ConstantExpr::getIntToPtr( - Context.getConstantInt(Type::Int64Ty, VT->offset), PTy)); + ConstantInt::get(Type::Int64Ty, VT->offset), PTy)); // cache Elemts.push_back(N); @@ -1377,7 +1378,7 @@ // nbSecondaryTypes Elemts.push_back(ConstantExpr::getIntToPtr( - Context.getConstantInt(Type::Int64Ty, VT->nbSecondaryTypes), PTy)); + ConstantInt::get(Type::Int64Ty, VT->nbSecondaryTypes), PTy)); // secondaryTypes const ArrayType* DTy = ArrayType::get(JnjvmModule::VTType, @@ -1507,7 +1508,7 @@ Constant* cons = - ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, + ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t(isolate)), ptrType); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Mon Jul 27 12:54:50 2009 @@ -158,7 +158,7 @@ Constant* Offset = LMI->getOffset(); indexes2[1] = Offset; #ifdef ISOLATE_SHARING - indexesCtp = llvmContext->getConstantInt(Type::Int32Ty, + indexesCtp = ConstantInt::get(Type::Int32Ty, Offset->getZExtValue() * -1); #endif } else { @@ -280,7 +280,7 @@ BasicBlock* executeBlock = createBasicBlock("execute"); endBlock = createBasicBlock("end block"); - Constant* sizeB = llvmContext->getConstantInt(Type::Int32Ty, sizeof(jmp_buf)); + Constant* sizeB = ConstantInt::get(Type::Int32Ty, sizeof(jmp_buf)); Value* oldJB = new AllocaInst(module->ptrType, "", currentBlock); Value* newJB = new AllocaInst(Type::Int8Ty, sizeB, "", currentBlock); @@ -512,8 +512,8 @@ // It's a thin lock. Look if we're the owner of this lock. currentBlock = ThinLockBB; - Value* idMask = llvmContext->getConstantInt(module->pointerSizeType, 0x7FFFFF00); - Value* cptMask = llvmContext->getConstantInt(module->pointerSizeType, 0xFF); + Value* idMask = ConstantInt::get(module->pointerSizeType, 0x7FFFFF00); + Value* cptMask = ConstantInt::get(module->pointerSizeType, 0xFF); Value* IdInLock = BinaryOperator::CreateAnd(atomic, idMask, "", currentBlock); Value* owner = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, threadId, IdInLock, ""); @@ -995,7 +995,7 @@ currentBlock); OldIsolateID = new LoadInst(IsolateIDPtr, "", currentBlock); - Value* MyID = llvmContext->getConstantInt(module->pointerSizeType, + Value* MyID = ConstantInt::get(module->pointerSizeType, loader->getIsolate()->IsolateID); Cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, OldIsolateID, MyID, ""); @@ -1212,13 +1212,13 @@ } #endif } else if (type == JavaConstantPool::ConstantLong) { - push(llvmContext->getConstantInt(Type::Int64Ty, ctpInfo->LongAt(index)), + push(ConstantInt::get(Type::Int64Ty, ctpInfo->LongAt(index)), false); } else if (type == JavaConstantPool::ConstantDouble) { push(llvmContext->getConstantFP(Type::DoubleTy, ctpInfo->DoubleAt(index)), false); } else if (type == JavaConstantPool::ConstantInteger) { - push(llvmContext->getConstantInt(Type::Int32Ty, ctpInfo->IntegerAt(index)), + push(ConstantInt::get(Type::Int32Ty, ctpInfo->IntegerAt(index)), false); } else if (type == JavaConstantPool::ConstantFloat) { push(llvmContext->getConstantFP(Type::FloatTy, ctpInfo->FloatAt(index)), @@ -1548,7 +1548,7 @@ BranchInst::Create(falseCl, trueCl, test, currentBlock); std::vector Args; Args.push_back(ctpCache); - Args.push_back(llvmContext->getConstantInt(Type::Int32Ty, index)); + Args.push_back(ConstantInt::get(Type::Int32Ty, index)); Args.push_back(GV); res = CallInst::Create(module->SpecialCtpLookupFunction, Args.begin(), Args.end(), "", falseCl); @@ -1676,7 +1676,7 @@ Args.push_back(resolver); Args.push_back(CTP); Args.push_back(Cl); - Args.push_back(llvmContext->getConstantInt(Type::Int32Ty, index)); + Args.push_back(ConstantInt::get(Type::Int32Ty, index)); if (additionalArg) Args.push_back(additionalArg); Value* res = 0; @@ -1918,22 +1918,22 @@ const PrimitiveTypedef* prim = (PrimitiveTypedef*)sign; if (prim->isInt()) { sint32 val = field->getInt32Field(Obj); - push(llvmContext->getConstantInt(Type::Int32Ty, val), false); + push(ConstantInt::get(Type::Int32Ty, val), false); } else if (prim->isByte()) { sint8 val = (sint8)field->getInt8Field(Obj); - push(llvmContext->getConstantInt(Type::Int8Ty, val), false); + push(ConstantInt::get(Type::Int8Ty, val), false); } else if (prim->isBool()) { uint8 val = (uint8)field->getInt8Field(Obj); - push(llvmContext->getConstantInt(Type::Int8Ty, val), true); + push(ConstantInt::get(Type::Int8Ty, val), true); } else if (prim->isShort()) { sint16 val = (sint16)field->getInt16Field(Obj); - push(llvmContext->getConstantInt(Type::Int16Ty, val), false); + push(ConstantInt::get(Type::Int16Ty, val), false); } else if (prim->isChar()) { uint16 val = (uint16)field->getInt16Field(Obj); - push(llvmContext->getConstantInt(Type::Int16Ty, val), true); + push(ConstantInt::get(Type::Int16Ty, val), true); } else if (prim->isLong()) { sint64 val = (sint64)field->getLongField(Obj); - push(llvmContext->getConstantInt(Type::Int64Ty, val), false); + push(ConstantInt::get(Type::Int64Ty, val), false); } else if (prim->isFloat()) { float val = (float)field->getFloatField(Obj); push(llvmContext->getConstantFP(Type::FloatTy, val), false); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Mon Jul 27 12:54:50 2009 @@ -29,55 +29,48 @@ using namespace llvm; Constant* JavaJITCompiler::getNativeClass(CommonClass* classDef) { - LLVMContext& Context = getLLVMModule()->getContext(); const llvm::Type* Ty = classDef->isClass() ? JnjvmModule::JavaClassType : JnjvmModule::JavaCommonClassType; - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(classDef)); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(classDef)); return ConstantExpr::getIntToPtr(CI, Ty); } Constant* JavaJITCompiler::getConstantPool(JavaConstantPool* ctp) { void* ptr = ctp->ctpRes; assert(ptr && "No constant pool found"); - LLVMContext& Context = getLLVMModule()->getContext(); - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(ptr)); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(ptr)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::ConstantPoolType); } Constant* JavaJITCompiler::getMethodInClass(JavaMethod* meth) { - LLVMContext& Context = getLLVMModule()->getContext(); - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, (int64_t)meth); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, (int64_t)meth); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaMethodType); } Constant* JavaJITCompiler::getString(JavaString* str) { assert(str && "No string given"); - LLVMContext& Context = getLLVMModule()->getContext(); - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64(str)); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64(str)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } Constant* JavaJITCompiler::getStringPtr(JavaString** str) { assert(str && "No string given"); - LLVMContext& Context = getLLVMModule()->getContext(); const llvm::Type* Ty = PointerType::getUnqual(JnjvmModule::JavaObjectType); - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64(str)); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64(str)); return ConstantExpr::getIntToPtr(CI, Ty); } Constant* JavaJITCompiler::getEnveloppe(Enveloppe* enveloppe) { assert(enveloppe && "No enveloppe given"); - LLVMContext& Context = getLLVMModule()->getContext(); - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64(enveloppe)); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64(enveloppe)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::EnveloppeType); } Constant* JavaJITCompiler::getJavaClass(CommonClass* cl) { JavaObject* obj = cl->getClassDelegatee(JavaThread::get()->getJVM()); assert(obj && "Delegatee not created"); - LLVMContext& Context = getLLVMModule()->getContext(); - Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64(obj)); + Constant* CI = ConstantInt::get(Type::Int64Ty, uint64(obj)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } @@ -85,8 +78,7 @@ Jnjvm* vm = JavaThread::get()->getJVM(); JavaObject* const* obj = cl->getClassDelegateePtr(vm); assert(obj && "Delegatee not created"); - LLVMContext& Context = getLLVMModule()->getContext(); - Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64(obj)); + Constant* CI = ConstantInt::get(Type::Int64Ty, uint64(obj)); const Type* Ty = PointerType::getUnqual(JnjvmModule::JavaObjectType); return ConstantExpr::getIntToPtr(CI, Ty); } @@ -101,13 +93,11 @@ } Constant* JavaJITCompiler::getFinalObject(JavaObject* obj) { - LLVMContext& Context = getLLVMModule()->getContext(); - Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64(obj)); + Constant* CI = ConstantInt::get(Type::Int64Ty, uint64(obj)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::JavaObjectType); } Constant* JavaJITCompiler::getStaticInstance(Class* classDef) { - LLVMContext& Context = getLLVMModule()->getContext(); #ifdef ISOLATE assert(0 && "Should not be here"); abort(); @@ -122,29 +112,27 @@ } classDef->release(); } - Constant* CI = Context.getConstantInt(Type::Int64Ty, (uint64_t(obj))); + Constant* CI = ConstantInt::get(Type::Int64Ty, (uint64_t(obj))); return ConstantExpr::getIntToPtr(CI, JnjvmModule::ptrType); } Constant* JavaJITCompiler::getVirtualTable(JavaVirtualTable* VT) { - LLVMContext& Context = getLLVMModule()->getContext(); if (VT->cl->isClass()) { LLVMClassInfo* LCI = getClassInfo(VT->cl->asClass()); LCI->getVirtualType(); } - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(VT)); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(VT)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::VTType); } Constant* JavaJITCompiler::getNativeFunction(JavaMethod* meth, void* ptr) { - LLVMContext& Context = getLLVMModule()->getContext(); LLVMSignatureInfo* LSI = getSignatureInfo(meth->getSignature()); const llvm::Type* valPtrType = LSI->getNativePtrType(); assert(ptr && "No native function given"); - Constant* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(ptr)); + Constant* CI = ConstantInt::get(Type::Int64Ty, uint64_t(ptr)); return ConstantExpr::getIntToPtr(CI, valPtrType); } @@ -162,8 +150,7 @@ #ifdef SERVICE Value* JavaJITCompiler::getIsolate(Jnjvm* isolate, Value* Where) { - LLVMContext& Context = getLLVMModule()->getContext(); - ConstantInt* CI = Context.getConstantInt(Type::Int64Ty, uint64_t(isolate)); + ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(isolate)); return ConstantExpr::getIntToPtr(CI, JnjvmModule::ptrType); } #endif Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Mon Jul 27 12:54:50 2009 @@ -182,8 +182,8 @@ #if JNJVM_EXECUTE > 1 { Value* args[3] = { - llvmContext->getConstantInt(Type::Int32Ty, (int64_t)bytecodes[i]), - llvmContext->getConstantInt(Type::Int32Ty, (int64_t)i), + ConstantInt::get(Type::Int32Ty, (int64_t)bytecodes[i]), + ConstantInt::get(Type::Int32Ty, (int64_t)i), TheCompiler->getMethodInClass(compilingMethod) }; @@ -262,13 +262,13 @@ break; case BIPUSH : - push(ConstantExpr::getSExt(llvmContext->getConstantInt(Type::Int8Ty, + push(ConstantExpr::getSExt(ConstantInt::get(Type::Int8Ty, bytecodes[++i]), Type::Int32Ty), false); break; case SIPUSH : - push(ConstantExpr::getSExt(llvmContext->getConstantInt(Type::Int16Ty, + push(ConstantExpr::getSExt(ConstantInt::get(Type::Int16Ty, readS2(bytecodes, i)), Type::Int32Ty), false); break; @@ -1126,7 +1126,7 @@ case IUSHR : { Value* val2 = popAsInt(); Value* val1 = popAsInt(); - Value* mask = llvmContext->getConstantInt(Type::Int32Ty, 0x1F); + Value* mask = ConstantInt::get(Type::Int32Ty, 0x1F); val2 = BinaryOperator::CreateAnd(val2, mask, "", currentBlock); push(BinaryOperator::CreateLShr(val1, val2, "", currentBlock), false); @@ -1135,7 +1135,7 @@ case LUSHR : { Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock); - Value* mask = llvmContext->getConstantInt(Type::Int64Ty, 0x3F); + Value* mask = ConstantInt::get(Type::Int64Ty, 0x3F); val2 = BinaryOperator::CreateAnd(val2, mask, "", currentBlock); pop(); // remove the 0 on the stack Value* val1 = pop(); @@ -1207,7 +1207,7 @@ sint16 val = WREAD_S1(bytecodes, false, i, wide); llvm::Value* add = BinaryOperator::CreateAdd( new LoadInst(intLocals[idx], "", currentBlock), - llvmContext->getConstantInt(Type::Int32Ty, val), "", + ConstantInt::get(Type::Int32Ty, val), "", currentBlock); new StoreInst(add, intLocals[idx], false, currentBlock); break; @@ -1743,7 +1743,7 @@ case JSR : { uint32 tmp = i; Value* expr = ConstantExpr::getIntToPtr( - llvmContext->getConstantInt(Type::Int64Ty, + ConstantInt::get(Type::Int64Ty, uint64_t (jsrIndex++)), module->JavaObjectType); push(expr, false); @@ -1762,7 +1762,7 @@ uint32 index = 0; for (std::vector::iterator i = jsrs.begin(), e = jsrs.end(); i!= e; ++i, ++index) { - inst->addCase(llvmContext->getConstantInt(Type::Int32Ty, index), *i); + inst->addCase(ConstantInt::get(Type::Int32Ty, index), *i); } break; @@ -1783,7 +1783,7 @@ const llvm::Type* type = index->getType(); for (sint32 cur = low; cur < high; ++cur) { Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, - llvmContext->getConstantInt(type, cur), index, ""); + ConstantInt::get(type, cur), index, ""); BasicBlock* falseBlock = createBasicBlock("continue tableswitch"); branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock); @@ -1813,7 +1813,7 @@ key = new SExtInst(key, Type::Int32Ty, "", currentBlock); } for (uint32 cur = 0; cur < nbs; ++cur) { - Value* val = llvmContext->getConstantInt(Type::Int32Ty, readU4(bytecodes, i)); + Value* val = ConstantInt::get(Type::Int32Ty, readU4(bytecodes, i)); Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, val, key, ""); BasicBlock* falseBlock = createBasicBlock("continue lookupswitch"); @@ -1932,13 +1932,13 @@ valCl = TheCompiler->getNativeClass(dcl); #else Value* args[2] = { isolateLocal, - llvmContext->getConstantInt(Type::Int32Ty, id - 4) }; + ConstantInt::get(Type::Int32Ty, id - 4) }; valCl = CallInst::Create(module->GetJnjvmArrayClassFunction, args, args + 2, "", currentBlock); #endif LLVMAssessorInfo& LAI = LLVMAssessorInfo::AssessorInfo[charId]; - sizeElement = llvmContext->getConstantInt(Type::Int32Ty, + sizeElement = ConstantInt::get(Type::Int32Ty, LAI.logSizeInBytesConstant); if (TheCompiler->isStaticCompiling() && valCl->getType() != module->JavaClassArrayType) { @@ -2112,7 +2112,7 @@ objVT, "", currentBlock); uint32 depth = cl->virtualVT->depth; - ConstantInt* CI = llvmContext->getConstantInt(Type::Int32Ty, depth); + ConstantInt* CI = ConstantInt::get(Type::Int32Ty, depth); Value* displayArgs[2] = { inDisplay, CI }; Value* VTInDisplay = CallInst::Create(module->GetVTInDisplayFunction, @@ -2167,7 +2167,7 @@ Value* valCl = getResolvedCommonClass(index, true, 0); Value** args = (Value**)alloca(sizeof(Value*) * (dim + 2)); args[0] = valCl; - args[1] = llvmContext->getConstantInt(Type::Int32Ty, dim); + args[1] = ConstantInt::get(Type::Int32Ty, dim); for (int cur = dim + 1; cur >= 2; --cur) args[cur] = pop(); Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Mon Jul 27 12:54:50 2009 @@ -165,7 +165,6 @@ JnjvmModule::JnjvmModule(llvm::Module* module) : MvmModule(module) { - LLVMContext& Context = module->getContext(); if (!VTType) { initialise(); @@ -174,10 +173,10 @@ JavaObjectNullConstant = module->getContext().getNullValue(JnjvmModule::JavaObjectType); - MaxArraySizeConstant = Context.getConstantInt(Type::Int32Ty, + MaxArraySizeConstant = ConstantInt::get(Type::Int32Ty, JavaArray::MaxArraySize); JavaArraySizeConstant = - Context.getConstantInt(Type::Int32Ty, sizeof(JavaObject) + sizeof(ssize_t)); + ConstantInt::get(Type::Int32Ty, sizeof(JavaObject) + sizeof(ssize_t)); JavaArrayElementsOffsetConstant = constantTwo; @@ -187,22 +186,22 @@ OffsetClassInVTConstant = constantThree; OffsetDepthInVTConstant = constantFour; OffsetDisplayInVTConstant = constantSeven; - OffsetBaseClassVTInVTConstant = Context.getConstantInt(Type::Int32Ty, 17); + OffsetBaseClassVTInVTConstant = ConstantInt::get(Type::Int32Ty, 17); OffsetObjectSizeInClassConstant = constantOne; - OffsetVTInClassConstant = Context.getConstantInt(Type::Int32Ty, 7); + OffsetVTInClassConstant = ConstantInt::get(Type::Int32Ty, 7); OffsetTaskClassMirrorInClassConstant = constantTwo; OffsetStaticInstanceInTaskClassMirrorConstant = constantTwo; OffsetStatusInTaskClassMirrorConstant = constantZero; OffsetInitializedInTaskClassMirrorConstant = constantOne; - OffsetIsolateInThreadConstant = Context.getConstantInt(Type::Int32Ty, 3); - OffsetDoYieldInThreadConstant = Context.getConstantInt(Type::Int32Ty, 6); - OffsetJNIInThreadConstant = Context.getConstantInt(Type::Int32Ty, 9); - OffsetJavaExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 10); - OffsetCXXExceptionInThreadConstant = Context.getConstantInt(Type::Int32Ty, 11); + OffsetIsolateInThreadConstant = ConstantInt::get(Type::Int32Ty, 3); + OffsetDoYieldInThreadConstant = ConstantInt::get(Type::Int32Ty, 6); + OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 9); + OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 10); + OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 11); - ClassReadyConstant = Context.getConstantInt(Type::Int8Ty, ready); + ClassReadyConstant = ConstantInt::get(Type::Int8Ty, ready); module->addTypeName("JavaObject", JavaObjectType->getContainedType(0)); module->addTypeName("JavaArray", JavaArrayType->getContainedType(0)); Modified: vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/LowerConstantCalls.cpp Mon Jul 27 12:54:50 2009 @@ -411,7 +411,7 @@ ConstantInt* Cons = dyn_cast(Index); assert(CI && "Wrong use of GetConstantPoolAt"); uint64 val = Cons->getZExtValue(); - Value* indexes = Context->getConstantInt(Type::Int32Ty, val + 1); + Value* indexes = ConstantInt::get(Type::Int32Ty, val + 1); #else Value* indexes = Index; #endif @@ -537,7 +537,7 @@ BasicBlock* FailedBlock = BasicBlock::Create("", &F); PHINode* node = PHINode::Create(Type::Int1Ty, "", CurEndBlock); - ConstantInt* CC = Context->getConstantInt(Type::Int32Ty, + ConstantInt* CC = ConstantInt::get(Type::Int32Ty, JavaVirtualTable::getOffsetIndex()); Value* indices[2] = { module->constantZero, CC }; Value* Offset = GetElementPtrInst::Create(VT2, indices, indices + 2, @@ -595,7 +595,7 @@ // if (VT1.cache == VT2 || VT1 == VT2) goto end with true; // else goto headerLoop; ConstantInt* cacheIndex = - Context->getConstantInt(Type::Int32Ty, JavaVirtualTable::getCacheIndex()); + ConstantInt::get(Type::Int32Ty, JavaVirtualTable::getCacheIndex()); Value* indices[2] = { module->constantZero, cacheIndex }; Instruction* CachePtr = GetElementPtrInst::Create(VT1, indices, indices + 2, "", CI); @@ -613,7 +613,7 @@ // size = VT1->nbSecondaryTypes; // i = 0; // goto test; - ConstantInt* sizeIndex = Context->getConstantInt(Type::Int32Ty, + ConstantInt* sizeIndex = ConstantInt::get(Type::Int32Ty, JavaVirtualTable::getNumSecondaryTypesIndex()); indices[1] = sizeIndex; Instruction* Size = GetElementPtrInst::Create(VT1, indices, @@ -622,7 +622,7 @@ Size = new LoadInst(Size, "", false, Preheader); Size = new PtrToIntInst(Size, Type::Int32Ty, "", Preheader); - ConstantInt* secondaryTypesIndex = Context->getConstantInt(Type::Int32Ty, + ConstantInt* secondaryTypesIndex = ConstantInt::get(Type::Int32Ty, JavaVirtualTable::getSecondaryTypesIndex()); indices[1] = secondaryTypesIndex; Instruction* secondaryTypes = Modified: vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/EscapeAnalysis.cpp Mon Jul 27 12:54:50 2009 @@ -213,7 +213,7 @@ // we don't end up with tons of allocations on the stack. BasicBlock* BB = CurLoop->getLoopPreheader(); assert(BB && "No Preheader!"); - DOUT << "Escape analysis hoisting to " << BB->getName() << ": "; + DOUT << "Escape analysis hoisting to " << BB->getNameStr() << ": "; DOUT << *Alloc; Alloc->removeFromParent(); BB->getInstList().insert(BB->getTerminator(), Alloc); @@ -221,7 +221,7 @@ AllocaInst* AI = new AllocaInst(Type::Int8Ty, Size, "", Alloc); BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc); - DOUT << "escape" << Alloc->getParent()->getParent()->getName() << "\n"; + DOUT << "escape" << Alloc->getParent()->getParent()->getNameStr() << "\n"; Alloc->replaceAllUsesWith(BI); // If it's an invoke, replace the invoke with a direct branch. if (InvokeInst *CI = dyn_cast(Alloc)) { Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Mon Jul 27 12:54:50 2009 @@ -98,24 +98,24 @@ // Constant declaration - constantLongMinusOne = globalContext->getConstantInt(Type::Int64Ty, (uint64_t)-1); - constantLongZero = globalContext->getConstantInt(Type::Int64Ty, 0); - constantLongOne = globalContext->getConstantInt(Type::Int64Ty, 1); - constantZero = globalContext->getConstantInt(Type::Int32Ty, 0); - constantInt8Zero = globalContext->getConstantInt(Type::Int8Ty, 0); - constantOne = globalContext->getConstantInt(Type::Int32Ty, 1); - constantTwo = globalContext->getConstantInt(Type::Int32Ty, 2); - constantThree = globalContext->getConstantInt(Type::Int32Ty, 3); - constantFour = globalContext->getConstantInt(Type::Int32Ty, 4); - constantFive = globalContext->getConstantInt(Type::Int32Ty, 5); - constantSix = globalContext->getConstantInt(Type::Int32Ty, 6); - constantSeven = globalContext->getConstantInt(Type::Int32Ty, 7); - constantEight = globalContext->getConstantInt(Type::Int32Ty, 8); - constantMinusOne = globalContext->getConstantInt(Type::Int32Ty, (uint64_t)-1); - constantMinInt = globalContext->getConstantInt(Type::Int32Ty, MinInt); - constantMaxInt = globalContext->getConstantInt(Type::Int32Ty, MaxInt); - constantMinLong = globalContext->getConstantInt(Type::Int64Ty, MinLong); - constantMaxLong = globalContext->getConstantInt(Type::Int64Ty, MaxLong); + constantLongMinusOne = ConstantInt::get(Type::Int64Ty, (uint64_t)-1); + constantLongZero = ConstantInt::get(Type::Int64Ty, 0); + constantLongOne = ConstantInt::get(Type::Int64Ty, 1); + constantZero = ConstantInt::get(Type::Int32Ty, 0); + constantInt8Zero = ConstantInt::get(Type::Int8Ty, 0); + constantOne = ConstantInt::get(Type::Int32Ty, 1); + constantTwo = ConstantInt::get(Type::Int32Ty, 2); + constantThree = ConstantInt::get(Type::Int32Ty, 3); + constantFour = ConstantInt::get(Type::Int32Ty, 4); + constantFive = ConstantInt::get(Type::Int32Ty, 5); + constantSix = ConstantInt::get(Type::Int32Ty, 6); + constantSeven = ConstantInt::get(Type::Int32Ty, 7); + constantEight = ConstantInt::get(Type::Int32Ty, 8); + constantMinusOne = ConstantInt::get(Type::Int32Ty, (uint64_t)-1); + constantMinInt = ConstantInt::get(Type::Int32Ty, MinInt); + constantMaxInt = ConstantInt::get(Type::Int32Ty, MaxInt); + constantMinLong = ConstantInt::get(Type::Int64Ty, MinLong); + constantMaxLong = ConstantInt::get(Type::Int64Ty, MaxLong); constantFloatZero = globalContext->getConstantFP(Type::FloatTy, 0.0f); constantFloatOne = globalContext->getConstantFP(Type::FloatTy, 1.0f); constantFloatTwo = globalContext->getConstantFP(Type::FloatTy, 2.0f); @@ -136,17 +136,17 @@ constantDoubleMinusInfinity = globalContext->getConstantFP(Type::DoubleTy, MinDouble); constantDoubleMinusZero = globalContext->getConstantFP(Type::DoubleTy, -0.0); constantFloatMinusZero = globalContext->getConstantFP(Type::FloatTy, -0.0f); - constantThreadIDMask = globalContext->getConstantInt(pointerSizeType, mvm::Thread::IDMask); + constantThreadIDMask = ConstantInt::get(pointerSizeType, mvm::Thread::IDMask); constantStackOverflowMask = - globalContext->getConstantInt(pointerSizeType, mvm::Thread::StackOverflowMask); - constantFatMask = globalContext->getConstantInt(pointerSizeType, + ConstantInt::get(pointerSizeType, mvm::Thread::StackOverflowMask); + constantFatMask = ConstantInt::get(pointerSizeType, pointerSizeType == Type::Int32Ty ? 0x80000000 : 0x8000000000000000LL); - constantPtrOne = globalContext->getConstantInt(pointerSizeType, 1); - constantPtrZero = globalContext->getConstantInt(pointerSizeType, 0); + constantPtrOne = ConstantInt::get(pointerSizeType, 1); + constantPtrZero = ConstantInt::get(pointerSizeType, 0); constantPtrNull = globalContext->getNullValue(ptrType); constantPtrLogSize = - globalContext->getConstantInt(Type::Int32Ty, sizeof(void*) == 8 ? 3 : 2); + ConstantInt::get(Type::Int32Ty, sizeof(void*) == 8 ? 3 : 2); arrayPtrType = PointerType::getUnqual(ArrayType::get(Type::Int8Ty, 0)); Modified: vmkit/trunk/lib/N3/Mono/MonoString.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/Mono/MonoString.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/N3/Mono/MonoString.cpp (original) +++ vmkit/trunk/lib/N3/Mono/MonoString.cpp Mon Jul 27 12:54:50 2009 @@ -52,9 +52,8 @@ if (!str->_llvmVar) { const Type* pty = mvm::MvmModule::ptrType; Module* Mod = vm->getLLVMModule(); - LLVMContext& Context = Mod->getContext(); Constant* cons = - ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); str->_llvmVar = new GlobalVariable(*Mod, pty, true, GlobalValue::ExternalLinkage, Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Mon Jul 27 12:54:50 2009 @@ -103,7 +103,6 @@ Value* GC = ++(block->getParent()->arg_begin()); #endif - Function* llvmFunction = block->getParent(); Constant* zero = cl->vm->module->constantZero; for (std::vector::iterator i = fields.begin(), e = fields.end(); i!= e; ++i) { @@ -113,7 +112,7 @@ args.push_back(zero); if (boxed) { ConstantInt* CI = dyn_cast(field->offset); - args.push_back(llvmFunction->getContext().getConstantInt(CI->getValue() + 1)); + args.push_back(ConstantInt::get(Type::Int32Ty, CI->getValue() + 1)); } else { args.push_back(field->offset); } @@ -125,7 +124,7 @@ args.push_back(zero); if (boxed) { ConstantInt* CI = dyn_cast(field->offset); - args.push_back(llvmFunction->getContext().getConstantInt(CI->getValue() + 1)); + args.push_back(ConstantInt::get(Type::Int32Ty, CI->getValue() + 1)); } else { args.push_back(field->offset); } @@ -631,7 +630,7 @@ std::vector params; params.push_back(new BitCastInst(obj, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); @@ -738,7 +737,7 @@ std::vector params; params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -950,7 +949,7 @@ void* natPtr = NativeUtil::nativeLookup(compilingClass, compilingMethod); Value* valPtr = - ConstantExpr::getIntToPtr(llvmFunction->getContext().getConstantInt(Type::Int64Ty, (uint64)natPtr), + ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (uint64)natPtr), PointerType::getUnqual(funcType)); Value* result = CallInst::Create(valPtr, nativeArgs.begin(), @@ -1234,7 +1233,7 @@ params.push_back(new BitCastInst(alloc, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); @@ -1282,7 +1281,7 @@ currentBlock)); params.push_back(new BitCastInst(endNode, module->ptrType, "", currentBlock)); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantFour); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1411,7 +1410,7 @@ params.push_back(new BitCastInst(alloc, module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); Modified: vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/CLIJitMeta.cpp Mon Jul 27 12:54:50 2009 @@ -365,10 +365,9 @@ aquire(); if (!_llvmVar) { Module* Mod = vm->getLLVMModule(); - LLVMContext& Context = Mod->getContext(); const Type* pty = mvm::MvmModule::ptrType; Constant* cons = - ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); _llvmVar = new GlobalVariable(*Mod, pty, true, @@ -387,9 +386,8 @@ if (!_llvmVar) { const Type* pty = mvm::MvmModule::ptrType; Module* Mod = classDef->vm->getLLVMModule(); - LLVMContext& Context = Mod->getContext(); Constant* cons = - ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); _llvmVar = new GlobalVariable(*Mod, pty, true, @@ -406,10 +404,9 @@ classDef->aquire(); if (!_llvmVar) { Module* Mod = classDef->vm->getLLVMModule(); - LLVMContext& Context = Mod->getContext(); const Type* pty = mvm::MvmModule::ptrType; Constant* cons = - ConstantExpr::getIntToPtr(Context.getConstantInt(Type::Int64Ty, uint64_t (this)), + ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)), pty); _llvmVar = new GlobalVariable(*Mod, pty, true, Modified: vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/LowerArrayLength.cpp Mon Jul 27 12:54:50 2009 @@ -46,7 +46,7 @@ Changed = true; Value* val = CI->getOperand(1); // get the array std::vector args; //size= 2 - args.push_back(F.getContext().getConstantInt(Type::Int32Ty, 0)); + args.push_back(ConstantInt::get(Type::Int32Ty, 0)); args.push_back(n3::VMArray::sizeOffset()); Value* ptr = GetElementPtrInst::Create(val, args.begin(), args.end(), "", CI); Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Mon Jul 27 12:54:50 2009 @@ -164,7 +164,6 @@ static void store(Value* val, Value* local, bool vol, BasicBlock* currentBlock, mvm::MvmModule* module) { const Type* contained = local->getType()->getContainedType(0); - Function* llvmFunction = currentBlock->getParent(); if (contained->isSingleValueType()) { if (val->getType() != contained) { convertValue(val, contained, currentBlock); @@ -176,7 +175,7 @@ std::vector params; params.push_back(new BitCastInst(local, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); } else { @@ -186,7 +185,6 @@ static Value* load(Value* val, const char* name, BasicBlock* currentBlock, mvm::MvmModule* module) { const Type* contained = val->getType()->getContainedType(0); - Function* llvmFunction = currentBlock->getParent(); if (contained->isSingleValueType()) { return new LoadInst(val, name, currentBlock); } else { @@ -195,7 +193,7 @@ std::vector params; params.push_back(new BitCastInst(ret, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); return ret; @@ -230,13 +228,13 @@ #if N3_EXECUTE > 1 if (bytecodes[i] == 0xFE) { std::vector args; - args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)OpcodeNamesFE[bytecodes[i + 1]])); - args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); + args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNamesFE[bytecodes[i + 1]])); + args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod)); CallInst::Create(printExecutionLLVM, args.begin(), args.end(), "", currentBlock); } else { std::vector args; - args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]])); - args.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, (int64_t)compilingMethod)); + args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]])); + args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod)); CallInst::Create(printExecutionLLVM, args.begin(), args.end(), "", currentBlock); } #endif @@ -705,7 +703,7 @@ uint32 index = 0; for (std::vector::iterator i = leaves.begin(), e = leaves.end(); i!= e; ++i, ++index) { - inst->addCase(llvmFunction->getContext().getConstantInt(Type::Int32Ty, index), *i); + inst->addCase(ConstantInt::get(Type::Int32Ty, index), *i); } //currentBlock = bb2; @@ -749,12 +747,12 @@ } case LDC_I4 : { - push(llvmFunction->getContext().getConstantInt(Type::Int32Ty, readS4(bytecodes, i))); + push(ConstantInt::get(Type::Int32Ty, readS4(bytecodes, i))); break; } case LDC_I8 : { - push(llvmFunction->getContext().getConstantInt(Type::Int64Ty, readS8(bytecodes, i))); + push(ConstantInt::get(Type::Int64Ty, readS8(bytecodes, i))); break; } @@ -819,7 +817,7 @@ } case LDC_I4_S : { - push(llvmFunction->getContext().getConstantInt(Type::Int32Ty, readS1(bytecodes, i))); + push(ConstantInt::get(Type::Int32Ty, readS1(bytecodes, i))); break; } @@ -954,7 +952,7 @@ } if (res) { Value* expr = ConstantExpr::getIntToPtr( - llvmFunction->getContext().getConstantInt(Type::Int64Ty, + ConstantInt::get(Type::Int64Ty, uint64_t (leaveIndex++)), VMObject::llvmType); @@ -986,7 +984,7 @@ } if (res) { Value* expr = ConstantExpr::getIntToPtr( - llvmFunction->getContext().getConstantInt(Type::Int64Ty, + ConstantInt::get(Type::Int64Ty, uint64_t (leaveIndex++)), VMObject::llvmType); @@ -1262,7 +1260,7 @@ sint32 index = next + offset; assert(index > 0); BasicBlock* BB = opcodeInfos[index].newBlock; - SI->addCase(llvmFunction->getContext().getConstantInt(Type::Int32Ty, t), BB); + SI->addCase(ConstantInt::get(Type::Int32Ty, t), BB); } break; } @@ -1313,7 +1311,7 @@ std::vector params; params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1580,7 +1578,7 @@ uint32 value = readU4(bytecodes, i); uint32 index = value & 0xfffffff; const UTF8* utf8 = compilingClass->assembly->readUserString(index); - Value* val = ConstantExpr::getIntToPtr(llvmFunction->getContext().getConstantInt(Type::Int64Ty, (int64_t)utf8), + Value* val = ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (int64_t)utf8), module->ptrType); Value* res = CallInst::Create(newStringLLVM, val, "", currentBlock); /*CLIString * str = @@ -1812,7 +1810,7 @@ std::vector params; params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock)); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock); @@ -1963,7 +1961,7 @@ params.push_back(new BitCastInst(pop(), module->ptrType, "", currentBlock)); params.push_back(module->constantInt8Zero); - params.push_back(llvmFunction->getContext().getConstantInt(Type::Int32Ty, size)); + params.push_back(ConstantInt::get(Type::Int32Ty, size)); params.push_back(module->constantZero); CallInst::Create(module->llvm_memset_i32, params.begin(), params.end(), "", currentBlock); Modified: vmkit/trunk/lib/N3/VMCore/VMCache.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMCache.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMCache.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMCache.cpp Mon Jul 27 12:54:50 2009 @@ -92,7 +92,7 @@ Value* five = module->constantFive; Value* llvmEnv = - ConstantExpr::getIntToPtr(llvmFunction->getContext().getConstantInt(Type::Int64Ty, uint64_t (enveloppe)), + ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (enveloppe)), Enveloppe::llvmType); std::vector args1; Modified: vmkit/trunk/lib/N3/VMCore/VMClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMClass.cpp?rev=77212&r1=77211&r2=77212&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMClass.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMClass.cpp Mon Jul 27 12:54:50 2009 @@ -279,7 +279,7 @@ for (std::vector::iterator i = cl->staticFields.begin(), e = cl->staticFields.end(); i!= e; ++i) { // preincrement because 0 is VMObject - (*i)->offset = vm->getLLVMModule()->getContext().getConstantInt(llvm::Type::Int32Ty, ++offset); + (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset); } for (std::vector::iterator i = cl->staticFields.begin(), e = cl->staticFields.end(); i!= e; ++i) { @@ -329,7 +329,7 @@ uint32 offset = -1; for (std::vector::iterator i = virtualFields.begin(), e = virtualFields.end(); i!= e; ++i) { - (*i)->offset = vm->getLLVMModule()->getContext().getConstantInt(llvm::Type::Int32Ty, ++offset); + (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset); const llvm::Type* type = (*i)->signature->naturalType; Elts.push_back(type); } @@ -343,7 +343,7 @@ uint32 offset = 0; for (std::vector::iterator i = virtualFields.begin(), e = virtualFields.end(); i!= e; ++i) { - (*i)->offset = vm->getLLVMModule()->getContext().getConstantInt(llvm::Type::Int32Ty, ++offset); + (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset); const llvm::Type* type = (*i)->signature->naturalType; Elts.push_back(type); } From nicolas.geoffray at lip6.fr Mon Jul 27 11:01:43 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 27 Jul 2009 18:01:43 -0000 Subject: [vmkit-commits] [vmkit] r77214 - /vmkit/trunk/tools/vmjc/vmjc.cpp Message-ID: <200907271801.n6RI1isY014933@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jul 27 13:01:43 2009 New Revision: 77214 URL: http://llvm.org/viewvc/llvm-project?rev=77214&view=rev Log: Remove deleted header. Modified: vmkit/trunk/tools/vmjc/vmjc.cpp Modified: vmkit/trunk/tools/vmjc/vmjc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/vmjc/vmjc.cpp?rev=77214&r1=77213&r2=77214&view=diff ============================================================================== --- vmkit/trunk/tools/vmjc/vmjc.cpp (original) +++ vmkit/trunk/tools/vmjc/vmjc.cpp Mon Jul 27 13:01:43 2009 @@ -35,7 +35,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/System/Signals.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachineRegistry.h" #include "llvm/Target/TargetMachine.h" From nicolas.geoffray at lip6.fr Tue Jul 28 03:01:35 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 28 Jul 2009 10:01:35 -0000 Subject: [vmkit-commits] [vmkit] r77313 - in /vmkit/trunk/lib: JnJVM/Compiler/JavaAOTCompiler.cpp JnJVM/Compiler/JavaJIT.cpp Mvm/Compiler/JIT.cpp Message-ID: <200907281001.n6SA1mFU025196@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 28 05:01:17 2009 New Revision: 77313 URL: http://llvm.org/viewvc/llvm-project?rev=77313&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=77313&r1=77312&r2=77313&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Tue Jul 28 05:01:17 2009 @@ -360,11 +360,11 @@ field.getLongField(obj)); Elts.push_back(CI); } else if (prim->isFloat()) { - Constant* CF = Context.getConstantFP(Type::FloatTy, + Constant* CF = ConstantFP::get(Type::FloatTy, field.getFloatField(obj)); Elts.push_back(CF); } else if (prim->isDouble()) { - Constant* CF = Context.getConstantFP(Type::DoubleTy, + Constant* CF = ConstantFP::get(Type::DoubleTy, field.getDoubleField(obj)); Elts.push_back(CF); } else { @@ -390,9 +390,9 @@ if (Ty == Type::Int64Ty) { Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->LongAt(idx))); } else if (Ty == Type::DoubleTy) { - Elts.push_back(Context.getConstantFP(Ty, ctpInfo->DoubleAt(idx))); + Elts.push_back(ConstantFP::get(Ty, ctpInfo->DoubleAt(idx))); } else if (Ty == Type::FloatTy) { - Elts.push_back(Context.getConstantFP(Ty, ctpInfo->FloatAt(idx))); + Elts.push_back(ConstantFP::get(Ty, ctpInfo->FloatAt(idx))); } else { Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->IntegerAt(idx))); } @@ -409,7 +409,7 @@ } } - return Context.getConstantStruct(STy, Elts); + return ConstantStruct::get(STy, Elts); } Constant* JavaAOTCompiler::getStaticInstance(Class* classDef) { @@ -524,7 +524,7 @@ Constant* L = ConstantInt::get(Type::Int64Ty, 0); Elmts.push_back(ConstantExpr::getIntToPtr(L, JnjvmModule::ptrType)); - return Context.getConstantStruct(STy, Elmts); + return ConstantStruct::get(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromJavaClass(CommonClass* cl) { @@ -555,7 +555,7 @@ // constructor Elmts.push_back(Context.getNullValue(JnjvmModule::JavaObjectType)); - return Context.getConstantStruct(STy, Elmts); + return ConstantStruct::get(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromJavaObject(JavaObject* obj) { @@ -636,11 +636,11 @@ field.getLongField(obj)); TempElts.push_back(CI); } else if (prim->isFloat()) { - Constant* CF = Context.getConstantFP(Type::FloatTy, + Constant* CF = ConstantFP::get(Type::FloatTy, field.getFloatField(obj)); TempElts.push_back(CF); } else if (prim->isDouble()) { - Constant* CF = Context.getConstantFP(Type::DoubleTy, + Constant* CF = ConstantFP::get(Type::DoubleTy, field.getDoubleField(obj)); TempElts.push_back(CF); } else { @@ -657,7 +657,7 @@ } } } - CurConstant = Context.getConstantStruct(STy, TempElts); + CurConstant = ConstantStruct::get(STy, TempElts); } return CurConstant; @@ -691,7 +691,7 @@ Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->cachedHashCode)); Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->offset)); - return Context.getConstantStruct(STy, Elmts); + return ConstantStruct::get(STy, Elmts); } @@ -706,7 +706,7 @@ Elmts.push_back(Context.getNullValue(STy->getContainedType(2))); Elmts.push_back(getEnveloppe(CN->enveloppe)); - return Context.getConstantStruct(STy, Elmts); + return ConstantStruct::get(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromEnveloppe(Enveloppe* val) { @@ -731,7 +731,7 @@ Elmts.push_back(getNativeClass(val->classDef)); Elmts.push_back(firstCache); - return Context.getConstantStruct(STy, Elmts); + return ConstantStruct::get(STy, Elmts); } @@ -752,7 +752,7 @@ // nbb Elmts.push_back(ConstantInt::get(Type::Int32Ty, attribut.nbb)); - return Context.getConstantStruct(STy, Elmts); + return ConstantStruct::get(STy, Elmts); } Constant* JavaAOTCompiler::CreateConstantFromCommonClass(CommonClass* cl) { @@ -823,7 +823,7 @@ TempTy = JnjvmModule::VTType; CommonClassElts.push_back(Mod.getContext().getNullValue(TempTy)); } - return Context.getConstantStruct(STy, CommonClassElts); + return ConstantStruct::get(STy, CommonClassElts); } Constant* JavaAOTCompiler::CreateConstantFromJavaField(JavaField& field) { @@ -883,7 +883,7 @@ //JInfo FieldElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); - return Context.getConstantStruct(STy, FieldElts); + return ConstantStruct::get(STy, FieldElts); } Constant* JavaAOTCompiler::CreateConstantFromJavaMethod(JavaMethod& method) { @@ -961,7 +961,7 @@ //JInfo MethodElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); - return Context.getConstantStruct(STy, MethodElts); + return ConstantStruct::get(STy, MethodElts); } Constant* JavaAOTCompiler::CreateConstantFromClassPrimitive(ClassPrimitive* cl) { @@ -978,7 +978,7 @@ // primSize ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->logSize)); - return Context.getConstantStruct(STy, ClassElts); + return ConstantStruct::get(STy, ClassElts); } Constant* JavaAOTCompiler::CreateConstantFromClassArray(ClassArray* cl) { @@ -1000,7 +1000,7 @@ ClassElts.push_back(Cl); - return Context.getConstantStruct(STy, ClassElts); + return ConstantStruct::get(STy, ClassElts); } Constant* JavaAOTCompiler::CreateConstantFromClass(Class* cl) { @@ -1029,7 +1029,7 @@ TempElts.push_back(ConstantInt::get(Type::Int8Ty, status)); TempElts.push_back(ConstantInt::get(Type::Int1Ty, status == ready ? 1 : 0)); TempElts.push_back(getStaticInstance(cl)); - Constant* CStr[1] = { Context.getConstantStruct(TCMTy, TempElts) }; + Constant* CStr[1] = { ConstantStruct::get(TCMTy, TempElts) }; TempElts.clear(); ClassElts.push_back(Context.getConstantArray(ATy, CStr, 1)); @@ -1218,7 +1218,7 @@ // JInfo ClassElts.push_back(Mod.getContext().getNullValue(JnjvmModule::ptrType)); - return Context.getConstantStruct(STy, ClassElts); + return ConstantStruct::get(STy, ClassElts); } template @@ -1244,7 +1244,7 @@ if (Ty->isInteger()) { Vals.push_back(ConstantInt::get(Ty, (uint64)val->elements[i])); } else if (Ty->isFloatingPoint()) { - Vals.push_back(Context.getConstantFP(Ty, (double)(size_t)val->elements[i])); + Vals.push_back(ConstantFP::get(Ty, (double)(size_t)val->elements[i])); } else { if (val->elements[i]) { Vals.push_back(getFinalObject((JavaObject*)(size_t)val->elements[i])); @@ -1256,7 +1256,7 @@ Cts.push_back(Context.getConstantArray(ATy, Vals)); - return Context.getConstantStruct(STy, Cts); + return ConstantStruct::get(STy, Cts); } Constant* JavaAOTCompiler::CreateConstantFromUTF8(const UTF8* val) { @@ -1280,7 +1280,7 @@ Cts.push_back(Context.getConstantArray(ATy, Vals)); - return Context.getConstantStruct(STy, Cts); + return ConstantStruct::get(STy, Cts); } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=77313&r1=77312&r2=77313&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 28 05:01:17 2009 @@ -1215,13 +1215,13 @@ push(ConstantInt::get(Type::Int64Ty, ctpInfo->LongAt(index)), false); } else if (type == JavaConstantPool::ConstantDouble) { - push(llvmContext->getConstantFP(Type::DoubleTy, ctpInfo->DoubleAt(index)), + push(ConstantFP::get(Type::DoubleTy, ctpInfo->DoubleAt(index)), false); } else if (type == JavaConstantPool::ConstantInteger) { push(ConstantInt::get(Type::Int32Ty, ctpInfo->IntegerAt(index)), false); } else if (type == JavaConstantPool::ConstantFloat) { - push(llvmContext->getConstantFP(Type::FloatTy, ctpInfo->FloatAt(index)), + push(ConstantFP::get(Type::FloatTy, ctpInfo->FloatAt(index)), false); } else if (type == JavaConstantPool::ConstantClass) { UserCommonClass* cl = 0; @@ -1936,10 +1936,10 @@ push(ConstantInt::get(Type::Int64Ty, val), false); } else if (prim->isFloat()) { float val = (float)field->getFloatField(Obj); - push(llvmContext->getConstantFP(Type::FloatTy, val), false); + push(ConstantFP::get(Type::FloatTy, val), false); } else if (prim->isDouble()) { double val = (double)field->getDoubleField(Obj); - push(llvmContext->getConstantFP(Type::DoubleTy, val), false); + push(ConstantFP::get(Type::DoubleTy, val), false); } else { abort(); } Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77313&r1=77312&r2=77313&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Tue Jul 28 05:01:17 2009 @@ -116,26 +116,26 @@ constantMaxInt = ConstantInt::get(Type::Int32Ty, MaxInt); constantMinLong = ConstantInt::get(Type::Int64Ty, MinLong); constantMaxLong = ConstantInt::get(Type::Int64Ty, MaxLong); - constantFloatZero = globalContext->getConstantFP(Type::FloatTy, 0.0f); - constantFloatOne = globalContext->getConstantFP(Type::FloatTy, 1.0f); - constantFloatTwo = globalContext->getConstantFP(Type::FloatTy, 2.0f); - constantDoubleZero = globalContext->getConstantFP(Type::DoubleTy, 0.0); - constantDoubleOne = globalContext->getConstantFP(Type::DoubleTy, 1.0); - constantMaxIntFloat = globalContext->getConstantFP(Type::FloatTy, MaxIntFloat); - constantMinIntFloat = globalContext->getConstantFP(Type::FloatTy, MinIntFloat); - constantMinLongFloat = globalContext->getConstantFP(Type::FloatTy, MinLongFloat); - constantMinLongDouble = globalContext->getConstantFP(Type::DoubleTy, MinLongDouble); - constantMaxLongFloat = globalContext->getConstantFP(Type::FloatTy, MaxLongFloat); - constantMaxIntDouble = globalContext->getConstantFP(Type::DoubleTy, MaxIntDouble); - constantMinIntDouble = globalContext->getConstantFP(Type::DoubleTy, MinIntDouble); - constantMaxLongDouble = globalContext->getConstantFP(Type::DoubleTy, MaxLongDouble); - constantMaxLongDouble = globalContext->getConstantFP(Type::DoubleTy, MaxLongDouble); - constantFloatInfinity = globalContext->getConstantFP(Type::FloatTy, MaxFloat); - constantFloatMinusInfinity = globalContext->getConstantFP(Type::FloatTy, MinFloat); - constantDoubleInfinity = globalContext->getConstantFP(Type::DoubleTy, MaxDouble); - constantDoubleMinusInfinity = globalContext->getConstantFP(Type::DoubleTy, MinDouble); - constantDoubleMinusZero = globalContext->getConstantFP(Type::DoubleTy, -0.0); - constantFloatMinusZero = globalContext->getConstantFP(Type::FloatTy, -0.0f); + constantFloatZero = ConstantFP::get(Type::FloatTy, 0.0f); + constantFloatOne = ConstantFP::get(Type::FloatTy, 1.0f); + constantFloatTwo = ConstantFP::get(Type::FloatTy, 2.0f); + constantDoubleZero = ConstantFP::get(Type::DoubleTy, 0.0); + constantDoubleOne = ConstantFP::get(Type::DoubleTy, 1.0); + constantMaxIntFloat = ConstantFP::get(Type::FloatTy, MaxIntFloat); + constantMinIntFloat = ConstantFP::get(Type::FloatTy, MinIntFloat); + constantMinLongFloat = ConstantFP::get(Type::FloatTy, MinLongFloat); + constantMinLongDouble = ConstantFP::get(Type::DoubleTy, MinLongDouble); + constantMaxLongFloat = ConstantFP::get(Type::FloatTy, MaxLongFloat); + constantMaxIntDouble = ConstantFP::get(Type::DoubleTy, MaxIntDouble); + constantMinIntDouble = ConstantFP::get(Type::DoubleTy, MinIntDouble); + constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, MaxLongDouble); + constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, MaxLongDouble); + constantFloatInfinity = ConstantFP::get(Type::FloatTy, MaxFloat); + constantFloatMinusInfinity = ConstantFP::get(Type::FloatTy, MinFloat); + constantDoubleInfinity = ConstantFP::get(Type::DoubleTy, MaxDouble); + constantDoubleMinusInfinity = ConstantFP::get(Type::DoubleTy, MinDouble); + constantDoubleMinusZero = ConstantFP::get(Type::DoubleTy, -0.0); + constantFloatMinusZero = ConstantFP::get(Type::FloatTy, -0.0f); constantThreadIDMask = ConstantInt::get(pointerSizeType, mvm::Thread::IDMask); constantStackOverflowMask = ConstantInt::get(pointerSizeType, mvm::Thread::StackOverflowMask); From nicolas.geoffray at lip6.fr Tue Jul 28 03:04:48 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 28 Jul 2009 10:04:48 -0000 Subject: [vmkit-commits] [vmkit] r77314 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907281004.n6SA4tEK025298@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 28 05:04:44 2009 New Revision: 77314 URL: http://llvm.org/viewvc/llvm-project?rev=77314&view=rev Log: Remove warning. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=77314&r1=77313&r2=77314&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Tue Jul 28 05:04:44 2009 @@ -326,7 +326,6 @@ const Type* Ty = LCI->getStaticType(); const StructType* STy = dyn_cast(Ty->getContainedType(0)); Module& Mod = *getLLVMModule(); - LLVMContext& Context = Mod.getContext(); std::vector Elts; @@ -515,7 +514,6 @@ dyn_cast(JnjvmModule::JavaObjectType->getContainedType(0)); std::vector Elmts; - LLVMContext& Context = getLLVMModule()->getContext(); // VT Elmts.push_back(getVirtualTable(cl->virtualVT)); @@ -561,7 +559,6 @@ Constant* JavaAOTCompiler::CreateConstantFromJavaObject(JavaObject* obj) { CommonClass* cl = obj->getClass(); Module& Mod = *getLLVMModule(); - LLVMContext& Context = getLLVMModule()->getContext(); if (cl->isArray()) { Classpath* upcalls = cl->classLoader->bootstrapLoader->upcalls; @@ -669,7 +666,6 @@ LLVMClassInfo* LCI = getClassInfo(cl); const StructType* STy = dyn_cast(LCI->getVirtualType()->getContainedType(0)); - LLVMContext& Context = getLLVMModule()->getContext(); std::vector Elmts; @@ -738,7 +734,6 @@ Constant* JavaAOTCompiler::CreateConstantFromAttribut(Attribut& attribut) { const StructType* STy = dyn_cast(JnjvmModule::AttributType->getContainedType(0)); - LLVMContext& Context = getLLVMModule()->getContext(); std::vector Elmts; @@ -968,7 +963,6 @@ const llvm::Type* JCPTy = JnjvmModule::JavaClassPrimitiveType->getContainedType(0); const StructType* STy = dyn_cast(JCPTy); - LLVMContext& Context = getLLVMModule()->getContext(); std::vector ClassElts; @@ -984,7 +978,6 @@ Constant* JavaAOTCompiler::CreateConstantFromClassArray(ClassArray* cl) { const StructType* STy = dyn_cast(JnjvmModule::JavaClassArrayType->getContainedType(0)); - LLVMContext& Context = getLLVMModule()->getContext(); std::vector ClassElts; Constant* ClGEPs[2] = { getIntrinsics()->constantZero, From nicolas.geoffray at lip6.fr Tue Jul 28 03:20:04 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 28 Jul 2009 10:20:04 -0000 Subject: [vmkit-commits] [vmkit] r77315 - /vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Message-ID: <200907281020.n6SAKAwL025675@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 28 05:19:33 2009 New Revision: 77315 URL: http://llvm.org/viewvc/llvm-project?rev=77315&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=77315&r1=77314&r2=77315&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Tue Jul 28 05:19:33 2009 @@ -757,12 +757,12 @@ } case LDC_R4 : { - push(llvmFunction->getContext().getConstantFP(Type::FloatTy, readFloat(bytecodes, i))); + push(ConstantFP::get(Type::FloatTy, readFloat(bytecodes, i))); break; } case LDC_R8 : { - push(llvmFunction->getContext().getConstantFP(Type::DoubleTy, readDouble(bytecodes, i))); + push(ConstantFP::get(Type::DoubleTy, readDouble(bytecodes, i))); break; } From nicolas.geoffray at lip6.fr Tue Jul 28 03:24:29 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 28 Jul 2009 10:24:29 -0000 Subject: [vmkit-commits] [vmkit] r77316 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h include/mvm/JIT.h lib/JnJVM/Compiler/JavaJIT.cpp lib/JnJVM/Compiler/JavaJIT.h lib/JnJVM/Compiler/JavaJITOpcodes.cpp lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll lib/Mvm/Compiler/JIT.cpp lib/Mvm/Compiler/LLVMRuntime.ll lib/Mvm/Runtime/Object.cpp Message-ID: <200907281024.n6SAOdDH025830@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 28 05:24:07 2009 New Revision: 77316 URL: http://llvm.org/viewvc/llvm-project?rev=77316&view=rev Log: Add the first bits for cooperative GC. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/include/mvm/JIT.h vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/Mvm/Compiler/JIT.cpp vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll vmkit/trunk/lib/Mvm/Runtime/Object.cpp Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Tue Jul 28 05:24:07 2009 @@ -375,6 +375,7 @@ bool enabledException; + bool cooperativeGC; virtual void makeVT(Class* cl) = 0; @@ -398,11 +399,19 @@ bool hasExceptionsEnabled() { return enabledException; } + + bool useCooperativeGC() { + return cooperativeGC; + } void disableExceptions() { enabledException = false; } + void disableCooperativeGC() { + cooperativeGC = false; + } + virtual JavaCompiler* Create(const std::string& ModuleID) = 0; virtual ~JavaLLVMCompiler(); Modified: vmkit/trunk/include/mvm/JIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/include/mvm/JIT.h (original) +++ vmkit/trunk/include/mvm/JIT.h Tue Jul 28 05:24:07 2009 @@ -115,6 +115,8 @@ llvm::Function* llvm_atomic_lcs_ptr; llvm::Function* llvm_gc_gcroot; + llvm::Function* conditionalSafePoint; + llvm::Function* unconditionalSafePoint; llvm::Constant* constantInt8Zero; llvm::Constant* constantZero; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 28 05:24:07 2009 @@ -368,8 +368,12 @@ new BitCastInst(temp, module->ptrPtrType, "", currentBlock), module->constantPtrNull }; - CallInst::Create(module->llvm_gc_gcroot, GCArgs, GCArgs + 2, "", - currentBlock); + + if (TheCompiler->useCooperativeGC()) { + CallInst::Create(module->llvm_gc_gcroot, GCArgs, GCArgs + 2, "", + currentBlock); + } + new StoreInst(i, temp, false, currentBlock); node->addIncoming(temp, currentBlock); BranchInst::Create(BB, currentBlock); @@ -668,17 +672,19 @@ } static void removeUnusedObjects(std::vector& objects, - JnjvmModule* module) { + JnjvmModule* module, bool coop) { for (std::vector::iterator i = objects.begin(), e = objects.end(); i != e; ++i) { AllocaInst* temp = *i; if (temp->getNumUses()) { - Instruction* I = new BitCastInst(temp, module->ptrPtrType, ""); - I->insertAfter(temp); - Value* GCArgs[2] = { I, module->constantPtrNull }; - Instruction* C = CallInst::Create(module->llvm_gc_gcroot, GCArgs, - GCArgs + 2, ""); - C->insertAfter(I); + if (coop) { + Instruction* I = new BitCastInst(temp, module->ptrPtrType, ""); + I->insertAfter(temp); + Value* GCArgs[2] = { I, module->constantPtrNull }; + Instruction* C = CallInst::Create(module->llvm_gc_gcroot, GCArgs, + GCArgs + 2, ""); + C->insertAfter(I); + } } else { temp->eraseFromParent(); } @@ -845,8 +851,8 @@ removeUnusedLocals(floatStack); removeUnusedLocals(longStack); - removeUnusedObjects(objectLocals, module); - removeUnusedObjects(objectStack, module); + removeUnusedObjects(objectLocals, module, TheCompiler->useCooperativeGC()); + removeUnusedObjects(objectStack, module, TheCompiler->useCooperativeGC()); return endNode; @@ -1039,7 +1045,27 @@ if (returnType != Type::VoidTy) { endNode = llvm::PHINode::Create(returnType, "", endBlock); } - + + if (TheCompiler->useCooperativeGC()) { + Value* threadId = getCurrentThread(); + + Value* YieldPtr = + GetElementPtrInst::Create(threadId, + module->OffsetDoYieldInThreadConstant, + "", currentBlock); + + Value* Yield = new LoadInst(YieldPtr, "", currentBlock); + + BasicBlock* continueBlock = createBasicBlock("After safe point"); + BasicBlock* yieldBlock = createBasicBlock("In safe point"); + BranchInst::Create(yieldBlock, continueBlock, Yield, currentBlock); + + currentBlock = yieldBlock; + CallInst::Create(module->conditionalSafePoint, "", currentBlock); + BranchInst::Create(continueBlock, currentBlock); + + currentBlock = continueBlock; + } if (isSynchro(compilingMethod->access)) @@ -1148,8 +1174,8 @@ removeUnusedLocals(floatStack); removeUnusedLocals(longStack); - removeUnusedObjects(objectLocals, module); - removeUnusedObjects(objectStack, module); + removeUnusedObjects(objectLocals, module, TheCompiler->useCooperativeGC()); + removeUnusedObjects(objectStack, module, TheCompiler->useCooperativeGC()); func->setLinkage(GlobalValue::ExternalLinkage); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Tue Jul 28 05:24:07 2009 @@ -51,6 +51,11 @@ /// handler. /// bool handler; + + /// backEdge - If the instruction is the first instruction of a basic block + /// where a forward opcode branches to, consider the block as a back edge. + /// + bool backEdge; }; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Tue Jul 28 05:24:07 2009 @@ -2423,6 +2423,9 @@ uint16 index = tmp + readU2(bytecodes, i); if (!(opcodeInfos[index].newBlock)) opcodeInfos[index].newBlock = createBasicBlock("GOTO or IF*"); + + if (index <= tmp) opcodeInfos[index].backEdge = true; + break; } @@ -2455,6 +2458,9 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index].newBlock = block; } + + if (index <= tmp) opcodeInfos[index].backEdge = true; + uint32 low = readU4(bytecodes, i); uint32 high = readU4(bytecodes, i) + 1; uint32 depl = high - low; @@ -2464,6 +2470,7 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index2].newBlock = block; } + if (index2 <= tmp) opcodeInfos[index2].backEdge = true; } i = tmp + 12 + filled + (depl << 2); break; @@ -2478,6 +2485,8 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index].newBlock = block; } + if (index <= tmp) opcodeInfos[index].backEdge = true; + uint32 nbs = readU4(bytecodes, i); for (uint32 cur = 0; cur < nbs; ++cur) { i += 4; @@ -2486,6 +2495,7 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index2].newBlock = block; } + if (index2 <= tmp) opcodeInfos[index2].backEdge = true; } i = tmp + 8 + filled + (nbs << 3); @@ -2557,6 +2567,7 @@ uint16 index = tmp + readU2(bytecodes, i); if (!(opcodeInfos[index].newBlock)) opcodeInfos[index].newBlock = createBasicBlock("true IF*NULL"); + if (index <= tmp) opcodeInfos[index].backEdge = true; break; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Tue Jul 28 05:24:07 2009 @@ -66,6 +66,7 @@ JavaIntrinsics(TheModule) { enabledException = true; + cooperativeGC = false; } void JavaLLVMCompiler::resolveVirtualClass(Class* cl) { Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Tue Jul 28 05:24:07 2009 @@ -229,7 +229,6 @@ declare void @jnjvmJNIProceedPendingException(i32**, i8**) declare void @jnjvmGetSJLJBuffer(i32*, i32**, i8*, i8**) -declare %JavaObject* @gcmalloc(i32, %VT*) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Debugging methods ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -238,3 +237,11 @@ declare void @jnjvmPrintExecution(i32, i32, %JavaMethod*) declare void @jnjvmPrintMethodStart(%JavaMethod*) declare void @jnjvmPrintMethodEnd(%JavaMethod*) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GC methods ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +declare %JavaObject* @gcmalloc(i32, %VT*) Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Tue Jul 28 05:24:07 2009 @@ -211,6 +211,9 @@ llvm_atomic_lcs_ptr = pointerSizeType == Type::Int32Ty ? llvm_atomic_lcs_i32 : llvm_atomic_lcs_i64; + + unconditionalSafePoint = module->getFunction("unconditionalSafePoint"); + conditionalSafePoint = module->getFunction("conditionalSafePoint"); } Modified: vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll (original) +++ vmkit/trunk/lib/Mvm/Compiler/LLVMRuntime.ll Tue Jul 28 05:24:07 2009 @@ -74,6 +74,9 @@ declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64*, i64, i64) nounwind +declare void @unconditionalSafePoint() nounwind +declare void @conditionalSafePoint() nounwind + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Modified: vmkit/trunk/lib/Mvm/Runtime/Object.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Runtime/Object.cpp?rev=77316&r1=77315&r2=77316&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Runtime/Object.cpp (original) +++ vmkit/trunk/lib/Mvm/Runtime/Object.cpp Tue Jul 28 05:24:07 2009 @@ -307,3 +307,9 @@ void Allocator::freeTemporaryMemory(void* obj) { return free(obj); } + + + +extern "C" void conditionalSafePoint() { + abort(); +} From nicolas.geoffray at lip6.fr Tue Jul 28 07:53:20 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 28 Jul 2009 14:53:20 -0000 Subject: [vmkit-commits] [vmkit] r77319 - in /vmkit/trunk/lib: JnJVM/Compiler/JavaJIT.cpp JnJVM/Compiler/JavaJIT.h JnJVM/Compiler/JavaJITOpcodes.cpp JnJVM/Compiler/JnjvmModule.cpp Mvm/Compiler/LoopSafePoints.cpp Message-ID: <200907281453.n6SErN6e000812@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 28 09:53:06 2009 New Revision: 77319 URL: http://llvm.org/viewvc/llvm-project?rev=77319&view=rev Log: Add safe points in loops during an LLVM pass, not directly. This way, we can benefit from llvm loop optimization passes. Added: vmkit/trunk/lib/Mvm/Compiler/LoopSafePoints.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=77319&r1=77318&r2=77319&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Tue Jul 28 09:53:06 2009 @@ -859,7 +859,6 @@ } - llvm::Function* JavaJIT::javaCompile() { PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "compiling %s.%s\n", UTF8Buffer(compilingClass->name).cString(), @@ -1045,28 +1044,6 @@ if (returnType != Type::VoidTy) { endNode = llvm::PHINode::Create(returnType, "", endBlock); } - - if (TheCompiler->useCooperativeGC()) { - Value* threadId = getCurrentThread(); - - Value* YieldPtr = - GetElementPtrInst::Create(threadId, - module->OffsetDoYieldInThreadConstant, - "", currentBlock); - - Value* Yield = new LoadInst(YieldPtr, "", currentBlock); - - BasicBlock* continueBlock = createBasicBlock("After safe point"); - BasicBlock* yieldBlock = createBasicBlock("In safe point"); - BranchInst::Create(yieldBlock, continueBlock, Yield, currentBlock); - - currentBlock = yieldBlock; - CallInst::Create(module->conditionalSafePoint, "", currentBlock); - BranchInst::Create(continueBlock, currentBlock); - - currentBlock = continueBlock; - } - if (isSynchro(compilingMethod->access)) beginSynchronize(); @@ -1093,6 +1070,28 @@ throwException(module->StackOverflowErrorFunction, 0, 0); currentBlock = noStackOverflow; } + + if (TheCompiler->useCooperativeGC()) { + Value* threadId = getCurrentThread(); + + Value* GEP[2] = { module->constantZero, + module->OffsetDoYieldInThreadConstant }; + + Value* YieldPtr = GetElementPtrInst::Create(threadId, GEP, GEP + 2, "", + currentBlock); + + Value* Yield = new LoadInst(YieldPtr, "", currentBlock); + + BasicBlock* continueBlock = createBasicBlock("After safe point"); + BasicBlock* yieldBlock = createBasicBlock("In safe point"); + BranchInst::Create(yieldBlock, continueBlock, Yield, currentBlock); + + currentBlock = yieldBlock; + CallInst::Create(module->conditionalSafePoint, "", currentBlock); + BranchInst::Create(continueBlock, currentBlock); + + currentBlock = continueBlock; + } compileOpcodes(&compilingClass->bytes->elements[start], codeLen); Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h?rev=77319&r1=77318&r2=77319&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.h Tue Jul 28 09:53:06 2009 @@ -52,10 +52,6 @@ /// bool handler; - /// backEdge - If the instruction is the first instruction of a basic block - /// where a forward opcode branches to, consider the block as a back edge. - /// - bool backEdge; }; Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=77319&r1=77318&r2=77319&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Tue Jul 28 09:53:06 2009 @@ -2423,9 +2423,6 @@ uint16 index = tmp + readU2(bytecodes, i); if (!(opcodeInfos[index].newBlock)) opcodeInfos[index].newBlock = createBasicBlock("GOTO or IF*"); - - if (index <= tmp) opcodeInfos[index].backEdge = true; - break; } @@ -2458,9 +2455,6 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index].newBlock = block; } - - if (index <= tmp) opcodeInfos[index].backEdge = true; - uint32 low = readU4(bytecodes, i); uint32 high = readU4(bytecodes, i) + 1; uint32 depl = high - low; @@ -2470,7 +2464,6 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index2].newBlock = block; } - if (index2 <= tmp) opcodeInfos[index2].backEdge = true; } i = tmp + 12 + filled + (depl << 2); break; @@ -2485,8 +2478,6 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index].newBlock = block; } - if (index <= tmp) opcodeInfos[index].backEdge = true; - uint32 nbs = readU4(bytecodes, i); for (uint32 cur = 0; cur < nbs; ++cur) { i += 4; @@ -2495,7 +2486,6 @@ BasicBlock* block = createBasicBlock("tableswitch"); opcodeInfos[index2].newBlock = block; } - if (index2 <= tmp) opcodeInfos[index2].backEdge = true; } i = tmp + 8 + filled + (nbs << 3); @@ -2567,7 +2557,6 @@ uint16 index = tmp + readU2(bytecodes, i); if (!(opcodeInfos[index].newBlock)) opcodeInfos[index].newBlock = createBasicBlock("true IF*NULL"); - if (index <= tmp) opcodeInfos[index].backEdge = true; break; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77319&r1=77318&r2=77319&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Tue Jul 28 09:53:06 2009 @@ -14,6 +14,7 @@ #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" +#include "llvm/Analysis/LoopPass.h" #include "llvm/Target/TargetData.h" #include "mvm/JIT.h" @@ -356,6 +357,7 @@ namespace mvm { llvm::FunctionPass* createEscapeAnalysisPass(); + llvm::LoopPass* createLoopSafePointsPass(); } namespace jnjvm { @@ -371,6 +373,9 @@ JavaFunctionPasses = new FunctionPassManager(TheModuleProvider); JavaFunctionPasses->add(new TargetData(TheModule)); + if (cooperativeGC) + JavaFunctionPasses->add(mvm::createLoopSafePointsPass()); + JavaFunctionPasses->add(mvm::createEscapeAnalysisPass()); JavaFunctionPasses->add(createLowerConstantCallsPass()); } Added: vmkit/trunk/lib/Mvm/Compiler/LoopSafePoints.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/LoopSafePoints.cpp?rev=77319&view=auto ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/LoopSafePoints.cpp (added) +++ vmkit/trunk/lib/Mvm/Compiler/LoopSafePoints.cpp Tue Jul 28 09:53:06 2009 @@ -0,0 +1,126 @@ +//===------- LoopSafePoints.cpp - Add safe points in loop headers ---------===// +// +// The VMKit project +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Compiler.h" + +using namespace llvm; + +namespace { + + class VISIBILITY_HIDDEN LoopSafePoints : public LoopPass { + public: + static char ID; + + LoopSafePoints() : LoopPass((intptr_t)&ID) {} + + virtual bool runOnLoop(Loop* L, LPPassManager& LPM); + + private: + void insertSafePoint(BasicBlock* BB, Function* SafeFunction, + Value* YieldPtr); + }; + + char LoopSafePoints::ID = 0; + RegisterPass X("LoopSafePoints", + "Add safe points in loop headers"); + +void LoopSafePoints::insertSafePoint(BasicBlock* BB, Function* SafeFunction, + Value* YieldPtr) { + Instruction* I = BB->getFirstNonPHI(); + BasicBlock* NBB = BB->splitBasicBlock(I); + + NBB = NBB->getSinglePredecessor(); + I = NBB->getTerminator(); + BasicBlock* SU = (static_cast(I))->getSuccessor(0); + I->eraseFromParent(); + + Value* Ld = new LoadInst(YieldPtr, "", NBB); + BasicBlock* yield = BasicBlock::Create("", BB->getParent()); + BranchInst::Create(yield, SU, Ld, NBB); + + CallInst::Create(SafeFunction, "", yield); + BranchInst::Create(SU, yield); +} + +bool LoopSafePoints::runOnLoop(Loop* L, LPPassManager& LPM) { + + BasicBlock* Header = L->getHeader(); + Function *F = Header->getParent(); + Function* SafeFunction = + F->getParent()->getFunction("conditionalSafePoint"); + if (!SafeFunction) return false; + + Value* YieldPtr = 0; + + // Lookup the yield pointer. + for (Function::iterator BI = F->begin(), BE = F->end(); BI != BE; BI++) { + BasicBlock *Cur = BI; + + for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) { + Instruction *I = II; + II++; + CallSite Call = CallSite::get(I); + if (Call.getInstruction() && Call.getCalledValue() == SafeFunction) { + if (BasicBlock* Incoming = Cur->getSinglePredecessor()) { + if (BranchInst* T = dyn_cast(Incoming->getTerminator())) { + if (LoadInst* LI = dyn_cast(T->getCondition())) { + YieldPtr = LI->getPointerOperand(); + break; + } + } + } + } + } + if (YieldPtr) break; + } + + assert(YieldPtr && "Could not find initial yield pointer."); + + TerminatorInst* TI = Header->getTerminator(); + + // Insert the check after the entry block if the entry block does the + // loop exit. + if (BranchInst* BI = dyn_cast(TI)) { + if (BI->isConditional()) { + + BasicBlock* First = BI->getSuccessor(0); + BasicBlock* Second = BI->getSuccessor(1); + + bool containsFirst = L->contains(First); + bool containsSecond = L->contains(Second); + + if (!containsFirst) { + insertSafePoint(Second, SafeFunction, YieldPtr); + return true; + } + + if (!containsSecond) { + insertSafePoint(First, SafeFunction, YieldPtr); + return true; + } + } + } + + insertSafePoint(Header, SafeFunction, YieldPtr); + return true; +} + +} + + +namespace mvm { + +LoopPass* createLoopSafePointsPass() { + return new LoopSafePoints(); +} + +} From nicolas.geoffray at lip6.fr Tue Jul 28 10:47:41 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 28 Jul 2009 17:47:41 -0000 Subject: [vmkit-commits] [vmkit] r77333 - /vmkit/trunk/tools/jnjvm/Main.cpp Message-ID: <200907281747.n6SHlf2r006653@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jul 28 12:47:41 2009 New Revision: 77333 URL: http://llvm.org/viewvc/llvm-project?rev=77333&view=rev Log: Fix header. Modified: vmkit/trunk/tools/jnjvm/Main.cpp Modified: vmkit/trunk/tools/jnjvm/Main.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/jnjvm/Main.cpp?rev=77333&r1=77332&r2=77333&view=diff ============================================================================== --- vmkit/trunk/tools/jnjvm/Main.cpp (original) +++ vmkit/trunk/tools/jnjvm/Main.cpp Tue Jul 28 12:47:41 2009 @@ -1,8 +1,8 @@ //===--------- Main.cpp - Simple execution of JnJVM -----------------------===// // -// JnJVM +// The VMKit project // -// This file is distributed under the University of Pierre et Marie Curie +// This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// From nicolas.geoffray at lip6.fr Wed Jul 29 01:51:33 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 29 Jul 2009 08:51:33 -0000 Subject: [vmkit-commits] [vmkit] r77448 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907290851.n6T8pYNL016257@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 29 03:51:20 2009 New Revision: 77448 URL: http://llvm.org/viewvc/llvm-project?rev=77448&view=rev Log: Move to new LLVM API. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=77448&r1=77447&r2=77448&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Wed Jul 29 03:51:20 2009 @@ -766,7 +766,7 @@ assert(ATy && "Malformed type"); Constant* TCM[1] = { getJavaClass(cl) }; - CommonClassElts.push_back(Context.getConstantArray(ATy, TCM, 1)); + CommonClassElts.push_back(ConstantArray::get(ATy, TCM, 1)); // access CommonClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->access)); @@ -778,7 +778,7 @@ } ATy = ArrayType::get(JnjvmModule::JavaClassType, cl->nbInterfaces); - Constant* interfaces = Context.getConstantArray(ATy, TempElmts); + Constant* interfaces = ConstantArray::get(ATy, TempElmts); interfaces = new GlobalVariable(Mod, ATy, true, GlobalValue::InternalLinkage, interfaces, ""); @@ -850,7 +850,7 @@ TempElts.push_back(CreateConstantFromAttribut(field.attributs[i])); } - Constant* attributs = Context.getConstantArray(ATy, TempElts); + Constant* attributs = ConstantArray::get(ATy, TempElts); TempElts.clear(); attributs = new GlobalVariable(*getLLVMModule(), ATy, true, GlobalValue::InternalLinkage, @@ -904,7 +904,7 @@ TempElts.push_back(CreateConstantFromAttribut(method.attributs[i])); } - Constant* attributs = Context.getConstantArray(ATy, TempElts); + Constant* attributs = ConstantArray::get(ATy, TempElts); TempElts.clear(); attributs = new GlobalVariable(Mod, ATy, true, GlobalValue::InternalLinkage, @@ -1024,7 +1024,7 @@ TempElts.push_back(getStaticInstance(cl)); Constant* CStr[1] = { ConstantStruct::get(TCMTy, TempElts) }; TempElts.clear(); - ClassElts.push_back(Context.getConstantArray(ATy, CStr, 1)); + ClassElts.push_back(ConstantArray::get(ATy, CStr, 1)); // thinlock ClassElts.push_back(Context.getNullValue(JnjvmModule::ptrType)); @@ -1055,7 +1055,7 @@ Constant* fields = 0; if (cl->nbStaticFields + cl->nbVirtualFields) { - fields = Context.getConstantArray(ATy, TempElts); + fields = ConstantArray::get(ATy, TempElts); TempElts.clear(); fields = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, @@ -1102,7 +1102,7 @@ Constant* methods = 0; if (cl->nbVirtualMethods + cl->nbStaticMethods) { - methods = Context.getConstantArray(ATy, TempElts); + methods = ConstantArray::get(ATy, TempElts); TempElts.clear(); GlobalVariable* GV = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, @@ -1147,7 +1147,7 @@ TempElts.push_back(CreateConstantFromAttribut(cl->attributs[i])); } - Constant* attributs = Context.getConstantArray(ATy, TempElts); + Constant* attributs = ConstantArray::get(ATy, TempElts); TempElts.clear(); attributs = new GlobalVariable(*getLLVMModule(), ATy, true, GlobalValue::InternalLinkage, @@ -1170,7 +1170,7 @@ const llvm::Type* TempTy = JnjvmModule::JavaClassType; ATy = ArrayType::get(TempTy, cl->nbInnerClasses); - Constant* innerClasses = Context.getConstantArray(ATy, TempElts); + Constant* innerClasses = ConstantArray::get(ATy, TempElts); innerClasses = new GlobalVariable(*getLLVMModule(), ATy, true, GlobalValue::InternalLinkage, innerClasses, ""); @@ -1247,7 +1247,7 @@ } } - Cts.push_back(Context.getConstantArray(ATy, Vals)); + Cts.push_back(ConstantArray::get(ATy, Vals)); return ConstantStruct::get(STy, Cts); } @@ -1271,7 +1271,7 @@ Vals.push_back(ConstantInt::get(Type::Int16Ty, val->elements[i])); } - Cts.push_back(Context.getConstantArray(ATy, Vals)); + Cts.push_back(ConstantArray::get(ATy, Vals)); return ConstantStruct::get(STy, Cts); @@ -1383,7 +1383,7 @@ Constant* Cl = getVirtualTable(VT->secondaryTypes[i]); TempElmts.push_back(Cl); } - Constant* display = Context.getConstantArray(DTy, TempElmts); + Constant* display = ConstantArray::get(DTy, TempElmts); TempElmts.clear(); display = new GlobalVariable(*getLLVMModule(), DTy, true, @@ -1416,7 +1416,7 @@ } } - Constant* Array = Context.getConstantArray(ATy, Elemts); + Constant* Array = ConstantArray::get(ATy, Elemts); return Array; } @@ -1945,7 +1945,7 @@ GlobalValue::InternalLinkage, 0, "mainClass"); - Constant* NameArray = Context.getConstantArray(name, true); + Constant* NameArray = ConstantArray::get(name, true); GvarArrayStr->setInitializer(NameArray); Value* Indices[2] = { JavaIntrinsics.constantZero, JavaIntrinsics.constantZero }; From nicolas.geoffray at lip6.fr Wed Jul 29 03:21:01 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 29 Jul 2009 10:21:01 -0000 Subject: [vmkit-commits] [vmkit] r77449 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907291021.n6TAL5IU019391@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jul 29 05:20:35 2009 New Revision: 77449 URL: http://llvm.org/viewvc/llvm-project?rev=77449&view=rev Log: Remove warnings. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=77449&r1=77448&r2=77449&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Wed Jul 29 05:20:35 2009 @@ -825,7 +825,6 @@ const StructType* STy = dyn_cast(JnjvmModule::JavaFieldType->getContainedType(0)); Module& Mod = *getLLVMModule(); - LLVMContext& Context = Mod.getContext(); std::vector FieldElts; std::vector TempElts; @@ -1217,7 +1216,6 @@ template Constant* JavaAOTCompiler::CreateConstantFromArray(const T* val, const Type* Ty) { Module& Mod = *getLLVMModule(); - LLVMContext& Context = Mod.getContext(); std::vector Elemts; const ArrayType* ATy = ArrayType::get(Ty, val->size); Elemts.push_back(JnjvmModule::JavaObjectType->getContainedType(0)); @@ -1253,8 +1251,6 @@ } Constant* JavaAOTCompiler::CreateConstantFromUTF8(const UTF8* val) { - Module& Mod = *getLLVMModule(); - LLVMContext& Context = Mod.getContext(); std::vector Elemts; const ArrayType* ATy = ArrayType::get(Type::Int16Ty, val->size); Elemts.push_back(JnjvmModule::pointerSizeType); @@ -1299,7 +1295,6 @@ Constant* JavaAOTCompiler::CreateConstantFromVT(JavaVirtualTable* VT) { Module& Mod = *getLLVMModule(); - LLVMContext& Context = Mod.getContext(); CommonClass* classDef = VT->cl; uint32 size = classDef->isClass() ? classDef->asClass()->virtualTableSize : JavaVirtualTable::getBaseSize(); @@ -1926,8 +1921,6 @@ } void JavaAOTCompiler::generateMain(const char* name, bool jit) { - Module& Mod = *getLLVMModule(); - LLVMContext& Context = Mod.getContext(); // Type Definitions std::vector FuncArgs; From nicolas.geoffray at lip6.fr Thu Jul 30 02:38:40 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 09:38:40 -0000 Subject: [vmkit-commits] [vmkit] r77588 - in /vmkit/trunk: include/mvm/Threads/Thread.h lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll lib/JnJVM/VMCore/JavaThread.cpp lib/JnJVM/VMCore/JavaThread.h lib/Mvm/CommonThread/ctlock.cpp lib/Mvm/CommonThread/ctthread.cpp lib/Mvm/GCMmap2/MvmGC.h lib/Mvm/GCMmap2/gc.cpp lib/Mvm/GCMmap2/gccollector.cpp lib/Mvm/GCMmap2/gcthread.cpp lib/Mvm/GCMmap2/gcthread.h lib/Mvm/Runtime/Object.cpp Message-ID: <200907300938.n6U9clZG017606@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 04:38:29 2009 New Revision: 77588 URL: http://llvm.org/viewvc/llvm-project?rev=77588&view=rev Log: Fully support a cooperative GC. Modified: vmkit/trunk/include/mvm/Threads/Thread.h vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h vmkit/trunk/lib/Mvm/Runtime/Object.cpp Modified: vmkit/trunk/include/mvm/Threads/Thread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Threads/Thread.h (original) +++ vmkit/trunk/include/mvm/Threads/Thread.h Thu Jul 30 04:38:29 2009 @@ -10,7 +10,7 @@ #ifndef MVM_THREAD_H #define MVM_THREAD_H -#include +#include #include "types.h" @@ -103,9 +103,7 @@ /// yield - Yield the processor to another thread. /// - static void yield(void) { - sched_yield(); - } + static void yield(void); /// kill - Kill the thread with the given pid by sending it a signal. /// @@ -143,6 +141,15 @@ /// bool doYield; + /// inGC - Flag to tell that the thread is being part of a GC. + /// + bool inGC; + + /// stackScanned - Flag to tell that the thread's stack has already + /// been analyzed. + /// + bool stackScanned; + /// get - Get the thread specific data of the current thread. /// static Thread* get() { @@ -151,6 +158,12 @@ private: + /// lastSP - If the thread is running native code that can not be + /// interrupted, lastSP is not null and contains the value of the + /// stack pointer before entering native. + /// + void* lastSP; + /// internalThreadID - The implementation specific thread id. /// void* internalThreadID; @@ -164,6 +177,10 @@ /// virtual void internalClearException() {} + /// joinCollection - Join a collection. + /// + void joinCollection(); + public: /// ~Thread - Give the class a home. @@ -174,6 +191,23 @@ /// a tracer. /// virtual void tracer() {} + + void* getLastSP() { return lastSP; } + void setLastSP(void* V) { lastSP = V; } + + void enterUncooperativeCode() { + if (isMvmThread()) { + lastSP = __builtin_frame_address(0); + if (doYield && !inGC) joinCollection(); + } + } + + void leaveUncooperativeCode() { + if (isMvmThread()) { + lastSP = 0; + if (doYield && !inGC) joinCollection(); + } + } /// clearException - Clear any pending exception of the current thread. @@ -181,10 +215,23 @@ internalClearException(); } + bool isMvmThread() { + if (!baseAddr) return false; + else return (((uintptr_t)this) & MvmThreadMask) == baseAddr; + } + + /// baseAddr - The base address for all threads. + static uintptr_t baseAddr; + /// IDMask - Apply this mask to the stack pointer to get the Thread object. /// static const uint64_t IDMask = 0x7FF00000; + /// MvmThreadMask - Apply this mask to verify that the current thread was + /// created by Mvm. + /// + static const uint64_t MvmThreadMask = 0xF0000000; + /// OverflowMask - Apply this mask to implement overflow checks. For /// efficiency, we lower the available size of the stack: it can never go /// under 0xC0000 Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Thu Jul 30 04:38:29 2009 @@ -199,9 +199,9 @@ OffsetIsolateInThreadConstant = ConstantInt::get(Type::Int32Ty, 3); OffsetDoYieldInThreadConstant = ConstantInt::get(Type::Int32Ty, 6); - OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 9); - OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 10); - OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 11); + OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 12); + OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 13); + OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 14); ClassReadyConstant = ConstantInt::get(Type::Int8Ty, ready); Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Thu Jul 30 04:38:29 2009 @@ -41,13 +41,16 @@ ;;; Field 4: MyVM ;;; Field 5: baseSP ;;; Field 6: doYield -;;; Field 7: internalThreadID -;;; field 8: routine -;;; field 9: jnienv -;;; field 10: Java pendingException -;;; field 11: CXX pendingException -%JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i1, i8*, - i8*, i8*, %JavaObject*, i8* } +;;; Field 7: inGC +;;; Field 8: stackScanned +;;; Field 9: lastSP +;;; Field 10: internalThreadID +;;; field 11: routine +;;; field 12: jnienv +;;; field 13: Java pendingException +;;; field 14: CXX pendingException +%JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i1, i1, + i1, i8*, i8*, i8*, i8*, %JavaObject*, i8* } %Attribut = type { %UTF8*, i32, i32 } Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Thu Jul 30 04:38:29 2009 @@ -103,6 +103,9 @@ assert((addresses.size() % 2) && "Wrong stack"); addresses.push_back(cur); + + // Start uncooperative mode. + enterUncooperativeCode(); } void JavaThread::startJava() { Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Thu Jul 30 04:38:29 2009 @@ -240,6 +240,9 @@ localJNIRefs->removeJNIReferences(this, *currentAddedReferences); addresses.pop_back(); + + // Go back to cooperative mode. + leaveUncooperativeCode(); } /// endJava - Record that we are leaving Java code. Modified: vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp (original) +++ vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp Thu Jul 30 04:38:29 2009 @@ -63,8 +63,11 @@ } void LockNormal::lock() { + Thread* th = Thread::get(); + th->enterUncooperativeCode(); pthread_mutex_lock((pthread_mutex_t*)&internalLock); - owner = mvm::Thread::get(); + th->leaveUncooperativeCode(); + owner = th; } void LockNormal::unlock() { @@ -75,8 +78,11 @@ void LockRecursive::lock() { if (!selfOwner()) { + Thread* th = Thread::get(); + th->enterUncooperativeCode(); pthread_mutex_lock((pthread_mutex_t*)&internalLock); - owner = mvm::Thread::get(); + th->leaveUncooperativeCode(); + owner = th; } ++n; } @@ -113,8 +119,11 @@ if (selfOwner()) { n += count; } else { + Thread* th = Thread::get(); + th->enterUncooperativeCode(); pthread_mutex_lock((pthread_mutex_t*)&internalLock); - owner = mvm::Thread::get(); + th->leaveUncooperativeCode(); + owner = th; n = count; } } @@ -136,8 +145,11 @@ int n = l->unsafeUnlock(); + Thread* th = Thread::get(); + th->enterUncooperativeCode(); int res = pthread_cond_wait((pthread_cond_t*)&internalCond, (pthread_mutex_t*)&(l->internalLock)); + th->leaveUncooperativeCode(); assert(!res && "Error on wait"); l->unsafeLock(n); @@ -158,9 +170,12 @@ int n = l->unsafeUnlock(); + Thread* th = Thread::get(); + th->enterUncooperativeCode(); int res = pthread_cond_timedwait((pthread_cond_t*)&internalCond, (pthread_mutex_t*)&(l->internalLock), &timeout); + th->leaveUncooperativeCode(); assert((!res || res == ETIMEDOUT) && "Error on timed wait"); l->unsafeLock(n); Modified: vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp (original) +++ vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp Thu Jul 30 04:38:29 2009 @@ -19,6 +19,7 @@ #include #include #include +#include #include using namespace mvm; @@ -35,6 +36,21 @@ pthread_exit((void*)value); } +void Thread::yield(void) { + Thread* th = mvm::Thread::get(); + if (th->isMvmThread()) { + if (th->doYield && !th->inGC) th->joinCollection(); + } + sched_yield(); +} + +void Thread::joinCollection() { + Collector::traceStackThread(); +} + + +uintptr_t Thread::baseAddr = 0; + // These could be set at runtime. #define STACK_SIZE 0x100000 #define NR_THREADS 255 @@ -91,6 +107,7 @@ memset((void*)used, 0, NR_THREADS * sizeof(uint32)); allocPtr = 0; + mvm::Thread::baseAddr = baseAddr; } uintptr_t allocate() { Modified: vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h Thu Jul 30 04:38:29 2009 @@ -81,6 +81,8 @@ static inline size_t real_nbb(GCChunkNode *n) { return n->nbb() - sizeof(gcRoot); } + + static void traceForeignThreadStack(mvm::Thread* th, void* endPtr); public: static GCThread *threads; /* le gestionnaire de thread et de synchro */ @@ -98,6 +100,10 @@ static int siggc(); + static void traceStackThread() { + siggc_handler(0); + } + static void inject_my_thread(mvm::Thread* th); static inline void remove_my_thread(mvm::Thread* th) { threads->remove(th); Modified: vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp Thu Jul 30 04:38:29 2009 @@ -39,16 +39,63 @@ void Collector::siggc_handler(int) { mvm::Thread* th = mvm::Thread::get(); + th->inGC = true; - jmp_buf buf; - setjmp(buf); Collector::threads->stackLock(); + + if (Collector::threads->cooperative && !th->doYield) { + // I was previously blocked, and I'm running late: someone else collected + // my stack, and the GC has finished already. Just unlock and return. + Collector::threads->stackUnlock(); + th->inGC = false; + return; + } + + // I woke up while a GC was happening, and no-one has collected my stack yet. + // Do it now. + if (!th->stackScanned) { + jmp_buf buf; + setjmp(buf); - if(!th) /* The thread is being destroyed */ - Collector::threads->another_mark(); - else { - register unsigned int **cur = (unsigned int**)(void*)&buf; + if(!th) /* The thread is being destroyed */ + Collector::threads->another_mark(); + else { + register unsigned int **cur = (unsigned int**)(void*)&buf; + register unsigned int **max = (unsigned int**)th->baseSP; + + GCChunkNode *node; + + for(; curremove(); + node->append(Collector::used_nodes); + Collector::mark(node); + } + } + + Collector::threads->another_mark(); + } + th->stackScanned = true; + } + + // Wait for the collection to finish. + Collector::threads->waitCollection(); + Collector::threads->stackUnlock(); + + // If the current thread is not the collector thread, this means that the + // collection is finished. Set inGC to false. + if(th != threads->getCurrentCollector()) + th->inGC = false; +} + +void Collector::traceForeignThreadStack(mvm::Thread* th, void* endPtr) { + Collector::threads->stackLock(); + + // The thread may have waken up during this GC. In this case, it may also + // have collected its stack. Don't scan it then. + if (!th->stackScanned) { + register unsigned int **cur = (unsigned int**)endPtr; register unsigned int **max = (unsigned int**)th->baseSP; GCChunkNode *node; @@ -60,9 +107,13 @@ Collector::mark(node); } } - Collector::threads->another_mark(); - Collector::threads->waitCollection(); + th->stackScanned = true; } + Collector::threads->stackUnlock(); } + +extern "C" void conditionalSafePoint() { + Collector::traceStackThread(); +} Modified: vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp Thu Jul 30 04:38:29 2009 @@ -46,6 +46,7 @@ mvm::Thread* th = mvm::Thread::get(); th->MyVM->startCollection(); + th->inGC = true; threads->synchronize(); @@ -103,6 +104,7 @@ next = cur->next(); allocator->reject_chunk(cur); } + th->inGC = false; } Modified: vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp Thu Jul 30 04:38:29 2009 @@ -20,18 +20,58 @@ } void GCThread::synchronize() { - int signo = Collector::siggc(); - mvm::Thread* self = mvm::Thread::get(); - assert(self && "No thread local data for this thread"); - current_collector = self; - _nb_collected = 0; - - for(mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self; - cur = (mvm::Thread*)cur->next()) { - cur->kill(signo); - } + + if (cooperative) { + mvm::Thread* self = mvm::Thread::get(); + assert(self && "No thread local data for this thread"); + current_collector = self; + _nb_collected = 0; + + // Lock stacks. Changes on the doYield flag of threads must be + // protected, as threads may wake up after being blocked in native code + // and join the collection. + stackLock(); + + mvm::Thread* cur = self; + do { + cur->stackScanned = false; + cur->doYield = true; + cur = (mvm::Thread*)cur->next(); + } while (cur != self); + + // Unlock now. Each running thread will scan its stack. + stackUnlock(); + + // Scan the stacks of currently blocked threads. + for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self; + cur = (mvm::Thread*)cur->next()) { + void* val = cur->getLastSP(); + // If val is null, this means that the thread woke up, and is + // joining the collection. We are sure the thread will scan its stack. + if (val) Collector::traceForeignThreadStack(cur, val); + } + + // Finally, scan my stack too! + Collector::siggc_handler(0); + + // And wait for other threads to finish. + waitStacks(); + } else { + int signo = Collector::siggc(); + mvm::Thread* self = mvm::Thread::get(); + self->stackScanned = false; + assert(self && "No thread local data for this thread"); + current_collector = self; + _nb_collected = 0; + + for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self; + cur = (mvm::Thread*)cur->next()) { + cur->stackScanned = false; + cur->kill(signo); + } - Collector::siggc_handler(signo); + Collector::siggc_handler(signo); - waitStacks(); + waitStacks(); + } } Modified: vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h Thu Jul 30 04:38:29 2009 @@ -42,12 +42,18 @@ public: mvm::Thread* base; - + bool cooperative; + + mvm::Thread* getCurrentCollector() { + return current_collector; + } + GCThread() { _nb_threads = 0; _nb_collected = 0; current_collector = 0; base = 0; + cooperative = false; } inline unsigned int get_nb_threads() { @@ -61,7 +67,25 @@ void waitStacks(); void waitCollection(); - inline void collectionFinished() { _collectionCond.broadcast(); } + + inline void collectionFinished() { + if (cooperative) { + // We lock here to make sure no previously blocked in native threads + // will join the collection and never go back to running code. + stackLock(); + mvm::Thread* cur = current_collector; + do { + cur->doYield = false; + cur = (mvm::Thread*)cur->next(); + } while (cur != current_collector); + _collectionCond.broadcast(); + stackUnlock(); + } else { + _collectionCond.broadcast(); + } + current_collector->inGC = false; + } + inline void collectorGo() { _stackCond.broadcast(); } inline void cancel() { Modified: vmkit/trunk/lib/Mvm/Runtime/Object.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Runtime/Object.cpp?rev=77588&r1=77587&r2=77588&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Runtime/Object.cpp (original) +++ vmkit/trunk/lib/Mvm/Runtime/Object.cpp Thu Jul 30 04:38:29 2009 @@ -119,6 +119,8 @@ void VirtualMachine::finalizerStart(mvm::Thread* th) { VirtualMachine* vm = th->MyVM; + gc* res = 0; + llvm_gcroot(res, 0); while (true) { vm->FinalizationLock.lock(); @@ -129,7 +131,6 @@ while (true) { vm->FinalizationQueueLock.acquire(); - gc* res = 0; if (vm->CurrentFinalizedIndex != 0) { res = vm->ToBeFinalized[--vm->CurrentFinalizedIndex]; } @@ -146,6 +147,7 @@ } } catch(...) { } + res = 0; th->clearException(); } } @@ -153,6 +155,8 @@ void VirtualMachine::enqueueStart(mvm::Thread* th) { VirtualMachine* vm = th->MyVM; + gc* res = 0; + llvm_gcroot(res, 0); while (true) { vm->EnqueueLock.lock(); @@ -163,7 +167,6 @@ while (true) { vm->ToEnqueueLock.acquire(); - gc* res = 0; if (vm->ToEnqueueIndex != 0) { res = vm->ToEnqueue[--vm->ToEnqueueIndex]; } @@ -174,6 +177,7 @@ vm->enqueueReference(res); } catch(...) { } + res = 0; th->clearException(); } } @@ -307,9 +311,3 @@ void Allocator::freeTemporaryMemory(void* obj) { return free(obj); } - - - -extern "C" void conditionalSafePoint() { - abort(); -} From nicolas.geoffray at lip6.fr Thu Jul 30 04:33:06 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 11:33:06 -0000 Subject: [vmkit-commits] [vmkit] r77590 - /vmkit/trunk/tools/llcj/llcj.cpp Message-ID: <200907301133.n6UBXAZT022632@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 06:32:48 2009 New Revision: 77590 URL: http://llvm.org/viewvc/llvm-project?rev=77590&view=rev Log: LLVMSupport needs LLVMSystem. Modified: vmkit/trunk/tools/llcj/llcj.cpp Modified: vmkit/trunk/tools/llcj/llcj.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/tools/llcj/llcj.cpp?rev=77590&r1=77589&r2=77590&view=diff ============================================================================== --- vmkit/trunk/tools/llcj/llcj.cpp (original) +++ vmkit/trunk/tools/llcj/llcj.cpp Thu Jul 30 06:32:48 2009 @@ -231,6 +231,7 @@ gccArgv[gccArgc++] = "-lGCMmap2"; gccArgv[gccArgc++] = "-lvmjc"; gccArgv[gccArgc++] = "-lLLVMSupport"; + gccArgv[gccArgc++] = "-lLLVMSystem"; #if !defined(__MACH__) gccArgv[gccArgc++] = "-rdynamic"; #endif From nicolas.geoffray at lip6.fr Thu Jul 30 04:44:06 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 11:44:06 -0000 Subject: [vmkit-commits] [vmkit] r77591 - /vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Message-ID: <200907301144.n6UBiA17023190@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 06:43:49 2009 New Revision: 77591 URL: http://llvm.org/viewvc/llvm-project?rev=77591&view=rev Log: Also be in uncooperative code when locking on the JIT lock. Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77591&r1=77590&r2=77591&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Thu Jul 30 06:43:49 2009 @@ -301,7 +301,12 @@ // We protect the creation of IR with the executionEngine lock because // codegen'ing a function may also create IR objects. void MvmModule::protectIR() { - if (executionEngine) executionEngine->lock.acquire(); + if (executionEngine) { + mvm::Thread* th = mvm::Thread::get(); + th->enterUncooperativeCode(); + executionEngine->lock.acquire(); + th->leaveUncooperativeCode(); + } } void MvmModule::unprotectIR() { From nicolas.geoffray at lip6.fr Thu Jul 30 05:21:24 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 12:21:24 -0000 Subject: [vmkit-commits] [vmkit] r77592 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907301221.n6UCLPmw025110@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 07:21:22 2009 New Revision: 77592 URL: http://llvm.org/viewvc/llvm-project?rev=77592&view=rev Log: Also compile inner classes. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=77592&r1=77591&r2=77592&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Thu Jul 30 07:21:22 2009 @@ -1851,6 +1851,11 @@ } cl->setOwnerClass(JavaThread::get()); + cl->resolveInnerOuterClasses(); + for (uint32 i = 0; i < cl->nbInnerClasses; ++i) { + cl->innerClasses[i]->setOwnerClass(JavaThread::get()); + M->compileClass(cl->innerClasses[i]); + } M->compileClass(cl); } From nicolas.geoffray at lip6.fr Thu Jul 30 05:23:55 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 12:23:55 -0000 Subject: [vmkit-commits] [vmkit] r77593 - in /vmkit/trunk: include/mvm/Threads/Thread.h lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll lib/Mvm/CommonThread/ctthread.cpp lib/Mvm/Compiler/JIT.cpp Message-ID: <200907301223.n6UCNtsC025327@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 07:23:55 2009 New Revision: 77593 URL: http://llvm.org/viewvc/llvm-project?rev=77593&view=rev Log: Release JIT lock when entering GC. Because we don't want compile-time dependency with the JIT, we use a function pointer, stored in the thread class. Modified: vmkit/trunk/include/mvm/Threads/Thread.h vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/include/mvm/Threads/Thread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=77593&r1=77592&r2=77593&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Threads/Thread.h (original) +++ vmkit/trunk/include/mvm/Threads/Thread.h Thu Jul 30 07:23:55 2009 @@ -250,7 +250,12 @@ /// routine - The function to invoke when the thread starts. /// void (*routine)(mvm::Thread*); - + + /// releaseJIT - Function to release any locks held while we are trying to + /// join a collection. + /// + void (*releaseJIT)(bool); + #ifdef SERVICE /// stoppingService - The service that is currently stopping. /// Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77593&r1=77592&r2=77593&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Thu Jul 30 07:23:55 2009 @@ -199,9 +199,9 @@ OffsetIsolateInThreadConstant = ConstantInt::get(Type::Int32Ty, 3); OffsetDoYieldInThreadConstant = ConstantInt::get(Type::Int32Ty, 6); - OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 12); - OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 13); - OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 14); + OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 13); + OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 14); + OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 15); ClassReadyConstant = ConstantInt::get(Type::Int8Ty, ready); Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=77593&r1=77592&r2=77593&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Thu Jul 30 07:23:55 2009 @@ -46,11 +46,12 @@ ;;; Field 9: lastSP ;;; Field 10: internalThreadID ;;; field 11: routine -;;; field 12: jnienv -;;; field 13: Java pendingException -;;; field 14: CXX pendingException +;;; field 12: releaseJIT +;;; field 13: jnienv +;;; field 14: Java pendingException +;;; field 15: CXX pendingException %JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i1, i1, - i1, i8*, i8*, i8*, i8*, %JavaObject*, i8* } + i1, i8*, i8*, i8*, i8*, i8*, %JavaObject*, i8* } %Attribut = type { %UTF8*, i32, i32 } Modified: vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp?rev=77593&r1=77592&r2=77593&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp (original) +++ vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp Thu Jul 30 07:23:55 2009 @@ -45,7 +45,9 @@ } void Thread::joinCollection() { + if (releaseJIT) releaseJIT(false); Collector::traceStackThread(); + if (releaseJIT) releaseJIT(true); } Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77593&r1=77592&r2=77593&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Thu Jul 30 07:23:55 2009 @@ -298,6 +298,13 @@ } +static void releaseJIT(bool goBack) { + if (MvmModule::executionEngine) { + if (goBack) MvmModule::executionEngine->lock.acquire(); + else MvmModule::executionEngine->lock.release(); + } +} + // We protect the creation of IR with the executionEngine lock because // codegen'ing a function may also create IR objects. void MvmModule::protectIR() { @@ -306,11 +313,14 @@ th->enterUncooperativeCode(); executionEngine->lock.acquire(); th->leaveUncooperativeCode(); + if (th->isMvmThread()) th->releaseJIT = releaseJIT; } } void MvmModule::unprotectIR() { if (executionEngine) executionEngine->lock.release(); + Thread* th = Thread::get(); + if (th->isMvmThread()) th->releaseJIT = releaseJIT; } From nicolas.geoffray at lip6.fr Thu Jul 30 05:57:54 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 12:57:54 -0000 Subject: [vmkit-commits] [vmkit] r77594 - in /vmkit/trunk: include/mvm/JIT.h lib/JnJVM/Compiler/JITInfo.cpp lib/JnJVM/Compiler/JavaJITCompiler.cpp lib/JnJVM/Compiler/JnjvmModule.cpp lib/Mvm/Compiler/JIT.cpp Message-ID: <200907301257.n6UCvvum026874@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 07:57:45 2009 New Revision: 77594 URL: http://llvm.org/viewvc/llvm-project?rev=77594&view=rev Log: Avoid recursively locking the JIT lock. Modified: vmkit/trunk/include/mvm/JIT.h vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/include/mvm/JIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=77594&r1=77593&r2=77594&view=diff ============================================================================== --- vmkit/trunk/include/mvm/JIT.h (original) +++ vmkit/trunk/include/mvm/JIT.h Thu Jul 30 07:57:45 2009 @@ -183,7 +183,7 @@ static int disassemble(unsigned int* addr); - static void protectIR(); + static bool protectIR(); static void unprotectIR(); static void copyDefinitions(llvm::Module* Dst, llvm::Module* Src); Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=77594&r1=77593&r2=77594&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Thu Jul 30 07:57:45 2009 @@ -214,7 +214,7 @@ const llvm::FunctionType* LLVMSignatureInfo::getVirtualType() { if (!virtualType) { // Lock here because we are called by arbitrary code - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); std::vector llvmArgs; uint32 size = signature->nbArguments; Typedef* const* arguments = signature->getArgumentsType(); @@ -234,7 +234,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); virtualType = FunctionType::get(LAI.llvmType, llvmArgs, false); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); } return virtualType; } @@ -242,7 +242,7 @@ const llvm::FunctionType* LLVMSignatureInfo::getStaticType() { if (!staticType) { // Lock here because we are called by arbitrary code - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); std::vector llvmArgs; uint32 size = signature->nbArguments; Typedef* const* arguments = signature->getArgumentsType(); @@ -260,7 +260,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); staticType = FunctionType::get(LAI.llvmType, llvmArgs, false); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); } return staticType; } @@ -268,7 +268,7 @@ const llvm::FunctionType* LLVMSignatureInfo::getNativeType() { if (!nativeType) { // Lock here because we are called by arbitrary code - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); std::vector llvmArgs; uint32 size = signature->nbArguments; Typedef* const* arguments = signature->getArgumentsType(); @@ -298,7 +298,7 @@ const llvm::Type* RetType = LAI.llvmType == JnjvmModule::JavaObjectType ? LAI.llvmTypePtr : LAI.llvmType; nativeType = FunctionType::get(RetType, llvmArgs, false); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); } return nativeType; } @@ -447,7 +447,7 @@ const FunctionType* LLVMSignatureInfo::getVirtualBufType() { if (!virtualBufType) { // Lock here because we are called by arbitrary code - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); std::vector Args2; Args2.push_back(JnjvmModule::ConstantPoolType); // ctp Args2.push_back(getVirtualPtrType()); @@ -456,7 +456,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); virtualBufType = FunctionType::get(LAI.llvmType, Args2, false); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); } return virtualBufType; } @@ -464,7 +464,7 @@ const FunctionType* LLVMSignatureInfo::getStaticBufType() { if (!staticBufType) { // Lock here because we are called by arbitrary code - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); std::vector Args; Args.push_back(JnjvmModule::ConstantPoolType); // ctp Args.push_back(getStaticPtrType()); @@ -472,7 +472,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); staticBufType = FunctionType::get(LAI.llvmType, Args, false); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); } return staticBufType; } @@ -480,7 +480,7 @@ Function* LLVMSignatureInfo::getVirtualBuf() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on virtualBufFunction to have an address. - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); if (!virtualBufFunction) { virtualBufFunction = createFunctionCallBuf(true); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -490,14 +490,14 @@ virtualBufFunction->deleteBody(); } } - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); return virtualBufFunction; } Function* LLVMSignatureInfo::getVirtualAP() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on virtualAPFunction to have an address. - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); if (!virtualAPFunction) { virtualAPFunction = createFunctionCallAP(true); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -507,14 +507,14 @@ virtualAPFunction->deleteBody(); } } - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); return virtualAPFunction; } Function* LLVMSignatureInfo::getStaticBuf() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on staticBufFunction to have an address. - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); if (!staticBufFunction) { staticBufFunction = createFunctionCallBuf(false); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -524,14 +524,14 @@ staticBufFunction->deleteBody(); } } - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); return staticBufFunction; } Function* LLVMSignatureInfo::getStaticAP() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on staticAPFunction to have an address. - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); if (!staticAPFunction) { staticAPFunction = createFunctionCallAP(false); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -541,7 +541,7 @@ staticAPFunction->deleteBody(); } } - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); return staticAPFunction; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=77594&r1=77593&r2=77594&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Thu Jul 30 07:57:45 2009 @@ -209,10 +209,10 @@ void* JavaJITCompiler::materializeFunction(JavaMethod* meth) { Function* func = parseFunction(meth); - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); void* res = mvm::MvmModule::executionEngine->getPointerToGlobal(func); func->deleteBody(); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); return res; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77594&r1=77593&r2=77594&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Thu Jul 30 07:57:45 2009 @@ -72,18 +72,18 @@ void JavaLLVMCompiler::resolveVirtualClass(Class* cl) { // Lock here because we may be called by a class resolver - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl); LCI->getVirtualType(); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); } void JavaLLVMCompiler::resolveStaticClass(Class* cl) { // Lock here because we may be called by a class initializer - mvm::MvmModule::protectIR(); + bool un = mvm::MvmModule::protectIR(); LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl); LCI->getStaticType(); - mvm::MvmModule::unprotectIR(); + if (un) mvm::MvmModule::unprotectIR(); } @@ -332,7 +332,7 @@ Function* func = LMI->getMethod(); if (func->hasNotBeenReadFromBitcode()) { // We are jitting. Take the lock. - JnjvmModule::protectIR(); + bool un = JnjvmModule::protectIR(); if (func->hasNotBeenReadFromBitcode()) { JavaJIT jit(this, meth, func); if (isNative(meth->access)) { @@ -344,7 +344,7 @@ JnjvmModule::runPasses(func, JavaFunctionPasses); } } - JnjvmModule::unprotectIR(); + if (un) JnjvmModule::unprotectIR(); } return func; } Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77594&r1=77593&r2=77594&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Thu Jul 30 07:57:45 2009 @@ -307,14 +307,19 @@ // We protect the creation of IR with the executionEngine lock because // codegen'ing a function may also create IR objects. -void MvmModule::protectIR() { +bool MvmModule::protectIR() { if (executionEngine) { mvm::Thread* th = mvm::Thread::get(); + + // If we already own the lock, don't lock it again. + if (th->isMvmThread() && th->releaseJIT) return false; + th->enterUncooperativeCode(); executionEngine->lock.acquire(); th->leaveUncooperativeCode(); if (th->isMvmThread()) th->releaseJIT = releaseJIT; } + return true; } void MvmModule::unprotectIR() { From nicolas.geoffray at lip6.fr Thu Jul 30 06:18:18 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 13:18:18 -0000 Subject: [vmkit-commits] [vmkit] r77595 - in /vmkit/trunk: include/mvm/JIT.h lib/JnJVM/Compiler/JnjvmModuleProvider.cpp lib/Mvm/Compiler/JIT.cpp Message-ID: <200907301318.n6UDIJG1027940@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 08:18:13 2009 New Revision: 77595 URL: http://llvm.org/viewvc/llvm-project?rev=77595&view=rev Log: When entering JnjvmModuleProvider::materializeFunction, the JIT lock must be held. Modified: vmkit/trunk/include/mvm/JIT.h vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/include/mvm/JIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=77595&r1=77594&r2=77595&view=diff ============================================================================== --- vmkit/trunk/include/mvm/JIT.h (original) +++ vmkit/trunk/include/mvm/JIT.h Thu Jul 30 08:18:13 2009 @@ -191,6 +191,8 @@ static void AddStandardCompilePasses(); static const char* getHostTriple(); + + static void releaseJITAfterGC(bool); }; } // end namespace mvm Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp?rev=77595&r1=77594&r2=77595&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp Thu Jul 30 08:18:13 2009 @@ -92,7 +92,11 @@ bool JnjvmModuleProvider::materializeFunction(Function *F, std::string *ErrInfo) { - + + // When the thread enters here, it _must_ hold the JIT lock. + mvm::Thread* th = mvm::Thread::get(); + th->releaseJIT = mvm::MvmModule::releaseJITAfterGC; + if (!(F->hasNotBeenReadFromBitcode())) return false; Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77595&r1=77594&r2=77595&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Thu Jul 30 08:18:13 2009 @@ -298,7 +298,7 @@ } -static void releaseJIT(bool goBack) { +void MvmModule::releaseJITAfterGC(bool goBack) { if (MvmModule::executionEngine) { if (goBack) MvmModule::executionEngine->lock.acquire(); else MvmModule::executionEngine->lock.release(); @@ -317,7 +317,7 @@ th->enterUncooperativeCode(); executionEngine->lock.acquire(); th->leaveUncooperativeCode(); - if (th->isMvmThread()) th->releaseJIT = releaseJIT; + if (th->isMvmThread()) th->releaseJIT = releaseJITAfterGC; } return true; } @@ -325,7 +325,7 @@ void MvmModule::unprotectIR() { if (executionEngine) executionEngine->lock.release(); Thread* th = Thread::get(); - if (th->isMvmThread()) th->releaseJIT = releaseJIT; + if (th->isMvmThread()) th->releaseJIT = 0; } From nicolas.geoffray at lip6.fr Thu Jul 30 06:25:03 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 13:25:03 -0000 Subject: [vmkit-commits] [vmkit] r77596 - /vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp Message-ID: <200907301325.n6UDP3qh028170@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 08:25:01 2009 New Revision: 77596 URL: http://llvm.org/viewvc/llvm-project?rev=77596&view=rev Log: Don't forget to put back releaseJIT to 0. Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp?rev=77596&r1=77595&r2=77596&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp Thu Jul 30 08:25:01 2009 @@ -97,11 +97,15 @@ mvm::Thread* th = mvm::Thread::get(); th->releaseJIT = mvm::MvmModule::releaseJITAfterGC; - if (!(F->hasNotBeenReadFromBitcode())) + if (!(F->hasNotBeenReadFromBitcode())) { + th->releaseJIT = 0; return false; + } - if (mvm::MvmModule::executionEngine->getPointerToGlobalIfAvailable(F)) + if (mvm::MvmModule::executionEngine->getPointerToGlobalIfAvailable(F)) { + th->releaseJIT = 0; return false; + } JavaMethod* meth = LLVMMethodInfo::get(F); @@ -131,6 +135,7 @@ assert(meth->classDef->isInitializing() && "Class not ready"); } + th->releaseJIT = 0; return false; } From nicolas.geoffray at lip6.fr Thu Jul 30 09:22:42 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 30 Jul 2009 16:22:42 -0000 Subject: [vmkit-commits] [vmkit] r77600 - in /vmkit/trunk: include/mvm/JIT.h include/mvm/Threads/Thread.h lib/JnJVM/Compiler/JITInfo.cpp lib/JnJVM/Compiler/JavaJITCompiler.cpp lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/Compiler/JnjvmModuleProvider.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll lib/Mvm/CommonThread/ctthread.cpp lib/Mvm/Compiler/JIT.cpp Message-ID: <200907301622.n6UGMkAF004570@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jul 30 11:22:24 2009 New Revision: 77600 URL: http://llvm.org/viewvc/llvm-project?rev=77600&view=rev Log: Revert to 77592, releasing the JIT lock before collecting was a stupid idea. Modified: vmkit/trunk/include/mvm/JIT.h vmkit/trunk/include/mvm/Threads/Thread.h vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Modified: vmkit/trunk/include/mvm/JIT.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/include/mvm/JIT.h (original) +++ vmkit/trunk/include/mvm/JIT.h Thu Jul 30 11:22:24 2009 @@ -183,7 +183,7 @@ static int disassemble(unsigned int* addr); - static bool protectIR(); + static void protectIR(); static void unprotectIR(); static void copyDefinitions(llvm::Module* Dst, llvm::Module* Src); @@ -191,8 +191,6 @@ static void AddStandardCompilePasses(); static const char* getHostTriple(); - - static void releaseJITAfterGC(bool); }; } // end namespace mvm Modified: vmkit/trunk/include/mvm/Threads/Thread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Threads/Thread.h (original) +++ vmkit/trunk/include/mvm/Threads/Thread.h Thu Jul 30 11:22:24 2009 @@ -250,12 +250,7 @@ /// routine - The function to invoke when the thread starts. /// void (*routine)(mvm::Thread*); - - /// releaseJIT - Function to release any locks held while we are trying to - /// join a collection. - /// - void (*releaseJIT)(bool); - + #ifdef SERVICE /// stoppingService - The service that is currently stopping. /// Modified: vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JITInfo.cpp Thu Jul 30 11:22:24 2009 @@ -214,7 +214,7 @@ const llvm::FunctionType* LLVMSignatureInfo::getVirtualType() { if (!virtualType) { // Lock here because we are called by arbitrary code - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); std::vector llvmArgs; uint32 size = signature->nbArguments; Typedef* const* arguments = signature->getArgumentsType(); @@ -234,7 +234,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); virtualType = FunctionType::get(LAI.llvmType, llvmArgs, false); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); } return virtualType; } @@ -242,7 +242,7 @@ const llvm::FunctionType* LLVMSignatureInfo::getStaticType() { if (!staticType) { // Lock here because we are called by arbitrary code - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); std::vector llvmArgs; uint32 size = signature->nbArguments; Typedef* const* arguments = signature->getArgumentsType(); @@ -260,7 +260,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); staticType = FunctionType::get(LAI.llvmType, llvmArgs, false); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); } return staticType; } @@ -268,7 +268,7 @@ const llvm::FunctionType* LLVMSignatureInfo::getNativeType() { if (!nativeType) { // Lock here because we are called by arbitrary code - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); std::vector llvmArgs; uint32 size = signature->nbArguments; Typedef* const* arguments = signature->getArgumentsType(); @@ -298,7 +298,7 @@ const llvm::Type* RetType = LAI.llvmType == JnjvmModule::JavaObjectType ? LAI.llvmTypePtr : LAI.llvmType; nativeType = FunctionType::get(RetType, llvmArgs, false); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); } return nativeType; } @@ -447,7 +447,7 @@ const FunctionType* LLVMSignatureInfo::getVirtualBufType() { if (!virtualBufType) { // Lock here because we are called by arbitrary code - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); std::vector Args2; Args2.push_back(JnjvmModule::ConstantPoolType); // ctp Args2.push_back(getVirtualPtrType()); @@ -456,7 +456,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); virtualBufType = FunctionType::get(LAI.llvmType, Args2, false); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); } return virtualBufType; } @@ -464,7 +464,7 @@ const FunctionType* LLVMSignatureInfo::getStaticBufType() { if (!staticBufType) { // Lock here because we are called by arbitrary code - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); std::vector Args; Args.push_back(JnjvmModule::ConstantPoolType); // ctp Args.push_back(getStaticPtrType()); @@ -472,7 +472,7 @@ LLVMAssessorInfo& LAI = JavaLLVMCompiler::getTypedefInfo(signature->getReturnType()); staticBufType = FunctionType::get(LAI.llvmType, Args, false); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); } return staticBufType; } @@ -480,7 +480,7 @@ Function* LLVMSignatureInfo::getVirtualBuf() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on virtualBufFunction to have an address. - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); if (!virtualBufFunction) { virtualBufFunction = createFunctionCallBuf(true); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -490,14 +490,14 @@ virtualBufFunction->deleteBody(); } } - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); return virtualBufFunction; } Function* LLVMSignatureInfo::getVirtualAP() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on virtualAPFunction to have an address. - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); if (!virtualAPFunction) { virtualAPFunction = createFunctionCallAP(true); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -507,14 +507,14 @@ virtualAPFunction->deleteBody(); } } - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); return virtualAPFunction; } Function* LLVMSignatureInfo::getStaticBuf() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on staticBufFunction to have an address. - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); if (!staticBufFunction) { staticBufFunction = createFunctionCallBuf(false); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -524,14 +524,14 @@ staticBufFunction->deleteBody(); } } - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); return staticBufFunction; } Function* LLVMSignatureInfo::getStaticAP() { // Lock here because we are called by arbitrary code. Also put that here // because we are waiting on staticAPFunction to have an address. - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); if (!staticAPFunction) { staticAPFunction = createFunctionCallAP(false); if (!signature->initialLoader->getCompiler()->isStaticCompiling()) { @@ -541,7 +541,7 @@ staticAPFunction->deleteBody(); } } - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); return staticAPFunction; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Thu Jul 30 11:22:24 2009 @@ -209,10 +209,10 @@ void* JavaJITCompiler::materializeFunction(JavaMethod* meth) { Function* func = parseFunction(meth); - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); void* res = mvm::MvmModule::executionEngine->getPointerToGlobal(func); func->deleteBody(); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); return res; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Thu Jul 30 11:22:24 2009 @@ -72,18 +72,18 @@ void JavaLLVMCompiler::resolveVirtualClass(Class* cl) { // Lock here because we may be called by a class resolver - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl); LCI->getVirtualType(); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); } void JavaLLVMCompiler::resolveStaticClass(Class* cl) { // Lock here because we may be called by a class initializer - bool un = mvm::MvmModule::protectIR(); + mvm::MvmModule::protectIR(); LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl); LCI->getStaticType(); - if (un) mvm::MvmModule::unprotectIR(); + mvm::MvmModule::unprotectIR(); } @@ -199,9 +199,9 @@ OffsetIsolateInThreadConstant = ConstantInt::get(Type::Int32Ty, 3); OffsetDoYieldInThreadConstant = ConstantInt::get(Type::Int32Ty, 6); - OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 13); - OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 14); - OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 15); + OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 12); + OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 13); + OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 14); ClassReadyConstant = ConstantInt::get(Type::Int8Ty, ready); @@ -332,7 +332,7 @@ Function* func = LMI->getMethod(); if (func->hasNotBeenReadFromBitcode()) { // We are jitting. Take the lock. - bool un = JnjvmModule::protectIR(); + JnjvmModule::protectIR(); if (func->hasNotBeenReadFromBitcode()) { JavaJIT jit(this, meth, func); if (isNative(meth->access)) { @@ -344,7 +344,7 @@ JnjvmModule::runPasses(func, JavaFunctionPasses); } } - if (un) JnjvmModule::unprotectIR(); + JnjvmModule::unprotectIR(); } return func; } Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModuleProvider.cpp Thu Jul 30 11:22:24 2009 @@ -92,20 +92,12 @@ bool JnjvmModuleProvider::materializeFunction(Function *F, std::string *ErrInfo) { - - // When the thread enters here, it _must_ hold the JIT lock. - mvm::Thread* th = mvm::Thread::get(); - th->releaseJIT = mvm::MvmModule::releaseJITAfterGC; - - if (!(F->hasNotBeenReadFromBitcode())) { - th->releaseJIT = 0; + + if (!(F->hasNotBeenReadFromBitcode())) return false; - } - if (mvm::MvmModule::executionEngine->getPointerToGlobalIfAvailable(F)) { - th->releaseJIT = 0; + if (mvm::MvmModule::executionEngine->getPointerToGlobalIfAvailable(F)) return false; - } JavaMethod* meth = LLVMMethodInfo::get(F); @@ -135,7 +127,6 @@ assert(meth->classDef->isInitializing() && "Class not ready"); } - th->releaseJIT = 0; return false; } Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Thu Jul 30 11:22:24 2009 @@ -46,12 +46,11 @@ ;;; Field 9: lastSP ;;; Field 10: internalThreadID ;;; field 11: routine -;;; field 12: releaseJIT -;;; field 13: jnienv -;;; field 14: Java pendingException -;;; field 15: CXX pendingException +;;; field 12: jnienv +;;; field 13: Java pendingException +;;; field 14: CXX pendingException %JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i1, i1, - i1, i8*, i8*, i8*, i8*, i8*, %JavaObject*, i8* } + i1, i8*, i8*, i8*, i8*, %JavaObject*, i8* } %Attribut = type { %UTF8*, i32, i32 } Modified: vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp (original) +++ vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp Thu Jul 30 11:22:24 2009 @@ -45,9 +45,7 @@ } void Thread::joinCollection() { - if (releaseJIT) releaseJIT(false); Collector::traceStackThread(); - if (releaseJIT) releaseJIT(true); } Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=77600&r1=77599&r2=77600&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original) +++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Thu Jul 30 11:22:24 2009 @@ -298,34 +298,19 @@ } -void MvmModule::releaseJITAfterGC(bool goBack) { - if (MvmModule::executionEngine) { - if (goBack) MvmModule::executionEngine->lock.acquire(); - else MvmModule::executionEngine->lock.release(); - } -} - // We protect the creation of IR with the executionEngine lock because // codegen'ing a function may also create IR objects. -bool MvmModule::protectIR() { +void MvmModule::protectIR() { if (executionEngine) { mvm::Thread* th = mvm::Thread::get(); - - // If we already own the lock, don't lock it again. - if (th->isMvmThread() && th->releaseJIT) return false; - th->enterUncooperativeCode(); executionEngine->lock.acquire(); th->leaveUncooperativeCode(); - if (th->isMvmThread()) th->releaseJIT = releaseJITAfterGC; } - return true; } void MvmModule::unprotectIR() { if (executionEngine) executionEngine->lock.release(); - Thread* th = Thread::get(); - if (th->isMvmThread()) th->releaseJIT = 0; } From nicolas.geoffray at lip6.fr Fri Jul 31 01:10:52 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Fri, 31 Jul 2009 08:10:52 -0000 Subject: [vmkit-commits] [vmkit] r77669 - /vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Message-ID: <200907310810.n6V8Ar3m020209@zion.cs.uiuc.edu> Author: geoffray Date: Fri Jul 31 03:10:35 2009 New Revision: 77669 URL: http://llvm.org/viewvc/llvm-project?rev=77669&view=rev Log: Also parse zip files into zip files. Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=77669&r1=77668&r2=77669&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Fri Jul 31 03:10:35 2009 @@ -1698,6 +1698,49 @@ } } + + +static void extractFiles(ArrayUInt8* bytes, + JavaAOTCompiler* M, + JnjvmBootstrapLoader* bootstrapLoader, + std::vector& classes) { + + ZipArchive archive(bytes, bootstrapLoader->allocator); + + char* realName = (char*)alloca(4096); + for (ZipArchive::table_iterator i = archive.filetable.begin(), + e = archive.filetable.end(); i != e; ++i) { + ZipFile* file = i->second; + + char* name = file->filename; + uint32 size = strlen(name); + if (size > 6 && !strcmp(&(name[size - 6]), ".class")) { + UserClassArray* array = bootstrapLoader->upcalls->ArrayOfByte; + ArrayUInt8* res = + (ArrayUInt8*)array->doNew(file->ucsize, bootstrapLoader->allocator); + int ok = archive.readFile(res, file); + if (!ok) return; + + memcpy(realName, name, size); + realName[size - 6] = 0; + const UTF8* utf8 = bootstrapLoader->asciizConstructUTF8(realName); + Class* cl = bootstrapLoader->constructClass(utf8, res); + if (cl == ClassArray::SuperArray) M->compileRT = true; + classes.push_back(cl); + } else if (size > 4 && (!strcmp(&name[size - 4], ".jar") || + !strcmp(&name[size - 4], ".zip"))) { + UserClassArray* array = bootstrapLoader->upcalls->ArrayOfByte; + ArrayUInt8* res = + (ArrayUInt8*)array->doNew(file->ucsize, bootstrapLoader->allocator); + int ok = archive.readFile(res, file); + if (!ok) return; + + extractFiles(res, M, bootstrapLoader, classes); + } + } +} + + static const char* name; void mainCompilerStart(JavaThread* th) { @@ -1723,40 +1766,16 @@ if (size > 4 && (!strcmp(&name[size - 4], ".jar") || !strcmp(&name[size - 4], ".zip"))) { - std::vector classes; - ArrayUInt8* bytes = Reader::openFile(bootstrapLoader, name); + if (!bytes) { fprintf(stderr, "Can't find zip file.\n"); goto end; } - ZipArchive archive(bytes, bootstrapLoader->allocator); - - char* realName = (char*)alloca(4096); - for (ZipArchive::table_iterator i = archive.filetable.begin(), - e = archive.filetable.end(); i != e; ++i) { - ZipFile* file = i->second; - - size = strlen(file->filename); - if (size > 6 && !strcmp(&(file->filename[size - 6]), ".class")) { - UserClassArray* array = bootstrapLoader->upcalls->ArrayOfByte; - ArrayUInt8* res = - (ArrayUInt8*)array->doNew(file->ucsize, bootstrapLoader->allocator); - int ok = archive.readFile(res, file); - if (!ok) { - fprintf(stderr, "Wrong zip file.\n"); - goto end; - } - - memcpy(realName, file->filename, size); - realName[size - 6] = 0; - const UTF8* utf8 = bootstrapLoader->asciizConstructUTF8(realName); - Class* cl = bootstrapLoader->constructClass(utf8, res); - if (cl == ClassArray::SuperArray) M->compileRT = true; - classes.push_back(cl); - } - } + + extractFiles(bytes, M, bootstrapLoader, classes); + // First resolve everyone so that there can not be unknown references in // constant pools. From nicolas.geoffray at lip6.fr Fri Jul 31 01:12:24 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Fri, 31 Jul 2009 08:12:24 -0000 Subject: [vmkit-commits] [vmkit] r77670 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h lib/JnJVM/Classpath/ClasspathVMRuntime.inc lib/JnJVM/Compiler/JavaJIT.cpp lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll lib/JnJVM/VMCore/JavaRuntimeJIT.cpp lib/JnJVM/VMCore/LinkJavaRuntime.h Message-ID: <200907310812.n6V8CPG9020289@zion.cs.uiuc.edu> Author: geoffray Date: Fri Jul 31 03:12:19 2009 New Revision: 77670 URL: http://llvm.org/viewvc/llvm-project?rev=77670&view=rev Log: Rename jnjvmJniProceedPendingException and jnjvmGetSjljBuffer to something more accurate of what they're actually doing. Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=77670&r1=77669&r2=77670&view=diff ============================================================================== --- vmkit/trunk/include/jnjvm/JnjvmModule.h (original) +++ vmkit/trunk/include/jnjvm/JnjvmModule.h Fri Jul 31 03:12:19 2009 @@ -245,14 +245,14 @@ llvm::Function* ArrayObjectTracerFunction; llvm::Function* RegularObjectTracerFunction; - llvm::Function* GetSJLJBufferFunction; + llvm::Function* StartJNIFunction; + llvm::Function* EndJNIFunction; llvm::Function* InterfaceLookupFunction; llvm::Function* VirtualFieldLookupFunction; llvm::Function* StaticFieldLookupFunction; llvm::Function* PrintExecutionFunction; llvm::Function* PrintMethodStartFunction; llvm::Function* PrintMethodEndFunction; - llvm::Function* JniProceedPendingExceptionFunction; llvm::Function* InitialiseClassFunction; llvm::Function* InitialisationCheckFunction; llvm::Function* ForceInitialisationCheckFunction; Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc?rev=77670&r1=77669&r2=77670&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMRuntime.inc Fri Jul 31 03:12:19 2009 @@ -81,9 +81,9 @@ #endif typedef int (*onLoad_t)(const void**, void*); -extern "C" void jnjvmJNIProceedPendingException(uint32** old, void** oldBuf); -extern "C" void jnjvmGetSJLJBuffer(uint32* num, uint32** old, void* newBuf, - void** oldBuf); +extern "C" void jnjvmEndJNI(uint32** old, void** oldBuf); +extern "C" void jnjvmStartJNI(uint32* num, uint32** old, void* newBuf, + void** oldBuf); // Calls the JNI_OnLoad function of a dynamic library. void callOnLoad(void* res, JnjvmClassLoader* loader, Jnjvm* vm) { @@ -95,13 +95,13 @@ uint32* old = 0; void* oldBuf = 0; jmp_buf buf; - jnjvmGetSJLJBuffer(&num, &old, (void*)buf, &oldBuf); if (setjmp((jumpbuf_t)buf) == 0) { + jnjvmStartJNI(&num, &old, (void*)buf, &oldBuf); onLoad(&vm->javavmEnv, res); } - jnjvmJNIProceedPendingException(&old, &oldBuf); + jnjvmEndJNI(&old, &oldBuf); } } Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=77670&r1=77669&r2=77670&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Fri Jul 31 03:12:19 2009 @@ -293,11 +293,6 @@ Value* oldCLIN = new AllocaInst(PointerType::getUnqual(Type::Int32Ty), "", currentBlock); - Value* Args4[4] = { temp, oldCLIN, newJB, oldJB }; - - CallInst::Create(module->GetSJLJBufferFunction, Args4, Args4 + 4, "", - currentBlock); - Value* test = CallInst::Create(module->setjmpLLVM, newJB, "", currentBlock); @@ -415,6 +410,11 @@ nativeFunc = node; } + Value* Args4[4] = { temp, oldCLIN, newJB, oldJB }; + + CallInst::Create(module->StartJNIFunction, Args4, Args4 + 4, "", + currentBlock); + Value* FrameAddr = CallInst::Create(module->llvm_frameaddress, module->constantZero, "", currentBlock); @@ -455,8 +455,7 @@ Value* Args2[2] = { oldCLIN, oldJB }; - CallInst::Create(module->JniProceedPendingExceptionFunction, Args2, Args2 + 2, - "", currentBlock); + CallInst::Create(module->EndJNIFunction, Args2, Args2 + 2, "", currentBlock); if (returnType != Type::VoidTy) ReturnInst::Create(endNode, currentBlock); Modified: vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp?rev=77670&r1=77669&r2=77670&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Fri Jul 31 03:12:19 2009 @@ -261,9 +261,8 @@ VirtualFieldLookupFunction = module->getFunction("jnjvmVirtualFieldLookup"); StaticFieldLookupFunction = module->getFunction("jnjvmStaticFieldLookup"); StringLookupFunction = module->getFunction("jnjvmStringLookup"); - JniProceedPendingExceptionFunction = - module->getFunction("jnjvmJNIProceedPendingException"); - GetSJLJBufferFunction = module->getFunction("jnjvmGetSJLJBuffer"); + StartJNIFunction = module->getFunction("jnjvmStartJNI"); + EndJNIFunction = module->getFunction("jnjvmEndJNI"); NullPointerExceptionFunction = module->getFunction("jnjvmNullPointerException"); Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=77670&r1=77669&r2=77670&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original) +++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Fri Jul 31 03:12:19 2009 @@ -229,8 +229,8 @@ declare void @jnjvmThrowException(%JavaObject*) declare void @jnjvmThrowExceptionFromJIT() -declare void @jnjvmJNIProceedPendingException(i32**, i8**) -declare void @jnjvmGetSJLJBuffer(i32*, i32**, i8*, i8**) +declare void @jnjvmEndJNI(i32**, i8**) +declare void @jnjvmStartJNI(i32*, i32**, i8*, i8**) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=77670&r1=77669&r2=77670&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Fri Jul 31 03:12:19 2009 @@ -378,7 +378,7 @@ } // Does not call Java code. -extern "C" void jnjvmJNIProceedPendingException(uint32** oldLRN, void** oldBuffer) { +extern "C" void jnjvmEndJNI(uint32** oldLRN, void** oldBuffer) { JavaThread* th = JavaThread::get(); // We're going back to Java @@ -400,21 +400,17 @@ } // Never throws. -extern "C" void** jnjvmGetSJLJBuffer(uint32* localReferencesNumber, - uint32** oldLocalReferencesNumber, - void* newBuffer, void** oldBuffer) { +extern "C" void** jnjvmStartJNI(uint32* localReferencesNumber, + uint32** oldLocalReferencesNumber, + void* newBuffer, void** oldBuffer) { JavaThread* th = JavaThread::get(); *oldBuffer = th->currentSjljBuffer; th->currentSjljBuffer = newBuffer; - memset(newBuffer, 0, sizeof(jmp_buf)); - *oldLocalReferencesNumber = th->currentAddedReferences; th->currentAddedReferences = localReferencesNumber; - // Start JNI because the next instruction after setjmp is a call to a - // JNI function. th->startJNI(2); void** val = (void**)th->addresses.back(); Modified: vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h?rev=77670&r1=77669&r2=77670&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/LinkJavaRuntime.h Fri Jul 31 03:12:19 2009 @@ -37,8 +37,8 @@ extern "C" JavaArray* jnjvmMultiCallNew(UserClassArray* cl, uint32 len, ...); extern "C" UserClassArray* jnjvmGetArrayClass(UserCommonClass*, UserClassArray**); -extern "C" void jnjvmJNIProceedPendingException(); -extern "C" void* jnjvmGetSJLJBuffer(); +extern "C" void jnjvmEndJNI(); +extern "C" void* jnjvmStartJNI(); extern "C" void jnjvmJavaObjectAquire(JavaObject* obj); extern "C" void jnjvmJavaObjectRelease(JavaObject* obj); extern "C" void jnjvmThrowException(JavaObject* obj); @@ -98,8 +98,8 @@ (void) jnjvmRuntimeDelegatee(0); (void) jnjvmMultiCallNew(0, 0); (void) jnjvmGetArrayClass(0, 0); - (void) jnjvmJNIProceedPendingException(); - (void) jnjvmGetSJLJBuffer(); + (void) jnjvmEndJNI(); + (void) jnjvmStartJNI(); (void) jnjvmJavaObjectAquire(0); (void) jnjvmJavaObjectRelease(0); (void) jnjvmThrowException(0); From nicolas.geoffray at lip6.fr Fri Jul 31 01:24:39 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Fri, 31 Jul 2009 08:24:39 -0000 Subject: [vmkit-commits] [vmkit] r77671 - /vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Message-ID: <200907310824.n6V8OfiI020686@zion.cs.uiuc.edu> Author: geoffray Date: Fri Jul 31 03:24:31 2009 New Revision: 77671 URL: http://llvm.org/viewvc/llvm-project?rev=77671&view=rev Log: Remove dead code. Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=77671&r1=77670&r2=77671&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Fri Jul 31 03:24:31 2009 @@ -51,10 +51,6 @@ #include "Zip.h" -namespace jnjvm { - -} - using namespace jnjvm; typedef void (*static_init_t)(JnjvmClassLoader*); @@ -427,6 +423,7 @@ if (!cl && doThrow) { Jnjvm* vm = JavaThread::get()->getJVM(); + fprintf(stderr, "Could not found %s\n", UTF8Buffer(name).cString()); if (name->equals(bootstrapLoader->NoClassDefFoundError)) { fprintf(stderr, "Unable to load NoClassDefFoundError"); abort(); From nicolas.geoffray at lip6.fr Fri Jul 31 02:12:38 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Fri, 31 Jul 2009 09:12:38 -0000 Subject: [vmkit-commits] [vmkit] r77672 - /vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Message-ID: <200907310912.n6V9CgwH022158@zion.cs.uiuc.edu> Author: geoffray Date: Fri Jul 31 04:12:15 2009 New Revision: 77672 URL: http://llvm.org/viewvc/llvm-project?rev=77672&view=rev Log: Remove accidential code from last commit. Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp?rev=77672&r1=77671&r2=77672&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmClassLoader.cpp Fri Jul 31 04:12:15 2009 @@ -423,7 +423,6 @@ if (!cl && doThrow) { Jnjvm* vm = JavaThread::get()->getJVM(); - fprintf(stderr, "Could not found %s\n", UTF8Buffer(name).cString()); if (name->equals(bootstrapLoader->NoClassDefFoundError)) { fprintf(stderr, "Unable to load NoClassDefFoundError"); abort(); From nicolas.geoffray at lip6.fr Fri Jul 31 05:24:39 2009 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Fri, 31 Jul 2009 12:24:39 -0000 Subject: [vmkit-commits] [vmkit] r77674 - /vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc Message-ID: <200907311224.n6VCOek8032356@zion.cs.uiuc.edu> Author: geoffray Date: Fri Jul 31 07:24:31 2009 New Revision: 77674 URL: http://llvm.org/viewvc/llvm-project?rev=77674&view=rev Log: Fix memory leak. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc?rev=77674&r1=77673&r2=77674&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMThrowable.inc Fri Jul 31 07:24:31 2009 @@ -37,15 +37,25 @@ Jnjvm* vm = th->getJVM(); // Allocate the temporary data. - std::vector* stack = new std::vector(); + std::vector stack; // Get the frame context. - th->getJavaFrameContext(*stack); + th->getJavaFrameContext(stack); + + ClassArray* cl = sizeof(void*) == 4 ? vm->upcalls->ArrayOfInt : + vm->upcalls->ArrayOfLong; + JavaArray* result = (JavaArray*) cl->doNew(stack.size(), vm); + void** tab = (void**)result->elements; + uint32 index = 0; + for (std::vector::iterator i = stack.begin(), e = stack.end(); + i != e; ++i, ++index) { + tab[index] = *i; + } // Set the tempory data in the new VMThrowable object. vmThrowable = vm->upcalls->newVMThrowable->doNew(vm); uint64 ptr = (uint64)vmThrowable + vm->upcalls->vmDataVMThrowable->ptrOffset; - ((JavaObject**)ptr)[0] = (JavaObject*)stack; + ((JavaObject**)ptr)[0] = result; return vmThrowable; } @@ -121,34 +131,27 @@ BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); JavaField* field = vm->upcalls->vmDataVMThrowable; - std::vector* stack = (std::vector*) - field->getObjectField(vmthrow); + JavaArray* stack = (JavaArray*)field->getObjectField(vmthrow); - std::vector::iterator i = stack->begin(), e = stack->end(); // remove the VMThrowable.fillInStackTrace method - uint32 index = 1; - ++i; - while (i != e) { - JavaMethod* meth = vm->IPToMethod(*i); + sint32 index = 1;; + while (index != stack->size) { + JavaMethod* meth = vm->IPToMethod(stack->elements[index]); assert(meth && "Wrong stack trace"); if (meth->classDef->isAssignableFrom(vm->upcalls->newThrowable)) { - ++i; ++index; } else break; } result = (ArrayObject*) - vm->upcalls->stackTraceArray->doNew(stack->size() - index, vm); + vm->upcalls->stackTraceArray->doNew(stack->size - index, vm); - index = 0; - for (; i != e; ++i) { - JavaMethod* meth = vm->IPToMethod(*i); + for (sint32 i = 0; i < result->size; ++i) { + JavaMethod* meth = vm->IPToMethod(stack->elements[i + index]); assert(meth && "Wrong stack trace"); - result->elements[index++] = consStackElement(meth, *i); + result->elements[i] = consStackElement(meth, stack->elements[i + index]); } - delete stack; - END_NATIVE_EXCEPTION return result;