📄 collectordebug.c
字号:
/* * Copyright (c) 1998-2002 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * * Use is subject to license terms. *//*========================================================================= * SYSTEM: KVM * SUBSYSTEM: Memory management * FILE: collectorDebug.c * OVERVIEW: Debug version of the garbage collector. This * implementation can be used in place of the standard * garbage collector to find spurious pointers elsewhere * in the codebase. This implementation is particularly * useful if you add your own native functions to the KVM * and you want to make sure that your functions access * memory correctly. Be sure to turn the EXCESSIVE_GARBAGE- * COLLECTION mode on to find bugs fast. * * The code here also includes an implementation of the * classic Cheney two-space copying collector. This * collector is very fast and simple, but it requires two * semi-spaces (two memory areas of the same size) to operate. * AUTHOR: Frank Yellin *=======================================================================*//*========================================================================= * For detailed explanation of the memory system, see Garbage.h *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include <global.h>/*========================================================================= * Definitions and declarations *=======================================================================*//* The number of separate memory spaces */#define SPACE_COUNT 10#define PERMANENT_MEMORY_SIZE 1024 * 1024#define MEMORY_SIZE 256 * 1024#define OBJECT_HEADER(object) ((cell *)(object))[-HEADERSIZE]#define inTargetSpace(object) \ (((cell *)(object) >= TargetSpace) && (((cell *)(object) < TargetSpaceFreePtr)))#define OVERWRITE_FREE_MEMORY (ENABLEPROFILING || INCLUDEDEBUGCODE)#define OVERWRITE_FREE_MEMORY_BYTE 0xF1#define OVERWRITE_FREE_MEMORY_WORD 0xF1F1F1F1#define PTR_OFFSET(ptr, offset) ((void *)((char *)ptr + offset))#define PTR_DELTA(ptr1, ptr2) ((char *)(ptr1) - (char *)ptr2)/*========================================================================= * Variables *=======================================================================*/cell* AllHeapStart; /* Start of first heap */cell* CurrentHeap; /* Bottom of current heap */cell* CurrentHeapEnd; /* End of current heap */cell* CurrentHeapFreePtr; /* Next allocation in current space */cell* PermanentSpace; /* Beginning of permanent space */cell* PermanentSpaceFreePtr;cell* AllHeapEnd;WEAKPOINTERLIST WeakPointers;static cell* TargetSpace;static cell* TargetSpaceFreePtr;long nHeapSize; /* Size of each heap */#if INCLUDEDEBUGCODEstatic void checkValidHeapPointer(cell *number);int NoAllocation = 0;#else#define checkValidHeapPointer(x)#define NoAllocation 0#endif#if EXCESSIVE_GARBAGE_COLLECTIONbool_t excessivegc;#endif /* EXCESSIVE_GARBAGE_COLLECTION */#if ASYNCHRONOUS_NATIVE_FUNCTIONS#include <async.h>extern ASYNCIOCB IocbRoots[];#endif/*========================================================================= * Static functions (private to this file) *=======================================================================*/static void updatePointer(void *ptr);static void updateMonitor(OBJECT object);static void copyRootObjects(void);static void copyNonRootObjects(void);static void copyWeakPointerLists(void);static void updateThreadAndStack(THREAD thisThread);static void expandPermanentMemory(cell *newPermanentSpace);/*========================================================================= * Heap initialization operations *=======================================================================*/#if CHENEY_TWO_SPACEvoid* TheHeap;#endif;void InitializeHeap(void){#if CHENEY_TWO_SPACE long VMHeapSize = RequestedHeapSize * 2; AllHeapStart = allocateHeap(&VMHeapSize, &TheHeap); if (TheHeap == NIL) { fatalVMError(KVM_MSG_NOT_ENOUGH_MEMORY); } /* Each space is 45% of the total, rounded to a multiple of 32 */ nHeapSize = (((VMHeapSize * 9) / 20) >> 5) << 5; PermanentSpace = PTR_OFFSET(AllHeapStart, 2 * nHeapSize); AllHeapEnd = PTR_OFFSET(AllHeapStart, VMHeapSize);#else nHeapSize = MEMORY_SIZE; AllHeapStart = allocateVirtualMemory_md(MEMORY_SIZE * SPACE_COUNT + PERMANENT_MEMORY_SIZE); PermanentSpace = PTR_OFFSET(AllHeapStart, MEMORY_SIZE * SPACE_COUNT); AllHeapEnd = PTR_OFFSET(PermanentSpace, PERMANENT_MEMORY_SIZE);#endif /* CHENEY_TWO_SPACE */ /* We start in the first semi space */ CurrentHeap = AllHeapStart; CurrentHeapFreePtr = AllHeapStart; CurrentHeapEnd = PTR_OFFSET(CurrentHeap, nHeapSize); /* Permanent space grows from the end toward the middle; */ PermanentSpaceFreePtr = AllHeapEnd; memset((char *)PermanentSpace, 0, PTR_DELTA(AllHeapEnd, PermanentSpace));#if !CHENEY_TWO_SPACE /* Protect all of the heaps except for the current one */ protectVirtualMemory_md(CurrentHeapEnd, MEMORY_SIZE * (SPACE_COUNT - 1), PVM_NoAccess);#endif #if INCLUDEDEBUGCODE if (tracememoryallocation) { Log->allocateHeap(MEMORY_SIZE, (long)CurrentHeap, (long)CurrentHeapEnd); } NoAllocation = 0;#endif}void FinalizeHeap(void){#if CHENEY_TWO_SPACE freeHeap(TheHeap);#else freeVirtualMemory_md(AllHeapStart, MEMORY_SIZE * SPACE_COUNT + PERMANENT_MEMORY_SIZE);#endif}/*========================================================================= * Memory allocation operations *=======================================================================*//*========================================================================= * FUNCTION: mallocHeapObject() * TYPE: public memory allocation operation * OVERVIEW: Allocate a contiguous area of n cells in the dynamic heap. * INTERFACE: * parameters: size: the requested object size in cells, * type: garbage collection type of the object * returns: pointer to newly allocated area, or * NIL is allocation fails. * COMMENTS: Allocated data area is not initialized, so it * may contain invalid heap references. *=======================================================================*/cell* mallocHeapObject(long size, GCT_ObjectType type)/* Remember: size is given in CELLs rather than bytes */{ cell* thisChunk; long realSize; realSize = size + HEADERSIZE;#if INCLUDEDEBUGCODE if (NoAllocation > 0) { fatalError(KVM_MSG_CALLED_ALLOCATOR_WHEN_FORBIDDEN); }#endif /* INCLUDEDEBUGCODE */#if EXCESSIVE_GARBAGE_COLLECTION if (excessivegc && CurrentHeapFreePtr > CurrentHeap) { garbageCollect(0); }#endif /* EXCESSIVE_GARBAGE_COLLECTION */ if (CurrentHeapEnd - CurrentHeapFreePtr < realSize) { garbageCollect(0); if (CurrentHeapEnd - CurrentHeapFreePtr < realSize) { return NULL; } } thisChunk = CurrentHeapFreePtr; CurrentHeapFreePtr += realSize; /* Augment the object header with gc type information */ *thisChunk = (type << TYPE_SHIFT) + (size << TYPEBITS);#if INCLUDEDEBUGCODE if (tracememoryallocation) { Log->allocateObject((long)thisChunk, (long)size+HEADERSIZE, (int)type, (long)thisChunk, memoryFree()); }#endif /* INCLUDEDEBUGCODE */#if ENABLEPROFILING DynamicObjectCounter += 1; DynamicAllocationCounter += (size+HEADERSIZE)*CELL;#endif /* ENABLEPROFILING */ return thisChunk + HEADERSIZE;}/*========================================================================= * FUNCTION: callocPermanentObject() * TYPE: public memory allocation operation * OVERVIEW: Allocate a contiguous area of n cells in the permanent heap * INTERFACE: * parameters: size: the requested object size in cells, * returns: pointer to newly allocated area, *=======================================================================*/cell*callocPermanentObject(long size) { cell* result = PermanentSpaceFreePtr - size; PermanentSpaceFreePtr = result; if (result < PermanentSpace) { /* We have to expand permanent memory */ cell* temp = PermanentSpace; do { temp = PTR_OFFSET(temp, -0x800); } while (temp > result); expandPermanentMemory(temp); } return result;}/*========================================================================= * Garbage collection operations *=======================================================================*//*========================================================================= * FUNCTION: garbageCollect * TYPE: public garbage collection function * OVERVIEW: Perform mark-and-sweep garbage collection. * INTERFACE: * parameters: int moreMemory: the amount by which the heap * size should be grown during garbage collection * (this feature is not supported in the mark-and-sweep * collector). * returns: <nothing> *=======================================================================*/voidgarbageCollectForReal(int moreMemory){ TargetSpace = (CurrentHeapEnd == PermanentSpace) ? AllHeapStart : CurrentHeapEnd; TargetSpaceFreePtr = TargetSpace;#if !CHENEY_TWO_SPACE protectVirtualMemory_md(TargetSpace, MEMORY_SIZE, PVM_ReadWrite);#endif WeakPointers = NULL; copyRootObjects(); /* Mark all the objects pointed at by the root objects, or pointed at * by objects that are pointed at by root objects. . . . */#if INCLUDEDEBUGCODE if (tracegarbagecollectionverbose) { Log->fprintf(stdout, "Scanning heap for additional objects\n"); }#endif copyNonRootObjects(); copyWeakPointerLists();#if !CHENEY_TWO_SPACE protectVirtualMemory_md(CurrentHeap, MEMORY_SIZE, PVM_NoAccess);#endif CurrentHeap = TargetSpace; CurrentHeapFreePtr = TargetSpaceFreePtr; CurrentHeapEnd = PTR_OFFSET(CurrentHeap, nHeapSize);}static voidexpandPermanentMemory(cell *newPermanentSpace) {#if CHENEY_TWO_SPACE int newHeapBytes = PTR_DELTA(newPermanentSpace, AllHeapStart); int newHeapSize = newHeapBytes / 2; cell *newHeapSpace1 = PTR_OFFSET(AllHeapStart, newHeapSize); int count; for (count = 0; ; count++) { if (CurrentHeap == AllHeapStart) { /* We're currently allocating into HeapSpace 0 */ if (CurrentHeapFreePtr <= newHeapSpace1) { /* We can just adjust the pointers */ CurrentHeapEnd = newHeapSpace1; break; } else if (count == 0) { /* Try compacting the heap to see if that helps */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -