⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gc-incremental.c

📁 kaffe是一个java虚拟机的源代码。里面包含了一些java例程和标准的java包。
💻 C
📖 第 1 页 / 共 2 页
字号:
	STOPWORLD();	/* measure time */	startTiming(&gc_time, "gctime-scan");	/* Walk all objects on the finalizer list */	for (unit = gclists[finalise].cnext;	     unit != &gclists[finalise]; unit = nunit) {		nunit = unit->cnext;		gcMarkObject(gcif, UTOMEM(unit));	}	(*walkRootSet)(gcif);}/* * Finish off the GC process.  Any unreached (white) objects are moved * for finalising and the finaliser woken. * The reached (black) objects are moved onto the now empty white list * and recoloured white. */staticvoidfinishGC(Collector *gcif){	gc_unit* unit;	gc_block* info;	int idx;	/* There shouldn't be any grey objects at this point */	assert(gclists[grey].cnext == &gclists[grey]);	/* 	 * Any white objects should now be freed, but we cannot call	 * gc_heap_free here because we might block in gc_heap_free, 	 * which would leave the white list unprotected.	 * So we move them to a 'mustfree' list from where we'll pull them	 * off later.	 *	 * XXX: this is so silly it hurts.  Jason has a fix.	 */	while (gclists[white].cnext != &gclists[white]) {		unit = gclists[white].cnext;		UREMOVELIST(unit);		info = GCMEM2BLOCK(unit);		idx = GCMEM2IDX(info, unit);		assert(GC_GET_COLOUR(info, idx) == GC_COLOUR_WHITE);		assert(GC_GET_STATE(info, idx) == GC_STATE_NORMAL);		gcStats.freedmem += GCBLOCKSIZE(info);		gcStats.freedobj += 1;		UAPPENDLIST(gclists[mustfree], unit);		OBJECTSTATSREMOVE(unit);	}	/* 	 * Now move the black objects back to the white queue for next time.	 * Note that all objects that were eligible for finalization are now	 * black - this is so because we marked and then walked them.	 * We recognize them by their "INFINALIZE" state, however, and put	 * them on the finalise list.	 */	while (gclists[black].cnext != &gclists[black]) {		unit = gclists[black].cnext;		UREMOVELIST(unit);		info = GCMEM2BLOCK(unit);		idx = GCMEM2IDX(info, unit);		assert(GC_GET_COLOUR(info, idx) == GC_COLOUR_BLACK);		if (GC_GET_STATE(info, idx) == GC_STATE_INFINALIZE) {			gcStats.finalmem += GCBLOCKSIZE(info);			gcStats.finalobj += 1;			UAPPENDLIST(gclists[finalise], unit);		}		else {			UAPPENDLIST(gclists[white], unit);		}		GC_SET_COLOUR(info, idx, GC_COLOUR_WHITE);	}	/* this is where we'll stop locking out other threads 	 * measure gc time until here.  This is not quite accurate, as	 * it excludes the time to sweep objects, but lacking	 * per-thread timing it's a reasonable thing to do.	 */	stopTiming(&gc_time);	/* 	 * Now that all lists that the mutator manipulates are in a	 * consistent state, we can reenable the mutator here 	 */	RESUMEWORLD();	/* 	 * Now free the objects.  We can block here since we're the only	 * thread manipulating the "mustfree" list.	 */	startTiming(&sweep_time, "gctime-sweep");	while (gclists[mustfree].cnext != &gclists[mustfree]) {		destroy_func_t destroy;		unit = gclists[mustfree].cnext;		/* invoke destroy function before freeing the object */		info = GCMEM2BLOCK(unit);		idx = GCMEM2IDX(info, unit);		destroy = gcFunctions[GC_GET_FUNCS(info,idx)].destroy;		if (destroy != 0) {			destroy(gcif, UTOMEM(unit));		}		UREMOVELIST(unit);		addToCounter(&gcgcablemem, "gcmem-gcable objects", 1, 			-((jlong)GCBLOCKSIZE(info)));		gc_heap_free(unit);	}	stopTiming(&sweep_time);}staticvoidstartFinalizer(void){	int iLockRoot;	int start;        start = 0;	lockStaticMutex(&gc_lock);	/* If there's stuff to be finalised then we'd better do it */	if (gclists[finalise].cnext != &gclists[finalise]) {		start = 1;	}	unlockStaticMutex(&gc_lock);	lockStaticMutex(&finman);	if (start != 0 && finalRunning == false) {		finalRunning = true;		signalStaticCond(&finman);	}	unlockStaticMutex(&finman);}/* * The finaliser sits in a loop waiting to finalise objects.  When a * new finalised list is available, it is woken by the GC and finalises * the objects in turn.  An object is only finalised once after which * it is deleted. */static voidfinaliserMan(void* arg){	gc_block* info;	gc_unit* unit;	int idx;	Collector *gcif = (Collector*)arg;	int iLockRoot;	for (;;) {		lockStaticMutex(&finman);		finalRunning = false;		while (finalRunning == false) {			waitStaticCond(&finman, 0);		}		assert(finalRunning == true);		while (gclists[finalise].cnext != &gclists[finalise]) {			lockStaticMutex(&gc_lock);			unit = gclists[finalise].cnext;			UREMOVELIST(unit);			UAPPENDLIST(gclists[grey], unit);			info = GCMEM2BLOCK(unit);			idx = GCMEM2IDX(info, unit);			gcStats.finalmem -= GCBLOCKSIZE(info);			gcStats.finalobj -= 1;			assert(GC_GET_STATE(info,idx) == GC_STATE_INFINALIZE);			/* Objects are only finalised once */			GC_SET_STATE(info, idx, GC_STATE_FINALIZED);			GC_SET_COLOUR(info, idx, GC_COLOUR_GREY);			unlockStaticMutex(&gc_lock);			/* Call finaliser */			unlockStaticMutex(&finman);			(*gcFunctions[GC_GET_FUNCS(info,idx)].final)(gcif, UTOMEM(unit));			lockStaticMutex(&finman);		}		/* Wake up anyone waiting for the finalizer to finish */		broadcastStaticCond(&finman);		unlockStaticMutex(&finman);	}}/* * Explicity invoke the garbage collector and wait for it to complete. */staticvoidgcInvokeGC(Collector* gcif, int mustgc){	int iLockRoot;	lockStaticMutex(&gcman);	if (gcRunning == 0) {		gcRunning = mustgc ? 2 : 1;		signalStaticCond(&gcman);	}	unlockStaticMutex(&gcman);	lockStaticMutex(&gcman);	while (gcRunning != 0) {		waitStaticCond(&gcman, 0);	}	unlockStaticMutex(&gcman);}/* * GC and invoke the finalizer.  Used to run finalizers on exit. */staticvoidgcInvokeFinalizer(Collector* gcif){	int iLockRoot;	/* First invoke the GC */	GC_invoke(gcif, 1);	/* Run the finalizer (if might already be running as a result of	 * the GC)	 */	lockStaticMutex(&finman);	if (finalRunning == false) {		finalRunning = true;		signalStaticCond(&finman); 	}	waitStaticCond(&finman, 0);	unlockStaticMutex(&finman);}/* * Allocate a new object.  The object is attached to the white queue. * After allocation, if incremental collection is active we peform * a little garbage collection.  If we finish it, we wakeup the garbage * collector. */void throwOutOfMemory(void) __NORETURN__;staticvoid*gcMalloc(Collector* gcif, size_t size, int fidx){	gc_block* info;	gc_unit* unit;	void * volatile mem;	/* needed on SGI, see comment below */	int i;	size_t bsz;	int iLockRoot;	assert(gc_init != 0);	assert(fidx < nrTypes && size != 0);	unit = gc_heap_malloc(size + sizeof(gc_unit));	/* keep pointer to object */	mem = UTOMEM(unit);	if (unit == 0) {		return 0;	}	lockStaticMutex(&gc_lock);	info = GCMEM2BLOCK(mem);	i = GCMEM2IDX(info, unit);	bsz = GCBLOCKSIZE(info);	gcStats.totalmem += bsz;	gcStats.totalobj += 1;	gcStats.allocmem += bsz;	gcStats.allocobj += 1;	GC_SET_FUNCS(info, i, fidx);	OBJECTSTATSADD(unit);	/* Determine whether we need to finalise or not */	if (gcFunctions[fidx].final == GC_OBJECT_NORMAL || gcFunctions[fidx].final == GC_OBJECT_FIXED) {		GC_SET_STATE(info, i, GC_STATE_NORMAL);	}	else {		GC_SET_STATE(info, i, GC_STATE_NEEDFINALIZE);	}	/* If object is fixed, we give it the fixed colour and do not	 * attach it to any lists.  This object is not part of the GC	 * regime and must be freed explicitly.	 */	if (gcFunctions[fidx].final == GC_OBJECT_FIXED) {		addToCounter(&gcfixedmem, "gcmem-fixed objects", 1, bsz);		GC_SET_COLOUR(info, i, GC_COLOUR_FIXED);	}	else {		addToCounter(&gcgcablemem, "gcmem-gcable objects", 1, bsz);		/*		 * Note that as soon as we put the object on the white list,		 * the gc might come along and free the object if it can't		 * find any references to it.  This is why we need to keep		 * a reference in `mem'.  Note that keeping a reference in		 * `unit' will not do because markObject performs a UTOUNIT()!		 * In addition, on some architectures (SGI), we must tell the		 * compiler to not delay computing mem by defining it volatile.		 */		GC_SET_COLOUR(info, i, GC_COLOUR_WHITE);		UAPPENDLIST(gclists[white], unit);	}	if (!reserve) {		reserve = gc_primitive_reserve();	}	/* It is not safe to allocate java objects the first time	 * gcMalloc is called, but it should be safe after gcEnable	 * has been called.	 */	if (garbageman && !outOfMem && !outOfMem_allocator) {		outOfMem_allocator = jthread_current();	}	unlockStaticMutex(&gc_lock);	/* jthread_current() will be null in some window before we	 * should try allocating java objects	 */	if (!outOfMem && outOfMem_allocator	    && outOfMem_allocator == jthread_current()) { 		outOfMem = OOM_ALLOCATING;		outOfMem = OutOfMemoryError; /* implicit allocation */		outOfMem_allocator = 0;		gc_add_ref(outOfMem);	}	return (mem);}staticHjava_lang_Throwable *gcThrowOOM(Collector *gcif){	Hjava_lang_Throwable *ret = 0;	int reffed;	int iLockRoot;	/*	 * Make sure we are the only thread to use this exception	 * object.	 */	lockStaticMutex(&gc_lock);	ret = outOfMem;	reffed = outOfMem != 0;	outOfMem = 0;	/* We try allocating reserved pages before we allocate the	 * outOfMemory error.  We can use some or all of the reserved	 * pages to actually grab an error.	 */	if (reserve) {		gc_primitive_free(reserve);		reserve = 0;		if (!ret || ret == OOM_ALLOCATING) {			unlockStaticMutex(&gc_lock);			ret = OutOfMemoryError; /* implicit allocation */			lockStaticMutex(&gc_lock);		}	}	if (ret == OOM_ALLOCATING || ret == 0) {		/* die now */		unlockStaticMutex(&gc_lock);		dprintf(			"Not enough memory to throw OutOfMemoryError!\n");		ABORT();	}	unlockStaticMutex(&gc_lock);	if (reffed) gc_rm_ref(ret);	return ret;}/* * Reallocate an object. */staticvoid*gcRealloc(Collector* gcif, void* mem, size_t size, int fidx){	gc_block* info;	int idx;	void* newmem;	gc_unit* unit;	int osize;	int iLockRoot;	assert(gcFunctions[fidx].final == GC_OBJECT_FIXED);	/* If nothing to realloc from, just allocate */	if (mem == NULL) {		return (gcMalloc(gcif, size, fidx));	}	lockStaticMutex(&gc_lock);	unit = UTOUNIT(mem);	info = GCMEM2BLOCK(unit);	idx = GCMEM2IDX(info, unit);	osize = GCBLOCKSIZE(info) - sizeof(gc_unit);	/* Can only handled fixed objects at the moment */	assert(GC_GET_COLOUR(info, idx) == GC_COLOUR_FIXED);	info = 0;	unlockStaticMutex(&gc_lock);	/* If we'll fit into the current space, just send it back */	if (osize >= size) {		return (mem);	}	/* Allocate new memory, copy data, and free the old */	newmem = gcMalloc(gcif, size, fidx);	memcpy(newmem, mem, osize);	gcFree(gcif, mem);	return (newmem);}/* * Explicitly free an object. */staticvoidgcFree(Collector* gcif, void* mem){	gc_block* info;	int idx;	gc_unit* unit;	int iLockRoot;	if (mem != 0) {		lockStaticMutex(&gc_lock);		unit = UTOUNIT(mem);		info = GCMEM2BLOCK(unit);		idx = GCMEM2IDX(info, unit);		if (GC_GET_COLOUR(info, idx) == GC_COLOUR_FIXED) {			size_t sz = GCBLOCKSIZE(info);			OBJECTSTATSREMOVE(unit);			/* Keep the stats correct */			gcStats.totalmem -= sz;			gcStats.totalobj -= 1;			addToCounter(&gcfixedmem, "gcmem-fixed objects", 1, -(jlong)sz);			gc_heap_free(unit);		}		else {			assert(!!!"Attempt to explicitly free nonfixed object");		}		unlockStaticMutex(&gc_lock);	}}staticvoidgcInit(Collector *collector){	gc_init = 1;}/* * Start gc threads, which enable collection */static void/* ARGSUSED */gcEnable(Collector* collector){	errorInfo info;        if (DBGEXPR(NOGC, false, true))        {                /* Start the GC daemons we need */                finalman = createDaemon(&finaliserMan, "finaliser", 				collector, THREAD_MAXPRIO,					FINALIZERSTACKSIZE, &info);                garbageman = createDaemon(&gcMan, "gc", 				collector, THREAD_MAXPRIO,					  GCSTACKSIZE, &info);		assert(finalman && garbageman);        }}#if defined(SUPPORT_VERBOSEMEM)/* --------------------------------------------------------------------- *//* The following functions are strictly for statistics gathering	 */staticvoidobjectStatsChange(gc_unit* unit, int diff){	gc_block* info;	int idx;	info = GCMEM2BLOCK(unit);	idx = GC_GET_FUNCS(info, GCMEM2IDX(info, unit));	assert(idx >= 0 && idx < nrTypes);	gcFunctions[idx].nr += diff * 1;	gcFunctions[idx].mem += diff * GCBLOCKSIZE(info);}static voidobjectStatsPrint(void){	int cnt = 0;	dprintf("Memory statistics:\n");	dprintf("------------------\n");	while (cnt < nrTypes) {		dprintf("%14.14s: Nr %6d  Mem %6dK",			gcFunctions[cnt].description, 			gcFunctions[cnt].nr, 			gcFunctions[cnt].mem/1024);		if (++cnt % 2 != 0) {			dprintf("   ");		} else {			dprintf("\n");		}	}	if (cnt % 2 != 0) {		dprintf("\n");	}}#endif/* * vtable for object implementing the collector interface. */static struct GarbageCollectorInterface_Ops GC_Ops = {	0,		/* reserved */	0,		/* reserved */	0,		/* reserved */	gcMalloc,	gcRealloc,	gcFree,	gcInvokeGC,	gcInvokeFinalizer,	gcInit,	gcEnable,	gcMarkAddress,	gcMarkObject,	gcGetObjectSize,	gcGetObjectDescription,	gcGetObjectIndex,	gcGetObjectBase,	gcWalkMemory,	gcWalkConservative,	gcRegisterFixedTypeByIndex,	gcRegisterGcTypeByIndex,	gcThrowOOM};/* * Initialise the Garbage Collection system. */Collector* createGC(void (*_walkRootSet)(Collector*)){	walkRootSet = _walkRootSet;	URESETLIST(gclists[white]);	URESETLIST(gclists[grey]);	URESETLIST(gclists[black]);	URESETLIST(gclists[finalise]);	URESETLIST(gclists[mustfree]);	gc_obj.collector.ops = &GC_Ops;	return (&gc_obj.collector);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -