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 = ¤tEE->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, ¤tEE->localRootsStack, callback, localRootData, gcOpts); interpreterStackData.targetEE = currentEE; interpreterStackData.prevFrame = NULL; CVMstackWalkAllFrames(¤tEE->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, ¤tEE->localRootsStack, callback, data, gcOpts); interpreterStackData.targetEE = currentEE; interpreterStackData.prevFrame = NULL; CVMstackScanRoots0(ee, ¤tEE->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 + -
显示快捷键?