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 + -
显示快捷键?