gc_common.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,731 行 · 第 1/4 页
C
1,731 行
/* * @(#)gc_common.c 1.163 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/directmem.h"#include "javavm/include/indirectmem.h"#include "javavm/include/interpreter.h"#include "javavm/include/stackwalk.h"#include "javavm/include/utils.h"#include "javavm/include/string.h"#include "javavm/include/sync.h"#include "javavm/include/localroots.h"#include "javavm/include/globalroots.h"#include "javavm/include/preloader.h"#include "javavm/include/gc_common.h"#include "javavm/include/gc/gc_impl.h"#include "javavm/include/gc_stat.h"#include "javavm/include/globals.h"#include "javavm/include/basictypes.h"#include "javavm/include/stackmaps.h"#ifdef CVM_INSPECTOR#include "javavm/include/inspector.h"#endif#ifdef CVM_JIT#include "javavm/include/jit/jitcodebuffer.h"#endif#ifdef CVM_JVMTI#include "javavm/include/jvmtiDumper.h"#include "javavm/include/jvmtiExport.h"#endif#ifdef CVM_JVMPI#include "javavm/include/jvmpi_impl.h"#endif/* #define CVM_TEST_FAILED_ALLOCATION_GC to simulate an allocation failure every CVM_NUM_ALLOCATIONS_PER_GC allocations and trigger GCs. This is only for test purposes. */#undef CVM_TEST_FAILED_ALLOCATION_GC#ifdef CVM_TEST_FAILED_ALLOCATION_GCstatic int failedAllocGCCount = 0;#define CVM_NUM_ALLOCATIONS_PER_GC 10#endif#ifdef CVM_JVMPI/* The following is a list of arena IDs for shared (i.e. not GC implementation specific GC heaps: NOTE: CVM_GC_ARENA_UNKNOWN is defined in gc_common.h. */enum { RESERVED_FOR__CVM_GC_ARENA_UNKNOWN = 0, CVM_GC_ARENA_PRELOADED, /* Arena for preloaded objects. */ /* CVM_GC_TOTAL_SHARED_ARENA_IDS must always be the last enum in the list: */ CVM_GC_TOTAL_SHARED_ARENA_IDS};#endif/* * Parse the heap size from the -Xms command line option. * */static CVMBoolparseOption(const char* sizeOption, CVMUint32* sizeRet, CVMUint32 defaultSize){ if (sizeOption != NULL) { CVMInt32 tmpVal; tmpVal = CVMoptionToInt32(sizeOption); if (tmpVal < 0) { return CVM_FALSE; } *sizeRet = (CVMUint32) tmpVal; } else { *sizeRet = defaultSize; } return CVM_TRUE;}static voidhandleGcStats(){ const char* statAttr; /* Are we doing GC statistics? */ statAttr = CVMgetParsedSubOption(&CVMglobals.gcCommon.gcOptions, "stat"); if (statAttr != NULL) { CVMgcstatDoGCMeasurement(CVM_TRUE); }}static voidhandleSmLimits(){ const char* maxSmMemAttr; /* Max stackmaps memory usage */ maxSmMemAttr = CVMgetParsedSubOption(&CVMglobals.gcCommon.gcOptions, "maxStackMapsMemorySize"); if (maxSmMemAttr == NULL) { CVMglobals.gcCommon.maxStackMapsMemorySize = 0xFFFFFFFF; } else { CVMglobals.gcCommon.maxStackMapsMemorySize = (CVMUint32)CVMoptionToInt32(maxSmMemAttr); }}#ifdef CVM_MTASKCVMBoolCVMgcParseXgcOptions(CVMExecEnv* ee, const char* xgcOpts){ if (!CVMinitParsedSubOptions(&CVMglobals.gcCommon.gcOptions, xgcOpts)) { CVMconsolePrintf("Error parsing GC attributes\n"); return CVM_FALSE; } /* Allow overrides of the following */ handleGcStats(); handleSmLimits(); /* Ignore any settings of heap size or young generation size */ return CVM_TRUE;}#endif/* * Initialize a heap of at least 'minBytes' bytes, and at most 'maxBytes' * bytes. */CVMBool CVMgcInitHeap(CVMOptions *options){ CVMUint32 startHeapSize, minHeapSize, maxHeapSize; if (!parseOption(options->startHeapSizeStr, &startHeapSize, CVM_DEFAULT_START_HEAP_SIZE_IN_BYTES)) { CVMconsolePrintf("Cannot start VM " "(error parsing heap size command " "line option -Xms)\n"); return CVM_FALSE; } if (!parseOption(options->minHeapSizeStr, &minHeapSize, CVM_DEFAULT_MIN_HEAP_SIZE_IN_BYTES)) { CVMconsolePrintf("Cannot start VM " "(error parsing heap size command " "line option -Xmn)\n"); return CVM_FALSE; } if (!parseOption(options->maxHeapSizeStr, &maxHeapSize, CVM_DEFAULT_MAX_HEAP_SIZE_IN_BYTES)) { CVMconsolePrintf("Cannot start VM " "(error parsing heap size command " "line option -Xmx)\n"); return CVM_FALSE; } if (!CVMinitParsedSubOptions(&CVMglobals.gcCommon.gcOptions, options->gcAttributesStr)) { CVMconsolePrintf("Cannot start VM " "(error parsing GC attributes " "command-line option)\n"); return CVM_FALSE; } /* * This is the place to parse shared attributes, if any. Currently * there aren't any that I can think of, so the particular GC * implementation is the only client of GC attributes now. * * CVMgcParseSharedGCAttributes(); */ /* CVMconsolePrintf("CVMgcInitHeap: heap size = %d, ", heapSize); */ handleGcStats(); handleSmLimits(); #ifdef CVM_JVMPI if (CVMjvmpiEventArenaNewIsEnabled()) { CVMjvmpiPostArenaNewEvent(CVM_GC_ARENA_PRELOADED, "Preloaded"); }#endif /* Let's round these up to nice double-word multiples, before passing them on */ /* * CVMalignDoubleWordUp returns a CVMAddr. * Just cast it to CVMUint32 */ startHeapSize = (CVMUint32)CVMalignDoubleWordUp(startHeapSize); minHeapSize = (CVMUint32)CVMalignDoubleWordUp(minHeapSize); maxHeapSize = (CVMUint32)CVMalignDoubleWordUp(maxHeapSize); if (minHeapSize > maxHeapSize) { CVMdebugPrintf(("WARNING: Minimum heap size %d is larger than " "maximum size %d, setting both to %d\n", minHeapSize, maxHeapSize, minHeapSize)); maxHeapSize = minHeapSize; } if (minHeapSize > startHeapSize) { CVMdebugPrintf(("WARNING: Minimum heap size %d is larger than " "start size %d, setting both to %d\n", minHeapSize, startHeapSize, minHeapSize)); startHeapSize = minHeapSize; } if (startHeapSize > maxHeapSize) { CVMdebugPrintf(("WARNING: Start heap size %d is larger than " "maximum size %d, setting both to %d\n", startHeapSize, maxHeapSize, startHeapSize)); maxHeapSize = startHeapSize; } /* stash away the max heap size */ CVMglobals.maxHeapSize = maxHeapSize; return CVMgcimplInitHeap(&CVMglobals.gc, startHeapSize, minHeapSize, maxHeapSize, (options->startHeapSizeStr == NULL), (options->minHeapSizeStr == NULL), (options->maxHeapSizeStr == NULL));}/* * Get GC attribute named 'attrName'. * If 'attrName' is of the form 'attrName=val', return "val". * If 'attrName' is a flag instead, just return attrName. * Return NULL if not found. */char *CVMgcGetGCAttributeVal(char* attrName){ return (char *)CVMgetParsedSubOption(&CVMglobals.gcCommon.gcOptions, attrName);}#undef CVM_FASTALLOC_STATS#ifdef CVM_FASTALLOC_STATSCVMUint32 fastLockCount = 0;CVMUint32 slowLockCount = 0;CVMUint32 verySlowLockCount = 0;#endif/* * The fast, GC-unsafe locking guarding allocations. * If atomic swap operations are supported, this lock is a simple * integer. * If not, the non-blocking 'tryLock' is used on the 'heapLock'. */static CVMBoolCVMgcPrivateLockHeapUnsafe(CVMExecEnv* ee){#ifdef CVM_ADV_ATOMIC_SWAP return CVMatomicSwap(&CVMglobals.fastHeapLock, 1) == 0;#else return CVMsysMutexTryLock(ee, &CVMglobals.heapLock);#endif}static voidCVMgcPrivateUnlockHeap(CVMExecEnv* ee){#ifdef CVM_ADV_ATOMIC_SWAP CVMatomicSwap(&CVMglobals.fastHeapLock, 0);#else CVMsysMutexUnlock(ee, &CVMglobals.heapLock);#endif}/* * WARNING: GC-unsafe allocator. Use CVMID_allocNewInstance() in GC-safe * code. */static CVMObject*doNewInstance(CVMExecEnv* ee, CVMClassBlock* cb, CVMObject* (*allocateInstance)(CVMExecEnv* ee, CVMUint32 numBytes));/* * Allocate heap array of length 'len'. The array type is 'arrayCb'. */static CVMArrayOfAnyType*doNewArray(CVMExecEnv* ee, CVMJavaInt arrayObjectSize, CVMClassBlock* arrayCb, CVMJavaInt arrayLen, CVMObject* (*allocateInstance)(CVMExecEnv* ee, CVMUint32 numBytes));/* * Handle finalizable allocations. Return a direct reference to this * object, since it might have changed due to GC. */static CVMObject*handleFinalizableAllocation(CVMExecEnv* ee, CVMObject* newInstance){ CVMObjectICell* theCell = CVMfinalizerRegisterICell(ee); /* * We should call java.lang.ref.Finalizer.register(). * We are going to go GC-safe here, so we'd better stash * the new object in a safe place in the interim. The caller * has not stored it in a GC-scannable place yet. * * NOTE: The following assertion is necessary to prevent a * case of a finalizable allocation in Finalizer.register(). * If there is such a case, then we are going to re-enter this * function, and we will want to overwrite theCell which is * big trouble. */ CVMassert(CVMID_icellIsNull(theCell)); CVMID_icellSetDirect(ee, theCell, newInstance); /* safe! */ CVMD_gcSafeExec(ee, { JNIEnv* env = CVMexecEnv2JniEnv(ee); jobject clazz = CVMcbJavaInstance(CVMsystemClass(java_lang_ref_Finalizer)); CVMMethodBlock* mb = CVMglobals.java_lang_ref_Finalizer_register; /* * We need to push a local frame here so we can make * JNI calls at all points that instances may be allocated. */ if ((*env)->PushLocalFrame(env, 4) == JNI_OK) { CVMdisableRemoteExceptions(ee); (*env)->CallStaticVoidMethod(env, clazz, mb, theCell); CVMenableRemoteExceptions(ee); (*env)->PopLocalFrame(env, NULL); } else { newInstance = NULL; } /* PushLocalFrame() or CallStaticVoidMethod() could have caused * an exception, and we don't want to propagate it. */ CVMclearLocalException(ee); }); /* * Now re-load, since the object's address may have changed. */ if (newInstance != NULL) { newInstance = CVMID_icellDirect(ee, theCell); } CVMID_icellSetNull(theCell); /* done! */ /* * check that a new object starts at an aligned address */ CVMassert((CVMAddr)CVMalignAddrUp(newInstance) == (CVMAddr)newInstance); return newInstance;}/* * GC for numBytes, and retry allocation if necessary */static CVMBoolstopTheWorldAndGCWithRetry(CVMExecEnv* ee, CVMUint32 numBytes, void (*retryAfterActionCallback)(CVMExecEnv *ee, void *data), void* retryData);typedef struct ObjAllocWrap { CVMClassBlock* cb;} ObjAllocWrap;/* * Retrying allocation for newInstance() */static voidnewInstanceRetry(CVMExecEnv* ee, void* data){ ObjAllocWrap* aw = (ObjAllocWrap*)data; CVMObjectICell* theCell = CVMallocationRetryICell(ee); CVMObject* newObject; CVMassert(CVMID_icellIsNull(theCell)); newObject = doNewInstance(ee, aw->cb, CVMgcimplRetryAllocationAfterGC); CVMID_icellSetDirectWithAssertion(CVM_TRUE, theCell, newObject);}/* * Re-trying a java.lang.Class instance allocation */static voidnewClassInstanceRetry(CVMExecEnv* ee, void* data){ ObjAllocWrap* aw = (ObjAllocWrap*)data; CVMObjectICell* theCell = CVMallocationRetryICell(ee); CVMObject* newObject; CVMassert(CVMID_icellIsNull(theCell)); /* * Create a new java.lang.Class, and fill in the back pointer */ newObject = doNewInstance(ee, CVMsystemClass(java_lang_Class), CVMgcimplRetryAllocationAfterGC); /* * Access member variable of type 'int' * and cast it to a native pointer. The java type 'int' only guarantees * 32 bit, but because one slot is used as storage space and * a slot is 64 bit on 64 bit platforms, it is possible * to store a native pointer without modification of * java source code. This assumes that all places in the C-code * which set/get this member are caught. */ if (newObject != NULL) { CVMD_fieldWriteAddr(newObject, CVMoffsetOfjava_lang_Class_classBlockPointer, (CVMAddr)aw->cb); } CVMID_icellSetDirectWithAssertion(CVM_TRUE, theCell, newObject);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?