gc_impl.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,897 行 · 第 1/5 页
C
1,897 行
/* * 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. * *//* * This file includes the implementation of a generational collector. */#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/classes.h"#include "javavm/include/directmem.h"#include "javavm/include/porting/time.h"/* * This file is generated from the GC choice given at build time. */#include "generated/javavm/include/gc_config.h"#include "javavm/include/gc_common.h"#include "javavm/include/gc/gc_impl.h"#include "javavm/include/gc/generational/generational.h"#include "javavm/include/gc/generational/gen_semispace.h"#include "javavm/include/gc/generational/gen_markcompact.h"#include "javavm/include/porting/memory.h"#include "javavm/include/porting/threads.h"#if !CVM_USE_MMAP_APIS#define CVMmemInit()#define CVMmemPageSize() NUM_BYTES_PER_CARD/* Purpose: Uses calloc() to simulate the reservation of memory. */staticvoid *CVMgenMap(size_t requestedSize, size_t *mappedSize){ void *mem; void *alignedMem; mem = calloc(1, requestedSize + CVMmemPageSize()); if (mem == NULL) { return NULL; } *mappedSize = requestedSize; /* We want to reserve at least the size of a pointer to store the actual address of the start of the allocated area. After that, we will realigned the pointer to the next alignment of NUM_BYTES_PER_CARD. Note: the padding in the the allocated size above is to allow room for this. */ alignedMem = (CVMUint8 *)mem + sizeof(void *); alignedMem = (void *)CVMpackSizeBy((CVMAddr)alignedMem, CVMmemPageSize()); /* Store the actual calloc'ed pointer just before the start of the "mapped" memory: */ ((void **)alignedMem)[-1] = mem; return alignedMem;}/* Purpose: Releases the memory that was calloc'ed to simulate the reservation of memory. */staticvoid *CVMgenUnmap(void *addr, size_t requestedSize, size_t *unmappedSize){ /* Retrieve the actual calloc'ed pointer from just before the start of the "mapped" memory tobe used by free(): */ void *mem = ((void **)addr)[-1]; free(mem); *unmappedSize = requestedSize; return addr;}#define CVMmemMap CVMgenMap#define CVMmemUnmap CVMgenUnmap#define CVMmemCommit(addr, requestedSize, committedSize) \ (CVMassert(CVM_FALSE /* Should not be used: CVMmemCommit() */), NULL)#define CVMmemDecommit(addr, requestedSize, decommittedSize) \ (CVMassert(CVM_FALSE /* Should not be used: CVMmemDecommit() */), NULL)#endif /* !CVM_USE_MMAP_APIS *//* * Define to GC on every n-th allocation try *//*#define CVM_GEN_GC_ON_EVERY_ALLOC*/#define CVM_GEN_NO_ALLOCS_UNTIL_GC 1#ifdef CVM_JVMPI/* The number of live objects at the end of the GC cycle: NOTE: This is implemented in this GC by keeping an active count of the objects in the heap. If an object is allocated, the count is incremented. When the object is GC'ed, the count is decremented. */CVMUint32 liveObjectCount;#endif#ifdef CVM_JITvoid** const CVMgcCardTableVirtualBasePtr = (void**)&CVMglobals.gc.cardTableVirtualBase;#endif#define roundUpToPage(x, pageSize) CVMpackSizeBy((x), pageSize)#define roundDownToPage(x, pageSize) \ CVMpackSizeBy(((CVMAddr)(x) - (pageSize-1)), pageSize)#define isPageAligned(x, pageSize) \ ((CVMAddr)(x) == CVMpackSizeBy((CVMAddr)(x), pageSize))#if CVM_USE_MMAP_APISstatic CVMUint32CVMgcimplSetSizeAndWatermarks(CVMGCGlobalState *gc, CVMUint32 newSize, CVMUint32 currentUsage);#endif/* * Initialize GC global state */voidCVMgcimplInitGlobalState(CVMGCGlobalState* globalState){ CVMtraceMisc(("GC: Initializing global state for generational GC\n"));}/* * %comment: f010 */voidCVMgenClearBarrierTable(){ memset(CVMglobals.gc.cardTable, CARD_CLEAN_BYTE, CVMglobals.gc.cardTableSize); memset(CVMglobals.gc.objectHeaderTable, 0, CVMglobals.gc.cardTableSize);}#ifdef CVM_DEBUG_ASSERTSvoid CVMgenAssertBarrierTableIsClear(){ CVMUint32 i; for (i = 0; i < CVMglobals.gc.cardTableSize; i++) { CVMassert(CVMglobals.gc.cardTable[i] == CARD_CLEAN_BYTE); CVMassert(CVMglobals.gc.objectHeaderTable[i] == 0); }}#endif /* CVM_DEBUG_ASSERTS *//* * Update the object headers table for objects in range [startRange, endRange) */voidCVMgenBarrierObjectHeadersUpdate(CVMGeneration* gen, CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMUint32* startRange, CVMUint32* endRange){ CVMJavaVal32* curr = (CVMJavaVal32*)startRange; CVMtraceGcCollect(("GC[SS,full]: " "object headers update [%x,%x)\n", startRange, endRange)); while (curr < (CVMJavaVal32*)endRange) { CVMObject* currObj = (CVMObject*)curr; CVMClassBlock* currCb = CVMobjectGetClass(currObj); CVMUint32 objSize = CVMobjectSizeGivenClass(currObj, currCb); CVMObject* currObjEnd = (CVMObject*)(curr + objSize / sizeof(CVMJavaVal32)); CVMUint8* startCard = (CVMUint8*)CARD_TABLE_SLOT_ADDRESS_FOR(currObj); CVMUint8* endCard = (CVMUint8*)CARD_TABLE_SLOT_ADDRESS_FOR(currObjEnd); /* * I don't need to do anything if object starts on a card boundary * since the object headers table is initialized to 0's. Otherwise * I'd have to make a special case of it here, and check * whether cardBoundary == curr. */ /* If the object resides entirely within the same card i.e. the startCard is the same as the endCard, then there is nothing to do. We only need to handle the case where the object spans a card boundary. */ if (startCard != endCard) { CVMUint8* card; CVMInt8* hdr; CVMJavaVal32* cardBoundary; CVMInt32 numCards; /* Object crosses card boundaries. Find the first card for which the header table entry would be >= 0. It's either startCard in case currObj is at a card boundary, or startCard+1 if currObj is not at a card boundary. */ cardBoundary = ROUND_UP_TO_CARD_SIZE(currObj); card = (CVMUint8*)CARD_TABLE_SLOT_ADDRESS_FOR(cardBoundary); CVMassert((card == startCard) || (card == startCard + 1)); if (card == CVMglobals.gc.cardTableEnd) { CVMassert(card == startCard + 1); return; /* nothing to do -- we are at the edge */ } hdr = HEADER_TABLE_SLOT_ADDRESS_FOR_CARD(card); CVMassert(hdr >= CVMglobals.gc.objectHeaderTable); CVMassert(hdr < CVMglobals.gc.objectHeaderTable + CVMglobals.gc.cardTableSize); /* Mark the number of words from this header */ CVMassert(cardBoundary >= curr); CVMassert(cardBoundary - curr <= 127); *hdr = (CVMUint8)(cardBoundary - curr); /* Now go through all the rest of the cards that the object spans, and inform them that the start of the object is here */ card += 1; hdr += 1; numCards = -1; if (endCard == CVMglobals.gc.cardTableEnd) { endCard--; } if (endCard - card < 127) { /* Fast common case, <= 127 iterations. */ while (card <= endCard) { CVMassert(hdr < CVMglobals.gc.objectHeaderTable + CVMglobals.gc.cardTableSize); *hdr = numCards; /* Plant back-pointers */ numCards--; hdr++; card++; } CVMassert(numCards >= -128); } else { /* Slower rarer case for large objects */ while (card <= endCard) { CVMassert(hdr < CVMglobals.gc.objectHeaderTable + CVMglobals.gc.cardTableSize); *hdr = numCards; /* Plant back-pointers */ numCards--; if (numCards == -127) { numCards = -1; /* Chain reaction! */ } hdr++; card++; } } CVMassert(card == endCard + 1); CVMassert(HEADER_TABLE_SLOT_ADDRESS_FOR_CARD(card) == hdr); } curr += objSize / sizeof(CVMJavaVal32); } CVMassert(curr == (CVMJavaVal32*)endRange); /* This had better be exact */}/* * Scan objects in contiguous range, without doing any special handling. * * Scan from head of objStart. Scan only within [regionStart,regionEnd). * Call out to 'callback' only if the reference found is * not in the range [oldGenLower, oldGenHigher) * (i.e. an old to young pointer). * * Returns what flag the card should contain based on what its scan * turned up. */static CVMUint32scanAndSummarizeObjectsOnCard(CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMJavaVal32* objStart, CVMGenSummaryTableEntry* summEntry, CVMJavaVal32* regionStart, CVMJavaVal32* regionEnd, CVMUint32* oldGenLower, CVMRefCallbackFunc callback, void* callbackData){ CVMUint32 scanStatus = CARD_CLEAN_BYTE; CVMUint32 numRefs = 0; CVMJavaVal32* curr = (CVMJavaVal32*)objStart; CVMJavaVal32* top = regionEnd; CVMJavaVal32* cardBoundary = CARD_BOUNDARY_FOR(regionStart); CVMGeneration *youngGen = CVMglobals.gc.CVMgenGenerations[0]; CVMJavaVal32* youngGenStart = (CVMJavaVal32 *)youngGen->heapBase; CVMJavaVal32* youngGenEnd = (CVMJavaVal32 *)youngGen->heapTop; /* sanity check */ CVMassert(SUMMARY_TABLE_SLOT_ADDRESS_FOR_CARD( CARD_TABLE_SLOT_ADDRESS_FOR(regionStart)) == summEntry); CVMassert(summEntry >= CVMglobals.gc.summaryTable); CVMassert(summEntry < &(CVMglobals.gc.summaryTable[CVMglobals.gc.cardTableSize])); CVMtraceGcCollect(("GC[SS,full]: " "Scanning card range [%x,%x), objStart=0x%x\n", regionStart, regionEnd, objStart)); /* * Clear summary table entry. * The summary table is 0xff terminated. */#if (CVM_GENGC_SUMMARY_COUNT == 4) summEntry->intVersion = 0xffffffff;#else memset(summEntry->offsets, 0xff, CVM_GENGC_SUMMARY_COUNT);#endif /* * And scan the objects on the card */ while (curr < top) { CVMObject* currObj = (CVMObject*)curr; CVMClassBlock* currCb = CVMobjectGetClass(currObj); CVMUint32 objSize = CVMobjectSizeGivenClass(currObj, currCb); /* Note: No need to mark the card for the class of the object. All classes are scanned for the youngGen, and the oldGen does a comprehensive root scan which include classes of objects found in the root tree. Hence, the cardTable need not concern itself with classes. */ /* Special-case large arrays of refs */ if ((objSize >= NUM_BYTES_PER_CARD) && ((CVMcbGcMap(currCb).map & CVM_GCMAP_FLAGS_MASK) == CVM_GCMAP_ALLREFS_FLAG)) { CVMArrayOfRef* arr = (CVMArrayOfRef*)currObj; CVMObject** arrStart = (CVMObject**)arr->elems; CVMObject** arrEnd = arrStart + CVMD_arrayGetLength(arr); CVMObject** scanStart; CVMObject** scanEnd; CVMObject** scanPtr; CVMassert(CVMisArrayClass(currCb)); /* Get the intersection of the array data and the card region */ if (arrStart < (CVMObject**)regionStart) { scanStart = (CVMObject**)regionStart; } else { scanStart = arrStart; } if (arrEnd > (CVMObject**)regionEnd) { scanEnd = (CVMObject**)regionEnd; } else { scanEnd = arrEnd; } CVMassert((scanStart <= scanEnd) || (arrStart >= (CVMObject**)regionEnd)); CVMassert(scanEnd <= arrEnd); CVMassert(scanEnd <= (CVMObject**)regionEnd); CVMassert(scanStart >= arrStart); CVMassert(scanStart >= (CVMObject**)cardBoundary); CVMassert(scanStart >= (CVMObject**)regionStart); /* Scan segment [scanStart, scanEnd) In the rare case where arrStart >= regionEnd and currObj < regionEnd, scanStart becomes larger than scanEnd, at which point this loop does not get executed. */ for (scanPtr = scanStart; scanPtr < scanEnd; scanPtr++) { CVMJavaVal32* ref = (CVMJavaVal32*) *scanPtr; /* Only scan youngGen pointers: */ if ((ref >= youngGenStart) && (ref < youngGenEnd)) { if (numRefs < CVM_GENGC_SUMMARY_COUNT) { summEntry->offsets[numRefs] = (CVMUint8) ((CVMJavaVal32*)scanPtr - cardBoundary); } (*callback)(scanPtr, callbackData);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?