gc_common.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,731 行 · 第 1/4 页

C
1,731
字号
    CVMRefCallbackFunc transitiveScanner, void* transitiveScannerData){    /*     * Handle weak reference structures, clearing out the right     * referents. This can change the liveness of things, so it should     * come first.     */    CVMweakrefProcessNonStrong(ee, isLive, isLiveData,			       transitiveScanner, transitiveScannerData,			       gcOpts);    CVMweakrefFinalizeProcessing(ee, isLive, isLiveData,			       transitiveScanner, transitiveScannerData,			       gcOpts);}/* Process interned strings with liveness info from a particular GC * implementation. * isLive - a predicate that returns true if an object is strongly referenced * transitiveScanner - a callback that marks an object and all its children */voidCVMgcProcessInternedStringsWithLivenessInfo(CVMExecEnv* ee,    CVMGCOptions* gcOpts, CVMRefLivenessQueryFunc isLive, void* isLiveData,    CVMRefCallbackFunc transitiveScanner, void* transitiveScannerData){    CVMinternProcessNonStrong(isLive, isLiveData,			      transitiveScanner, transitiveScannerData);    CVMinternFinalizeProcessing(isLive, isLiveData,				transitiveScanner, transitiveScannerData);}/* * Process special objects with liveness info from a particular GC * implementation. This covers special scans like string intern table, * weak references and monitor structures. */voidCVMgcProcessSpecialWithLivenessInfoWithoutWeakRefs(                                    CVMExecEnv* ee, CVMGCOptions* gcOpts,				    CVMRefLivenessQueryFunc isLive,				    void* isLiveData,                                    CVMRefCallbackFunc transitiveScanner,				    void* transitiveScannerData){    /*     * Handle monitor structures     */    CVMdeleteUnreferencedMonitors(ee, isLive, isLiveData,				  transitiveScanner, transitiveScannerData);        /*     * Purge unused entries for cb iff !CVMcbGcScanned(cb). NOTE: by     * default, all ROM classes are assumed to be scanned, even though     * CVMcbGcScanned(cbInRom) == FALSE.     */#ifdef CVM_CLASSLOADING    if (CVMglobals.gcCommon.doClassCleanup) {        CVMclassDoClassUnloadingPass1(ee, isLive, isLiveData,            transitiveScanner, transitiveScannerData, gcOpts);    }#endif}/* Purpose: Attempts to compute stackmaps for all the GC's root scan. *//* Returns: CVM_TRUE if successful, else returns CVM_FALSE. */CVMBoolCVMgcEnsureStackmapsForRootScans(CVMExecEnv *ee){    CVM_WALK_ALL_THREADS(ee, currentEE, {	CVMStack* iStack = &currentEE->interpreterStack;	CVMstackWalkAllFrames(iStack, {	    if (CVMframeIsJava(frame)) {		if (!CVMjavaFrameEnsureStackmaps(ee, currentEE, frame)) {		    return CVM_FALSE;		}	    }	});    });    return CVM_TRUE;}/* Purpose: Brings the stackmap memory usage back in line. */void CVMgcTrimStackmapsMemUsage(CVMExecEnv *ee){    CVMStackMaps *maps = CVMglobals.gcCommon.lastStackMaps;#undef DUMP_STACKMAPS_MEMORY_USAGE#ifdef DUMP_STACKMAPS_MEMORY_USAGE    CVMconsolePrintf("STACKMAPS: Total Memory Used BEFORE GC = %d\n",                     CVMglobals.stackMapsTotalMemoryUsed);#endif    while (CVMglobals.gcCommon.stackMapsTotalMemoryUsed >                   CVMglobals.gcCommon.maxStackMapsMemorySize) {        CVMassert(maps != NULL);        CVMstackmapDestroy(ee, maps);        maps = CVMglobals.gcCommon.lastStackMaps;    }#ifdef DUMP_STACKMAPS_MEMORY_USAGE    CVMconsolePrintf("STACKMAPS: Total Memory Used AFTER GC = %d\n",                     CVMglobals.stackMapsTotalMemoryUsed);#endif}/* * Start a GC cycle. */voidCVMgcStartGC(CVMExecEnv* ee){}voidCVMgcClearClassMarks(CVMExecEnv* ee, CVMGCOptions* gcOpts){    /*     * Clear the scanned bits of all classes. Each class will be scanned     * by the object scan as necessary. This includes the class     * global roots.     *     * Of course if we are not doing a full GC, we don't have to do this.     * All classes will be scanned anyway, so the GC_SCANNED bit is     * irrelevant.     */    CVMclassIterateDynamicallyLoadedClasses(        ee, CVMclassClearScannedFlagCallback, NULL);}/* * End a GC cycle. */voidCVMgcEndGC(CVMExecEnv* ee){#ifdef CVM_CLASSLOADING    if (CVMglobals.gcCommon.doClassCleanup) {        CVMclassDoClassUnloadingPass2(ee);    }#endif#ifdef CVM_JIT    /*      * Do aging of compiled methods so some can be decompiled if necessary.     */    CVMJITcodeCacheAgeEntryCountsAndDecompile(ee, 0);#endif}/* * Scan and optionally update special objects. This covers special * scans like string intern table, weak references and monitor * structures. */voidCVMgcScanSpecial(CVMExecEnv* ee, CVMGCOptions* gcOpts,		 CVMRefCallbackFunc refUpdate, void* refUpdateData){    CVMtraceGcCollect(("GC_COMMON: "		       "Scanning special objects (full)\n"));    /*     * Handle interned strings     */    CVMscanInternedStrings(refUpdate, refUpdateData);    /*     * Handle monitor structures     */    CVMscanMonitors(ee, refUpdate, refUpdateData);    /*     * Handle weak reference structures     */    CVMweakrefUpdate(ee, refUpdate, refUpdateData, gcOpts);    /*     * Update all live class loader roots     */    CVMstackScanRoots(ee, &CVMglobals.classLoaderGlobalRoots,		      refUpdate, refUpdateData, gcOpts);}/* * Scan the root set of collection */voidCVMgcScanRoots(CVMExecEnv *ee, CVMGCOptions* gcOpts,	       CVMRefCallbackFunc callback, void* data){    /*     * Assert that we are holding the right locks before scanning     * the data structures protected by those locks.     */    CVMassert(CVMreentrantMutexIAmOwner(        ee, CVMsysMutexGetReentrantMutex(&CVMglobals.threadLock)));    /*     * Scan global roots     */    {        void *callbackData = data;#if defined(CVM_INSPECTOR) || defined(CVM_JVMPI)        CVMGCProfilingInfo info;        if (gcOpts->isProfilingPass) {            info.type = CVMGCRefType_GLOBAL_ROOT;            info.data = data;            callbackData = &info;        }#endif        CVMstackScanRoots(ee, &CVMglobals.globalRoots, callback, callbackData,			  gcOpts);    }    /*     * Do the preloader statics     */    {        void *callbackData = data;#if defined(CVM_INSPECTOR) || defined(CVM_JVMPI)        CVMGCProfilingInfo info;        if (gcOpts->isProfilingPass) {            info.type = CVMGCRefType_PRELOADER_STATICS;            info.data = data;            callbackData = &info;        }#endif#ifdef CVM_LVM /* %begin lvm */	/* Each LVM has its own copy of static fields.	 * Walk throgh each of them. */	CVMLVMwalkStatics(callback, callbackData);#else /* %end lvm */	{	    CVMAddr  numRefStatics = CVMpreloaderNumberOfRefStatics();	    CVMAddr* refStatics    = CVMpreloaderGetRefStatics();	    CVMwalkContiguousRefs(refStatics, numRefStatics, callback,				  callbackData);	}#endif /* %begin,end lvm */    }    {	CVMClassScanOptions opt;#if defined(CVM_INSPECTOR) || defined(CVM_JVMPI)        CVMGCProfilingInfo info;#endif	/*	 * Now make sure to keep all system classes live. These cannot	 * be unloaded.	 */        opt.gcOpts = gcOpts;	opt.callback = callback;#if defined(CVM_INSPECTOR) || defined(CVM_JVMPI)        if (gcOpts->isProfilingPass) {            info.type = CVMGCRefType_CLASS_STATICS;            info.data = data;            opt.data = &info;        } else {            opt.data = data;        }#else        opt.data = data;#endif	CVMclassIterateDynamicallyLoadedClasses(            ee, CVMclassScanSystemClassCallback, &opt);    }    /*     * Scan the local and interpreter roots of each thread. The previous     * class table iterations already cleared the mark bits of classes     * if they are to be scanned based on reachability.     */#if defined(CVM_INSPECTOR) || defined(CVM_JVMPI)    {        void *localRootData = data;        CVMGCProfilingInfo localRootInfo;        CVMGCProfilingInfo interpreterStackInfo;	CVMInterpreterStackData interpreterStackData;		interpreterStackData.callbackData = data;        if (gcOpts->isProfilingPass) {            localRootInfo.type = CVMGCRefType_LOCAL_ROOTS;            localRootInfo.data = data;            interpreterStackInfo.data = data;            localRootData = &localRootInfo;            interpreterStackData.callbackData = &interpreterStackInfo;        }        CVM_WALK_ALL_THREADS(ee, currentEE, {            CVMInt32 frameNumber = 0;            localRootInfo.u.frame.ee = currentEE;            CVMstackScanRoots(ee, &currentEE->localRootsStack,                              callback, localRootData, gcOpts);	    interpreterStackData.targetEE = currentEE;	    interpreterStackData.prevFrame = NULL;            CVMstackWalkAllFrames(&currentEE->interpreterStack, {                if (gcOpts->isProfilingPass) {                    CVMGCProfilingInfo *info = &interpreterStackInfo;                    if (CVMframeIsJava(frame)) {                        info->type = CVMGCRefType_JAVA_FRAME;                    } else if (CVMframeIsJNI(frame)) {                        info->type = CVMGCRefType_JNI_FRAME;                    } else if (CVMframeIsTransition(frame)) {                        info->type = CVMGCRefType_TRANSITION_FRAME;                    } else {                        info->type = CVMGCRefType_UNKNOWN_STACK_FRAME;                        CVMassert(CVM_FALSE);                    }                    info->u.frame.ee = currentEE;                    info->u.frame.frameNumber = frameNumber++;                    info->data = data;                }                (*CVMframeScanners[frame->type])(ee, frame, chunk, callback,			        &interpreterStackData, gcOpts);		interpreterStackData.prevFrame = frame;            });        });    }#else    {	CVMInterpreterStackData interpreterStackData;	interpreterStackData.callbackData = data;	CVM_WALK_ALL_THREADS(ee, currentEE, {	    CVMstackScanRoots(ee, &currentEE->localRootsStack,			      callback, data, gcOpts);	    interpreterStackData.targetEE = currentEE;	    interpreterStackData.prevFrame = NULL;	    CVMstackScanRoots0(ee, &currentEE->interpreterStack,			       callback, &interpreterStackData,			       gcOpts, {}, {				   interpreterStackData.prevFrame = frame;			       });	});    }#endif}/* Purpose: Acquire all GC locks, stop all threads, and then call back to do            action specific work. When the action is done, the world is            resumed.   NOTE: If we can't execute the action successfully, return CVM_FALSE.         Otherwise, return the status of the action.   NOTE: The heapLock must have already been acquired before calling this         function.  preActionCallback and postActionCallback may be NULL         but actionCallback must point to a valid function.*/static CVMBoolstopTheWorldAndDoAction(CVMExecEnv *ee, void *data,                 CVMUint32 (*preActionCallback)(CVMExecEnv *ee, void *data),                 CVMBool (*actionCallback)(CVMExecEnv *ee, void *data),                 void (*postActionCallback)(CVMExecEnv *ee, void *data,                                            CVMBool actionSuccess,                                            CVMUint32 preActionStatus),		 void (*retryAfterActionCallback)(CVMExecEnv *ee, void *data),		 void* retryData);#ifdef CVM_INSPECTORCVMBoolCVMgcStopTheWorldAndDoAction(CVMExecEnv *ee, void *data,                 CVMUint32 (*preActionCallback)(CVMExecEnv *ee, void *data),                 CVMBool (*actionCallback)(CVMExecEnv *ee, void *data),                 void (*postActionCallback)(CVMExecEnv *ee, void *data,                                            CVMBool actionSuccess,                                            CVMUint32 preActionStatus),		 void (*retryAfterActionCallback)(CVMExecEnv *ee, void *data),                 void* retryData){    return stopTheWorldAndDoAction(ee, data, preActionCallback, actionCallback,	       postActionCallback, retryAfterActionCallback, retryData);}#endif /* CVM_INSPECTOR *//* Purpose: Acquire all GC locks, stop all threads, and then call back to do            action specific work. When the action is done, the world is            resumed.   NOTE: If we can't execute the action successfully, return CVM_FALSE.         Otherwise, return the status of the action.   NOTE: The heapLock must have already been acquired before calling this         function.  preActionCallback and postActionCallback may be NULL         but actionCallback must point to a valid function.*/static CVMBoolstopTheWorldAndDoAction(CVMExecEnv *ee, void *data,                 CVMUint32 (*preActionCallback)(CVMExecEnv *ee, void *data),                 CVMBool (*actionCallback)(CVMExecEnv *ee, void *data),                 void (*postActionCallback)(CVMExecEnv *ee, void *data,                                            CVMBool actionSuccess,                                            CVMUint32 preActionStatus),                 void (*retryAfterActionCallback)(CVMExecEnv *ee, void *data),                 void* retryData){    CVMBool success = CVM_FALSE;    CVMUint32 preActionStatus = 0;#ifdef CVM_JIT    /* The jitLock is needed for BecomeSafeAll() and must be acquired before       the heapLock: */    CVMassert(CVMsysMutexOwner(&CVMglobals.jitLock) == ee);#endif    CVMassert(CVMsysMutexOwner(&CVMglobals.heapLock) == ee);    CVMassert(CVMD_isgcSafe(ee));    CVMassert(actionCallback != NULL);    /* Get the rest of the GC locks.  The heapLock must have already been       acquired before calling this function. */    CVMlocksForGCAcquire(ee);    /* Roll all threads to GC-safe points. */    CVMD_gcBecomeSafeAll(ee);    /* Do callback for the preAction: */    if (preActionCallback != NULL) {        preActionStatus = preActionCallback(ee, data);        if (preActionStatus != 0) {            goto preActionFailed;        }    }    if (CVMgcEnsureStackmapsForRootScans(ee)) {        /* Do callback for the Action: */        success = actionCallback(ee, data);    }preActionFailed:    /* Even if the GC fails, we will want to allow the retry because we may       get here not due to a shortage of memory and a need to GC, but simply       due to contention during a fast allocation attempt.  The allocation       may still succeeded:    */    if (retryAfterActionCallback != NULL) {	retryAfterActionCallback(ee, retryData);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?