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

📄 ejsgarbage.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	vp = ep->result;	if (vp && vp->type == EJS_TYPE_OBJECT && ! vp->objectState->gcMarked) {		markObjByVar(ep, vp);	}	vp = ep->currentObj;	if (vp && vp->type == EJS_TYPE_OBJECT && ! vp->objectState->gcMarked) {		markObjByVar(ep, vp);	}	vp = ejsGetVarPtr(ep->currentProperty);	if (vp && vp->type == EJS_TYPE_OBJECT && ! vp->objectState->gcMarked) {		markObjByVar(ep, vp);	}	/*	 *	OPT -- we could mark master as "mark permanent" somehow and	 *	then we would not need to walk the master objects. 	 */	if (ep->slabAllocContext == ep->service->master) {		if (ep->service->master->global) {			markObjByVar(ep, ep->service->master->global);		}	}#if BLD_DEBUG	if (ep->gc.debugLevel >= 3) {		mprLog(ep, 0, " ");	}#endif}/******************************************************************************/#if UNUSEDstatic void resetMark(EjsVar *obj){	EjsProperty		*pp;	EjsVar			*vp, *baseClass;	obj->objectState->gcMarked = 0;	obj->objectState->visited = 1;	pp = ejsGetFirstProperty(obj, EJS_ENUM_ALL);	while (pp) {		vp = ejsGetVarPtr(pp);		if (vp->type == EJS_TYPE_OBJECT && !vp->objectState->visited) {			resetMark(vp);					}		pp = ejsGetNextProperty(pp, EJS_ENUM_ALL);	}	baseClass = obj->objectState->baseClass;	if (baseClass) {		mprAssert(baseClass->type == EJS_TYPE_OBJECT);		mprAssert(baseClass->objectState);		if (baseClass->objectState) {			if (! baseClass->objectState->visited) {				resetMark(baseClass);			}		}	}	obj->objectState->visited = 0;}/******************************************************************************//* *	Mark phase. Examine all variable frames and the return result. */static void resetAllMarks(Ejs *ep){	EjsVar	*vp;	int		i;	for (i = 0; i < mprGetItemCount(ep->frames); i++) {		vp = (EjsVar*) mprGetItem(ep->frames, i);		resetMark(vp);	}	if (ep->result && ep->result->type == EJS_TYPE_OBJECT &&			! ep->result->objectState->gcMarked) {		resetMark(ep->result);	}}#endif/******************************************************************************//* *	Sweep up the garbage */static void resetMarks(Ejs *ep, EjsSlab *slab){	EjsVar		*vp;	EjsObj		*obj;	int			gen, i;	for (gen = EJS_GEN_NEW; gen < EJS_GEN_MAX; gen++) {		obj = (EjsObj*) slab->allocList[gen].next;		for (; obj; obj = (EjsObj*) obj->gc.next) {			obj->gcMarked = 0;			obj->visited = 0;		}	}	if (ep->frames) {		for (i = 0; i < mprGetItemCount(ep->frames); i++) {			vp = (EjsVar*) mprGetItem(ep->frames, i);			mprAssert(vp->type == EJS_TYPE_OBJECT);			vp->objectState->gcMarked = 0;			vp->objectState->visited = 0;		}	}	if (ep->result && ep->result->type == EJS_TYPE_OBJECT) {		ep->result->objectState->gcMarked = 0;	}}/******************************************************************************//* *	Mark all permanent and non-alive objects */static void markPerm(Ejs *ep, uint gen){	EjsSlab		*slab;	EjsObj		*obj;	slab = &ep->slabs[EJS_SLAB_OBJ];	for (obj = (EjsObj*) slab->allocList[gen].next; obj; ) {		if (! obj->gcMarked) {			if (!obj->alive || obj->permanent) {				markObj(obj);			}		}		obj = (EjsObj*) obj->gc.next;	}}/******************************************************************************/static void markObj(EjsObj *obj){	EjsProperty		*pp;	EjsPropLink		*lp, *head;	EjsObj			*op;	mprAssert(obj);	obj->gcMarked = 1;	head = &obj->link;	for (lp = head->next; lp != head; lp = lp->next) {		pp = ejsGetPropertyFromLink(lp);		if (pp->var.type == EJS_TYPE_OBJECT) {			op = pp->var.objectState;			if (op != 0 && !op->gcMarked) {				markObj(op);			}		}	}}/******************************************************************************//* *	Sweep up the garbage. Return the number of objects freed. */static int sweep(Ejs *ep, uint gen){	EjsSlab		*slab;	EjsObj		*obj, *next, *prev;	int			count;	slab = &ep->slabs[EJS_SLAB_OBJ];	/*	 *	Examine allocated objects in the specified generation (only).	 *	NOTE: we only sweep object allocated to this interpreter and so	 *	we do not sweep any permanent objects in the default interpreter.	 */	prev = 0;	count = 0;	for (obj = (EjsObj*) slab->allocList[gen].next; obj; obj = next) {		next = (EjsObj*) obj->gc.next;#if BLD_DEBUG && (!BREW || BREW_SIMULATOR)		if ((uint) obj == breakAddr) {			mprBreakpoint(MPR_LOC, "Watched Block");		}#endif		/*		 *	If object has not been marked inuse and is not a permanent		 *	object, then free it.		 */		if (! obj->gcMarked && obj->alive && !obj->permanent) {#if BLD_DEBUG			if (ep->gc.debugLevel >= 2) {				if (obj->objName) {					mprLog(ep, 0, "GC: destroy %-18s   %10d, %8X", 						obj->objName, (uint) obj, (uint) obj);				} else {					mprLog(ep, 0, "GC: destroy UNKNOWN %x", (uint) obj);				}			}#endif			if (ejsDestroyObj(ep, obj) < 0) {				prev = obj;				obj->gcMarked = 0;				continue;			}			if (prev) {				prev->gc.next = (EjsGCLink*) next;			} else {				slab->allocList[gen].next = (EjsGCLink*) next;			}			count++;		} else {			prev = obj;			/* Reset for next time */			obj->gcMarked = 0;		} 	}	if (gen == (EJS_GEN_OLD - 1)) {		slab->lastRecentBlock = prev;	}#if BLD_FEATURE_ALLOC_STATS	slab->totalSweeps++;#endif#if BLD_DEBUG	if (ep->gc.debugLevel > 0) {		mprLog(ep, 0, "GC: Sweep freed %d objects", count);	}#endif	return count;}/******************************************************************************//* *	Sweep all variables */void ejsSweepAll(Ejs *ep){	EjsSlab		*slab;	EjsObj		*obj, *next, *prev;	int			gen;	slab = &ep->slabs[EJS_SLAB_OBJ];	for (gen = EJS_GEN_NEW; gen < EJS_GEN_MAX; gen++) {		prev = 0;		for (obj = (EjsObj*) slab->allocList[gen].next; obj; obj = next) {			next = (EjsObj*) obj->gc.next;			ejsDestroyObj(ep, obj);		}		break;	}}/******************************************************************************/bool ejsObjIsCollectable(EjsVar *vp){	if (vp == 0 || !ejsVarIsObject(vp)) {		return 0;	}	return (vp->objectState->alive && !vp->objectState->permanent);}/******************************************************************************/#if FUTUREstatic void ageGenerations(Ejs *ep){	EjsSlab		*slab;	EjsGCLink	*oldList;	int			gen;	slab = &ep->slabs[EJS_SLAB_OBJ];	/*	 *	Age all blocks. First append all (old - 1) blocks onto the old  	 *	alloc list  	 */	oldList = &slab->allocList[EJS_GEN_OLD];	if (slab->lastRecentBlock) {		slab->lastRecentBlock->gc.next = oldList->next;		oldList->next = (EjsGCLink*) slab->lastRecentBlock;	}	/* 	 *	Now simply copy all allocation lists up one generation	 */	for (gen = EJS_GEN_OLD - 1; gen > 0; gen--) {		slab->allocList[gen] = slab->allocList[gen - 1];	}	slab->allocList[0].next = 0;}#endif/******************************************************************************//* *	Collect the garbage. This is a mark and sweep over all possible objects. *	If an object is not referenced, it and all contained properties will be *	freed. If a slabIndex is provided, the collection halts when a block is  *	available for allocation on that slab. * *	Return 0 if memory is now available after collecting garbage. Otherwise, *	return MPR_ERR_MEMORY. */int ejsCollectGarbage(Ejs *ep, int slabIndex){	EjsGeneration	gen;		if (ep->flags & EJS_FLAGS_DONT_GC) {		return -1;	}	/*	 *	Prevent destructors invoking the garbage collector	 */	if (ep->gc.collecting) {		return 0;	}	ep->gc.collecting = 1;	resetMarks(ep, &ep->slabs[EJS_SLAB_OBJ]);	/*	 *	Examine each generation of objects starting with the most recent 	 *	generation. Stop scanning when we have a free block to use.	 */	for (gen = EJS_GEN_NEW; gen < EJS_GEN_MAX; gen++) {		if (slabIndex >= 0 && ep->slabs[slabIndex].freeList.next) {			break;		}		/*		 *	FUTURE OPT. Should mark objects in new generation and those 		 *	with a dirty bit set in older generations. Don't need to mark		 *	entire heap. But how to keep list of dirty objects. 		 */		mark(ep);		markPerm(ep, gen);		sweep(ep, gen);		/* FUTURE - not using generations yet */		break;	}	/*	 *	FUTURE -- not using generations yet.  	 * 	 * 		ageGenerations(ep);	 */	ep->gc.workDone = 0;	ep->gc.collecting = 0;	return (gen < EJS_GEN_MAX) ? 0 : MPR_ERR_MEMORY;} /******************************************************************************//* *	Should be called when the app has been idle for a little while and when it *	is likely to be idle a bit longer. Call ejsIsTimeForGC to see if this is *	true. Return the count of objects collected . */int ejsIncrementalCollectGarbage(Ejs *ep){	int		count;	if (ep->gc.collecting) {		return 0;	}	ep->gc.collecting = 1;	resetMarks(ep, &ep->slabs[EJS_SLAB_OBJ]);	mark(ep);	/* Not generational yet */	count = sweep(ep, EJS_GEN_NEW);	ep->gc.collecting = 0;	ep->gc.workDone = 0;	return count;}/******************************************************************************/#if BLD_DEBUGvoid ejsDumpObjects(Ejs *ep){	int		oldDebugLevel;	mprLog(ep, 0, "Dump of objects in use\n");	oldDebugLevel = ep->gc.debugLevel;	ep->gc.debugLevel = 3;	ep->gc.objectsInUse = 0;	ep->gc.propertiesInUse = 0;	ep->gc.collecting = 1;	resetMarks(ep, &ep->slabs[EJS_SLAB_OBJ]);	mark(ep);	ep->gc.collecting = 0;	ep->gc.debugLevel = oldDebugLevel;	mprLog(ep, 0, "%d objects and %d properties in use",		ep->gc.objectsInUse, ep->gc.propertiesInUse);	mprLog(ep, 0, "%d object bytes, %d property bytes and %d total",		(int) (ep->gc.objectsInUse * sizeof(EjsObj)),		(int) (ep->gc.propertiesInUse * sizeof(EjsProperty)),		(int) ((ep->gc.objectsInUse * sizeof(EjsObj) +		 		ep->gc.propertiesInUse * sizeof(EjsProperty))));}#endif/******************************************************************************//* *	Return true if there is time to do a garbage collection and if we will *	benefit from it. */int ejsIsTimeForGC(Ejs *ep, int timeTillNextEvent){	EjsGC		*gc;	if (timeTillNextEvent < EJS_MIN_TIME_FOR_GC) {		/*		 *	Not enough time to complete a collection		 */		return 0;	}	gc = &ep->gc;	/*	 *	Return if we haven't done enough work to warrant a collection 	 *	Trigger a little short of the work quota to try to run GC before	 *	a demand allocation requires it.	 */	if (!gc->enable || !gc->enableIdleCollect || 			(gc->workDone < (gc->workQuota - EJS_GC_MIN_WORK_QUOTA))) {		return 0;	}#if UNUSED	mprLog(ep, 0, "Time for GC. Work done %d, time till next event %d",		gc->workDone, timeTillNextEvent);#endif	return 1;}/******************************************************************************//* *	Return the amount of memory in use by EJS */uint ejsGetUsedMemory(Ejs *ep){#if BLD_FEATURE_ALLOC_STATS	EjsSlab		*slab;	int			i, totalMemory, slabMemory;	totalMemory = 0;	for (i = 0; i < EJS_SLAB_MAX; i++) {		slab = &ep->slabs[i];		slabMemory = slab->allocCount * slab->size;		totalMemory += slabMemory;	}	return totalMemory;#else	return 0;#endif}/******************************************************************************//* *	Return the amount of memory allocated by EJS */uint ejsGetAllocatedMemory(Ejs *ep){#if BLD_FEATURE_ALLOC_STATS	EjsSlab		*slab;	int			i, totalMemory, slabMemory;	totalMemory = 0;	for (i = 0; i < EJS_SLAB_MAX; i++) {		slab = &ep->slabs[i];		slabMemory = (slab->allocCount + slab->freeCount) * slab->size;		totalMemory += slabMemory;	}	return totalMemory;#else	return 0;#endif}/******************************************************************************//* *	On a memory allocation failure, go into graceful degrade mode. Set all *	slab allocation chunk increments to 1 so we can create an exception block  *	to throw. */static void ejsGracefulDegrade(Ejs *ep){	EjsSlab		*slab;	int			i;	mprLog(ep, 1, "WARNING: Memory almost depleted. In graceful degrade mode");	for (i = 0; i < EJS_SLAB_MAX; i++) {		slab = &ep->slabs[i];		slab->allocIncrement = 8;	}	ep->gc.degraded = 1;}/******************************************************************************/int ejsSetGCDebugLevel(Ejs *ep, int debugLevel){	int		old;	old = ep->gc.debugLevel;	ep->gc.debugLevel = debugLevel;	return old;}/******************************************************************************/int ejsSetGCMaxMemory(Ejs *ep, uint maxMemory){	int		old;	old = ep->gc.maxMemory;	ep->gc.maxMemory = maxMemory;	return old;}/******************************************************************************/bool ejsBlockInUseInt(EjsVar *vp){	if (vp) {#if BLD_DEBUG		if (vp->gc.magic != EJS_MAGIC) {			return 0;		}		if (vp->type == EJS_TYPE_OBJECT && vp->objectState && 			vp->objectState->gc.magic != EJS_MAGIC) {			return 0;		}#endif		return 1;	}	return 1;}/******************************************************************************/#elsevoid ejsGarbageDummy() {}#endif /* BLD_FEATURE_EJS *//******************************************************************************//* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim:tw=78 * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */

⌨️ 快捷键说明

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