/* * @(#)gc.h 1.10 97/01/24 * * Copyright (c) 1995, 1996 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. * * CopyrightVersion 1.1_beta * */ #ifndef _GC_H_ #define _GC_H_ #include "gc_md.h" /* * Lock against heap modification. */ extern sys_mon_t *_heap_lock; #define HEAP_LOCK_INIT() monitorRegister(_heap_lock, "Heap lock") #define HEAP_LOCK() sysMonitorEnter(_heap_lock) #define HEAP_UNLOCK() sysMonitorExit(_heap_lock) #define HEAP_LOCKED() sysMonitorEntered( _heap_lock) /* * Define this if you want the mark phase to detect pointers into the * interior of objects. */ /* #define CHECK_INTERIOR_POINTERS */ #define OBJECTGRAIN 8 #define HANDLEGRAIN 8 #define BITSPERCHAR 8 /* * Types of overflows: we might respond to an overflow of a particular * error differently, e.g. expanding only the overflowing area. */ #define OVERFLOW_NONE 0 #define OVERFLOW_OBJECTS 1 #define OVERFLOW_HANDLES 2 /* * Possible actions to take on overflows. manageAllocFailure() * decides between these. */ #define OVERFLOW_ACT_FAIL 0 #define OVERFLOW_ACT_GC 1 #define OVERFLOW_ACT_FINALIZE 2 #define OVERFLOW_ACT_REFS 3 #define OVERFLOW_ACT_EXPAND 4 #define OVERFLOW_ACT_DESPERATE 5 /* * Memory block header (bottom three bits are flags): * * ------------------------------------------------------------- * | <--- length --->| pinned | <- obj swapped -> | <- free -> | * ------------------------------------------------------------- * 31 3 2 1 0 */ typedef long hdr; #define obj_geth(p) (*((hdr *)(p))) #define obj_seth(p, h) (*((hdr *)(p)) = (h)) #define h_len(h) ((h) & ~(OBJECTGRAIN-1)) #define h_free(h) ((h) & 1) #define h_bumplen(h, l) ((h) += (l)) #define obj_len(p) (obj_geth(p)&~(OBJECTGRAIN-1)) #define obj_setlf(p, l, f) (obj_geth(p) = (l)|(f)) #define obj_bumplen(p, l) (obj_geth(p) += (l)) #define obj_free(p) (obj_geth(p)&1) #define obj_setfree(p) (obj_geth(p) |= 1) #define obj_clearfree(p) (obj_geth(p) &= ~1) #define obj_pinned(p) (obj_geth(p) & 4) #define obj_pin(p) (obj_geth(p) |= 4) #define obj_unpin(p) (obj_geth(p) &= ~4) /* * The marking code relies upon the values representing the three mark * states to be ordered numerically: NoMark < SoftMark < HardMark. */ #define NoMark 0 #define SoftMark 1 #define HardMark 3 #define MarkPtr(p, v) _MarkPtr(((unsigned int) (p) & ~(OBJECTGRAIN - 1)), v) #define ClearMarkPtr(p, v) _ClearMarkPtr(((unsigned int)(p)&~(OBJECTGRAIN-1)),v) #define IsMarked(p) _IsMarked((unsigned int) (p) & ~(OBJECTGRAIN - 1)) #define SOFTREFBAGSIZE 200 /* max number of soft refs to kill in one cycle */ #ifndef PAGED_HEAPS /************ CONTIGUOUS HEAPS: ********************/ #define ValidObject(p) ((((int)(p)) & (OBJECTGRAIN-1)) == 0 && \ (unsigned char *)(p) >= opmin && \ (unsigned char *)(p) < opmax) #define ValidHandle(p) (((int) (p) & (sizeof(JHandle)-1)) == 0 && \ (unsigned char *)(p) >= hpmin && \ (unsigned char *)(p) <= hpmax) /* ValidHorO() assumes OBJECTGRAIN=sizeof(JHandle)... */ #define ValidHorO(p) (((int) (p) & (OBJECTGRAIN-1)) == 0 && \ (unsigned char *)(p) >= hpmin && \ (unsigned char *)(p) <= opmax) #define SetLimits() \ register unsigned char *const opmin = opool, \ *const opmax = opoollimit, \ *const hpmin = hpool, \ *const hpmax = hpoollimit-sizeof(JHandle) #define POP_FREE_HANDLE(hp) \ hp = (JHandle *)hpoolfreelist; \ if (hp) { \ hpoolfreelist = (unsigned char *)hp->methods; \ } #define PUSH_FREE_HANDLE(hp) \ hp->methods = (struct methodtable *)hpoolfreelist; \ hpoolfreelist = (unsigned char *)hp; /* Mark bit access assumes contiguity of handles and objects */ #define MARKINDEX(p) (((unsigned char *)(p) - hpmin) >> 7) #define BITOFFSET(p) ((((unsigned char *)(p) - hpmin) >> 2) & 0x1e) #define _MarkPtr(p, v) (markbits[MARKINDEX(p)] |= (v) << BITOFFSET(p)) #define _ClearMarkPtr(p, v) (markbits[MARKINDEX(p)] &= ~((v) << BITOFFSET(p))) #define _IsMarked(p) ((markbits[MARKINDEX(p)] >> BITOFFSET(p)) &3) /* set the second word in an object (from ptr to header) to 0x55555555 */ #define CHECK_WORD_INDEX 1 #define MAP_OVER_HANDLES_FROM_START(MO_hp) { \ JHandle *MOH_limit = (JHandle *) hpmax; \ for (MO_hp = (JHandle *) hpool; MO_hp <= MOH_limit; MO_hp++) { #define END_MAP_OVER_HANDLES_FROM_START \ } /* end for */ \ } /* end MAP_OVER_HANDLES_FROM_START */ #define MAP_OVER_OBJECTS_FROM_START(p) { \ unsigned char *MOO_limit = opmax; \ unsigned char *MOO_start = opmin; \ for (p = opmin; \ p < MOO_limit; \ p += obj_len(p)) { #define END_MAP_OVER_OBJECTS_FROM_START \ } /* end for */ \ } /* end END_MAP_OVER_OBJECTS_FROM_START */ #else /************ PAGED HEAPS: ********************/ /* gc philosophy makes it necessary to detect if an arbitrary int is * (possibly) a handle or object ref. * A value is (possibly) valid if it is properly aligned, and it * points into a page that has a page map entry of the proper type. */ /* assumes ValidHorO already */ #define GetPageMapEntry(p) \ (page_map[((int)(p) - (int)mem_base) >> PTR_2_PAGE_SHIFT]) #define ValidObject(p) ((((int)(p)) & (OBJECTGRAIN-1)) == 0 && \ (void *)(p) >= mem_base && \ (void *)(p) < mem_top && \ (GetPageMapEntry((p)).chunk_size > 0)) #define ValidHandle(p) (((((int)(p)) & (HANDLEGRAIN-1)) == 0) && \ ((void *)(p) >= mem_base) && \ ((void *)(p) < mem_top) && \ (GetPageMapEntry((p)).chunk_size < 0)) /* ValidHorO() assumes OBJECTGRAIN == HANDLEGRAIN... */ #define ValidHorO(p) ((((int)(p)) & (HANDLEGRAIN-1)) == 0 && \ (void *)(p) >= mem_base && \ (void *)(p) < mem_top && \ (GetPageMapEntry((p)).chunk_size != 0)) #define SetLimits() int SL_dufus = 0 /* assumes ValidHorO already */ #define ChunkBase(p) (void *) \ (((int)(p) & ~(PAGE_ALIGNMENT - 1)) - \ (GetPageMapEntry((p)).page_number << PTR_2_PAGE_SHIFT)) /* curHanBlkP must be set in advance!!! */ #define POP_FREE_HANDLE(hp) \ hp = (JHandle *)curHanBlkP->freePtr; \ if (hp) { \ curHanBlkP->freePtr = (unsigned char *)hp->methods; \ } /* Can only be called within a MAP_OVER_HANDLES_FROM_START loop * - uses MOH_chunk instead of curHanBlkP for efficiency. */ #define PUSH_FREE_HANDLE(hp) \ hp->methods = (struct methodtable *)MOH_chunk->freePtr; \ MOH_chunk->freePtr = (unsigned char *)hp; #define MARKINDEX(p) (((int)(p) & (PAGE_ALIGNMENT - 1)) >> 7) #define BITOFFSET(p) ((((int)(p) & (PAGE_ALIGNMENT - 1)) >> 2) & 0x1e) #define _MarkPtr(p, v) (GetPageMapEntry(p).mark_bits[MARKINDEX(p)] |= \ (v) << BITOFFSET(p)) #define _ClearMarkPtr(p, v) (GetPageMapEntry(p).mark_bits[MARKINDEX(p)] &= \ ~((v) << BITOFFSET(p))) #define _IsMarked(p) ((GetPageMapEntry(p).mark_bits[MARKINDEX(p)] \ >> BITOFFSET(p)) & 3) /* # of bytes of markbits we need per page: */ #define MARK_BITS_SIZE ((PAGE_ALIGNMENT / (OBJECTGRAIN * BITSPERCHAR)) * 2) /* * Part of Java memory management and garbage collection. * * This supports a discontiguous gcable heap, which is useful for the * Mac OS, or other platforms without good memory mapping support. * * CHUNKS: * Memory is requested from the OS in "Chunks" of n pages, which are * PAGE_ALIGNMENT aligned and sized. Handles and objects are allocated out of * different chunks. When more memory is needed, additional chunks can be * allocated. When chunks are free, they may be returned to the OS. Chunks * don't need to be contiguous. Handle chunks and object chunks are linked * into seperate, doubly linked lists, which are sorted by chunk address. On * platforms without real "memalign" support, there may be unaligned (wasted) * space that precedes the true chunk that we can use for something else * (markbits come to mind). */ /* fields marked ### MUST BE OBJECT AND/OR HANDLE GRAIN ALIGNED */ typedef struct CHUNK_BLK { /* a chunk of pages */ void* chunkHandle; /* OS handle to this chunk */ struct CHUNK_BLK *nextPtr; /* ptr to next chunk header */ struct CHUNK_BLK *prevPtr; /* ptr to previous chunk header */ long chunkFlags; /* misc flags */ long allocSize; /* == (endPtr - startPtr)### */ long freeCnt; /* # of free bytes in this chunk */ unsigned char *startPtr; /* ptr to starting byte### */ unsigned char *endPtr; /* ptr past last byte### */ unsigned char *freePtr; /* ptr to first free space CANDIDATE * (may not really be free), or it might be a ptr to a free list * of objects, depending on phase of the moon. */ /* users may modify start and end ptrs, but not this one: */ unsigned char *physEndPtr; #ifdef WASTED_SPACE_IN_LEADER /* WARNING: clearLocalMarkBits assumes that only markbits are stored * in the waste !!! */ unsigned char *wasteStartPtr; /* ptr to starting wasted byte */ unsigned char *wasteFreePtr; /* ptr to first free wasted byte */ /* wasteEndPtr == the ChunkBlk pointer */ #endif /* WASTED_SPACE_IN_LEADER*/ } ChunkBlk, *ChunkBlkP; /* CHUNK_BLK->chunkFlags bits: */ /* set this bit in chunkFlags if any objects in the chunk are pinned */ #define CHUNK_PINNED 1 /* doubly-linked list of handle chunks, in address order: */ extern ChunkBlkP firstHanBlkP; extern ChunkBlkP lastHanBlkP; extern ChunkBlkP curHanBlkP; /* doubly-linked list of object chunks, in address order: */ extern ChunkBlkP firstObjBlkP; extern ChunkBlkP lastObjBlkP; extern ChunkBlkP curObjBlkP; /* store this into the last two words of the chunk to detect overwrites */ /* Odd to make a poor pointer, 111 in the low bits looks like a swapped * free block if a header! */ #define ALMOST_WORD 0x77777777 #define ULTIMATE_WORD 0xBAADDEED /* Why not. */ /* set the third word in an object (from ptr to header) to 0x55555555 */ #define CHECK_WORD_INDEX 2 /* Macros to abstract out looping over all handles or objects. * Note that you can't "break" out of this loop. Use goto or return instead. */ #define MAP_OVER_HANDLES_FROM_START(MO_hp) { \ ChunkBlkP MOH_chunk = firstHanBlkP; \ JHandle *MOH_limit; \ do { \ for (MO_hp = (JHandle *)MOH_chunk->startPtr, \ MOH_limit = (JHandle *)MOH_chunk->endPtr; \ MO_hp < MOH_limit; MO_hp++) { #define END_MAP_OVER_HANDLES_FROM_START \ } /* end for */ \ MOH_chunk = MOH_chunk->nextPtr; \ } while (MOH_chunk != firstHanBlkP); \ } /* end MAP_OVER_HANDLES_FROM_START */ #define MAP_OVER_OBJECTS_FROM_START(MO_p) { \ ChunkBlkP MOO_chunk = firstObjBlkP; \ unsigned char *MOO_limit; \ unsigned char *MOO_start; \ do { \ for ((MO_p) = MOO_chunk->startPtr, \ MOO_start = MOO_chunk->startPtr, \ MOO_limit = MOO_chunk->endPtr; \ (MO_p) < MOO_limit; \ (MO_p) += obj_len(MO_p)) { #define END_MAP_OVER_OBJECTS_FROM_START \ } /* end for */ \ MOO_chunk = MOO_chunk->nextPtr; \ } while (MOO_chunk != firstObjBlkP); \ } /* end END_MAP_OVER_OBJECTS_FROM_START */ #endif /************ END PAGED HEAPS ********************/ #ifdef WASTED_SPACE_IN_LEADER /* following functions defined in gc_md.c: */ void initWastedSpaceInChunk(ChunkBlkP chunk); void sysCheckWastedSpace(ChunkBlkP chunk); void clearLocalMarkBits(void); void* allocMarkBitsLocally(ChunkBlkP blkP); #else #define initWastedSpaceInChunk(xxx) 0 #define sysCheckWastedSpace(xxx) 0 #define clearLocalMarkBits() 0 #define allocMarkBitsLocally(xxx) 0 #endif #endif /* !_GC_H_ */