gen_semispace.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,610 行 · 第 1/4 页
C
1,610 行
if (fromSpace != NULL) { free(fromSpace); } if (toSpace != NULL) { free(toSpace); } return NULL; } /* * Initialize thisGen. */ thisGen->fromSpace = fromSpace; thisGen->toSpace = toSpace; thisGen->gen.heapBase = space; thisGen->gen.heapTop = space + totalNumBytes / 4; /* * Start the world on fromSpace */ CVMgenSemispaceMakeCurrent(thisGen, fromSpace); /* * And finally, set the function pointers for this generation */ thisGen->gen.collect = CVMgenSemispaceCollect;#if defined(CVM_SEMISPACE_AS_OLDGEN) || defined(CVM_DEBUG_ASSERTS) thisGen->gen.scanOlderToYoungerPointers = CVMgenSemispaceScanOlderToYoungerPointers;#endif thisGen->gen.promoteInto = CVMgenSemispacePromoteInto; thisGen->gen.scanPromotedPointers = CVMgenSemispaceScanPromotedPointers; thisGen->gen.getExtraSpace = CVMgenSemispaceGetExtraSpace; thisGen->gen.freeMemory = CVMgenSemispaceFreeMemory; thisGen->gen.totalMemory = CVMgenSemispaceTotalMemory;#if defined(CVM_DEBUG) CVMgenSemispaceDumpSysInfo(thisGen);#endif /* CVM_DEBUG */ return (CVMGeneration*)thisGen;}#if defined(CVM_DEBUG) || defined(CVM_INSPECTOR)/* Dumps info about the configuration of the semispace generation. */void CVMgenSemispaceDumpSysInfo(CVMGenSemispaceGeneration* thisGen){ CVMUint32 numBytes; CVMGenSpace* fromSpace = thisGen->fromSpace; CVMGenSpace* toSpace = thisGen->toSpace; CVMGenSpace* firstSpace; CVMGenSpace* secondSpace; firstSpace = (fromSpace->allocBase < toSpace->allocBase) ? fromSpace : toSpace; secondSpace = (fromSpace->allocBase > toSpace->allocBase) ? fromSpace : toSpace; numBytes = (firstSpace->allocTop - firstSpace->allocBase) * sizeof(CVMUint32); CVMconsolePrintf("GC[SS]: Initialized semi-space gen for generational GC\n"); CVMconsolePrintf("\tSize of *each* semispace in bytes=%d\n" "\tLimits of generation = [0x%x,0x%x)\n" "\tFirst semispace = [0x%x,0x%x)\n" "\tSecond semispace = [0x%x,0x%x)\n" "\tCurrent semispace = %s semispace\n", numBytes, firstSpace->allocBase, secondSpace->allocTop, firstSpace->allocBase, firstSpace->allocTop, secondSpace->allocBase, secondSpace->allocTop, ((fromSpace == firstSpace) ?"First":"Second"));}#endif /* CVM_DEBUG || CVM_INSPECTOR *//* * Free all the memory associated with the current semispaces generation */voidCVMgenSemispaceFree(CVMGenSemispaceGeneration* thisGen){ free(thisGen->fromSpace); free(thisGen->toSpace); thisGen->fromSpace = NULL; thisGen->toSpace = NULL; free(thisGen);}static voidCVMgenSemispaceSetupCopying(CVMGenSemispaceGeneration* thisGen){ CVMUint32 spaceSize = (CVMUint32) (thisGen->toSpace->allocTop - thisGen->toSpace->allocBase); /* Always copy from 'fromSpace' to 'toSpace' */ thisGen->copyBase = thisGen->toSpace->allocBase; thisGen->copyTop = thisGen->copyBase; thisGen->copyThreshold = thisGen->toSpace->allocTop - spaceSize / 4;}/* * GC done. Flip the semispaces. */static voidCVMgenSemispaceFlip(CVMGenSemispaceGeneration* thisGen){ /* Flip the spaces: */ CVMGenSpace* newCurrent = thisGen->toSpace; thisGen->toSpace = thisGen->fromSpace; thisGen->fromSpace = newCurrent; /* Update the alloc ptrs in this gen and the new current space: */ newCurrent->allocPtr = thisGen->copyTop; CVMgenSemispaceMakeCurrent(thisGen, newCurrent);}/* * Copy object, leave forwarding pointer behind */static CVMObject*CVMgenSemispaceForwardOrPromoteObject(CVMGenSemispaceGeneration* thisGen, CVMObject* ref, CVMAddr classWord){ CVMClassBlock* objCb = CVMobjectGetClassFromClassWord(classWord); CVMUint32 objSize = CVMobjectSizeGivenClass(ref, objCb); CVMUint32* copyTop = thisGen->copyTop; CVMObject* ret; CVMBool copyIntoToSpace; /* * If this is the old generation, copy into to-space unconditionally. * * If it is not the old generation, try promotions as well. Copy * into to-space if object age below the desired threshold. If * above the threshold, try promotion. If promotion fails, copy * into to-space anyway. */#ifdef CVM_SEMISPACE_AS_OLDGEN if (!CVMgenSemispaceIsYoung(thisGen)) { ret = NULL; copyIntoToSpace = CVM_TRUE; } else#endif if (CVMobjGcBitsPlusPlusCompare(ref, CVM_GEN_PROMOTION_THRESHOLD)) { ret = NULL; copyIntoToSpace = CVM_TRUE; } else { /* Try promotion */ ret = thisGen->gen.nextGen->promoteInto(thisGen->gen.nextGen, ref, objSize); if (ret == NULL) { thisGen->hasFailedPromotion = CVM_TRUE; copyIntoToSpace = CVM_TRUE; } else { copyIntoToSpace = CVM_FALSE; } } if (copyIntoToSpace) { CVMUint32* newCopyTop = copyTop + objSize / 4; CVMtraceGcCollect(("GC[SS,%d]: " "Forwarding object %x (len %d, class %C), to %x\n", thisGen->gen.generationNo, ref, objSize, objCb, thisGen->copyTop)); CVMgenSemispaceCopyDisjointWords(copyTop, (CVMUint32*)ref, objSize); thisGen->copyTop = newCopyTop; ret = (CVMObject*)copyTop; } CVMassert(ret != NULL);#ifdef CVM_JVMPI if (CVMjvmpiEventObjectMoveIsEnabled()) { CVMjvmpiPostObjectMoveEvent(1, ref, 1, ret); }#endif#ifdef CVM_INSPECTOR if (CVMglobals.inspector.hasCapturedState) { CVMgcHeapStateObjectMoved(ref, ret); }#endif /* * Set forwarding pointer */ { CVMAddr newClassWord = (CVMAddr)ret; /* Mark as forwarded */ CVMobjectSetMarkedOnClassWord(newClassWord); /* ... and forward to the new copy */ CVMobjectSetClassWord(ref, newClassWord); } return ret;}/* * Gray an object known to be in the old semispace */static voidCVMgenSemispaceGrayObject(CVMGenSemispaceGeneration* thisGen, CVMObject** refPtr, CVMObject *ref){ CVMAddr classWord = CVMobjectGetClassWord(ref); CVMtraceGcCollect(("GC[SS,%d]: Graying object %x\n", thisGen->gen.generationNo, ref)); /* * ROM objects should have been filtered out by the time we get here */ CVMassert(!CVMobjectIsInROM(ref)); /* * Also, all objects that don't belong to this generation need to have * been filtered out by now. */ CVMassert(CVMgenSemispaceInOld(thisGen, ref)); /* * If the object is in old space it might already be * forwarded. Check that. If it has been forwarded, set the slot * to refer to the new copy. If it has not been forwarded, copy * the object, and set the forwarding pointer. */ if (CVMobjectMarkedOnClassWord(classWord)) { /* Get the forwarding pointer */ *refPtr = (CVMObject*)CVMobjectClearMarkedOnClassWord(classWord); CVMtraceGcCollect(("GC[SS,%d]: Object already forwarded: %x -> %x\n", thisGen->gen.generationNo, ref, *refPtr)); } else { *refPtr = CVMgenSemispaceForwardOrPromoteObject(thisGen, ref, classWord); }}/* * Gray a slot if it points into this generation. */static voidCVMgenSemispaceFilteredGrayObject(CVMGenSemispaceGeneration* thisGen, CVMObject** refPtr, CVMObject* ref){ /* * Gray only if the slot points to this generation's from space. * * Make sure we don't scan roots twice! */ CVMassert(CVMobjectIsInROM(ref) || !CVMgenInGeneration((CVMGeneration*)thisGen, ref) || CVMgenSemispaceInOld(thisGen, ref)); if (CVMgenSemispaceInOld(thisGen, ref)) { CVMgenSemispaceGrayObject(thisGen, refPtr, ref); }}/* * A version of the above where multiple scans of the same slot are allowed. * Used for CVMgenSemispaceScanTransitively() only. */static voidCVMgenSemispaceFilteredGrayObjectWithMS(CVMGenSemispaceGeneration* thisGen, CVMObject** refPtr, CVMObject* ref){ /* * Gray only if the slot points to this generation's from space. */ if (CVMgenSemispaceInOld(thisGen, ref)) { CVMgenSemispaceGrayObject(thisGen, refPtr, ref); }}/* * Scan a non-NULL reference into this generation. Make sure to * handle the case that the slot has already been scanned -- the * root scan should allow for such a case. */static voidCVMgenSemispaceFilteredHandleRoot(CVMObject** refPtr, void* data){ CVMGenSemispaceGeneration* thisGen = (CVMGenSemispaceGeneration*)data; CVMObject* ref = *refPtr; CVMassert(refPtr != 0); CVMassert(ref != 0); CVMtraceGcCollect(("GC[SS,%d]: Handling external reference: [%x] = %x\n", thisGen->gen.generationNo, refPtr, ref)); CVMgenSemispaceFilteredGrayObject(thisGen, refPtr, ref);}typedef struct CVMGenSemispaceTransitiveScanData { CVMExecEnv* ee; CVMGCOptions* gcOpts; CVMGenSemispaceGeneration* thisGen;} CVMGenSemispaceTransitiveScanData;#ifndef BREADTH_FIRST_SCAN/* NOTE: The following CVMObjectIterator code is based on the CVMobjectWalkRefsAux() macro, and is supposed to achieve the equivalent scanning of objects. The difference being that CVMObjectIterator allows for a depth-first scan algorithm at the cost of a slightly higher overhead, while CVMobjectWalkRefsAux() enforces breadth-first scanning.*/typedef struct CVMObjectIterator CVMObjectIterator;struct CVMObjectIterator{ CVMObject *ref; CVMObject *forwardedRef; CVMAddr offset; CVMAddr map; CVMObject **refPtr; CVMAddr flags; /* For arrays only: */ CVMObject **arrEnd; /* For Big GC maps only: */ CVMAddr *mapPtr; CVMAddr *mapEnd; CVMObject** otherRefPtr;};/* Initializes the iterator to walk the references in the given object. */static voidCVMobjectIteratorInit(CVMExecEnv *ee, CVMGCOptions *gcOpts, CVMObjectIterator *iter, CVMObject *obj, CVMObject *forwardedObj){ CVMClassBlock *cb; CVMAddr map; CVMObject **refPtr; CVMAddr flags; CVMBool handleWeakReferences = CVM_TRUE; iter->ref = obj; iter->forwardedRef = forwardedObj; iter->offset = 0; cb = CVMobjectGetClass(forwardedObj); map = CVMcbGcMap(cb).map; flags = map & CVM_GCMAP_FLAGS_MASK; iter->map = map; iter->flags = flags; if (map == CVM_GCMAP_NOREFS) { return; } refPtr = (CVMObject **)&(forwardedObj)->fields[0]; if (flags == CVM_GCMAP_SHORTGCMAP_FLAG) { /* First skip the flags */ map >>= CVM_GCMAP_NUM_FLAGS; if (handleWeakReferences && gcOpts->discoverWeakReferences) { if (CVMcbIs(cb, REFERENCE)) { /* Skip referent, next in case we just discovered a new active weak reference object. */ if (CVMweakrefField(forwardedObj, next) == NULL) { CVMweakrefDiscover(ee, forwardedObj); map >>= CVM_GCMAP_NUM_WEAKREF_FIELDS; refPtr += CVM_GCMAP_NUM_WEAKREF_FIELDS; } } } } else if (flags == CVM_GCMAP_ALLREFS_FLAG) { CVMArrayOfRef *arrRefs = (CVMArrayOfRef *)forwardedObj; CVMJavaInt arrLen = CVMD_arrayGetLength(arrRefs); refPtr = (CVMObject **) &arrRefs->elems[0]; iter->arrEnd = (CVMObject **) &arrRefs->elems[arrLen]; } else { /* object with "big" GC map */ /* * CVMGCBitMap is a union of the scalar 'map' and the * pointer 'bigmap'. So it's best to * use the pointer if we need the pointer */ CVMBigGCBitMap *bigmap = (CVMBigGCBitMap *) ((CVMAddr)(CVMcbGcMap(cb).bigmap) & ~CVM_GCMAP_FLAGS_MASK); CVMUint32 mapLen = bigmap->maplen; /* * Make 'mapPtr' and 'mapEnd' pointers to the type of 'map' * in 'CVMBigGCBitMap'. */ CVMAddr *mapPtr = bigmap->map; CVMAddr *mapEnd = mapPtr + mapLen; CVMObject** otherRefPtr = refPtr; CVMassert(flags == CVM_GCMAP_LONGGCMAP_FLAG); /* Make sure there is something to do. */ CVMassert(mapPtr < mapEnd); map = *mapPtr; if (handleWeakReferences && gcOpts->discoverWeakReferences) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?