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

📄 alloc.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved. * Copyright (c) 1998 by Silicon Graphics.  All rights reserved. * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK. * * Permission is hereby granted to use or copy this program * for any purpose,  provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * */# include "private/gc_priv.h"# include <stdio.h># if !defined(MACOS) && !defined(MSWINCE)#   include <signal.h>#   include <sys/types.h># endif/* * Separate free lists are maintained for different sized objects * up to MAXOBJSZ. * The call GC_allocobj(i,k) ensures that the freelist for * kind k objects of size i points to a non-empty * free list. It returns a pointer to the first entry on the free list. * In a single-threaded world, GC_allocobj may be called to allocate * an object of (small) size i as follows: * *            opp = &(GC_objfreelist[i]); *            if (*opp == 0) GC_allocobj(i, NORMAL); *            ptr = *opp; *            *opp = obj_link(ptr); * * Note that this is very fast if the free list is non-empty; it should * only involve the execution of 4 or 5 simple instructions. * All composite objects on freelists are cleared, except for * their first word. *//* *  The allocator uses GC_allochblk to allocate large chunks of objects. * These chunks all start on addresses which are multiples of * HBLKSZ.   Each allocated chunk has an associated header, * which can be located quickly based on the address of the chunk. * (See headers.c for details.)  * This makes it possible to check quickly whether an * arbitrary address corresponds to an object administered by the * allocator. */word GC_non_gc_bytes = 0;  /* Number of bytes not intended to be collected */word GC_gc_no = 0;#ifndef SMALL_CONFIG  int GC_incremental = 0;  /* By default, stop the world.	*/#endifint GC_parallel = FALSE;   /* By default, parallel GC is off.	*/int GC_full_freq = 19;	   /* Every 20th collection is a full	*/			   /* collection, whether we need it 	*/			   /* or not.			        */GC_bool GC_need_full_gc = FALSE;			   /* Need full GC do to heap growth.	*/#ifdef THREADS  GC_bool GC_world_stopped = FALSE;# define IF_THREADS(x) x#else# define IF_THREADS(x)#endifword GC_used_heap_size_after_full = 0;char * GC_copyright[] ={"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ","Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved. ","Copyright (c) 1996-1998 by Silicon Graphics.  All rights reserved. ","Copyright (c) 1999-2001 by Hewlett-Packard Company.  All rights reserved. ","THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY"," EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.","See source code for details." };# include "version.h"#if defined(SAVE_CALL_CHAIN) && \	!(defined(REDIRECT_MALLOC) && defined(GC_HAVE_BUILTIN_BACKTRACE))#   define SAVE_CALL_CHAIN_IN_GC    /* This is only safe if the call chain save mechanism won't end up	*/    /* calling GC_malloc.  The GNU C library documentation suggests 	*/    /* that backtrace doesn't use malloc, but at least the initial	*/    /* call in some versions does seem to invoke the dynamic linker,	*/    /* which uses malloc.						*/#endif/* some more variables */extern signed_word GC_mem_found;  /* Number of reclaimed longwords	*/				  /* after garbage collection      	*/GC_bool GC_dont_expand = 0;word GC_free_space_divisor = 3;extern GC_bool GC_collection_in_progress();		/* Collection is in progress, or was abandoned.	*/int GC_never_stop_func GC_PROTO((void)) { return(0); }unsigned long GC_time_limit = TIME_LIMIT;CLOCK_TYPE GC_start_time;  	/* Time at which we stopped world.	*/				/* used only in GC_timeout_stop_func.	*/int GC_n_attempts = 0;		/* Number of attempts at finishing	*/				/* collection within GC_time_limit.	*/#if defined(SMALL_CONFIG) || defined(NO_CLOCK)#   define GC_timeout_stop_func GC_never_stop_func#else  int GC_timeout_stop_func GC_PROTO((void))  {    CLOCK_TYPE current_time;    static unsigned count = 0;    unsigned long time_diff;        if ((count++ & 3) != 0) return(0);    GET_TIME(current_time);    time_diff = MS_TIME_DIFF(current_time,GC_start_time);    if (time_diff >= GC_time_limit) {#   	ifdef CONDPRINT	  if (GC_print_stats) {	    GC_printf0("Abandoning stopped marking after ");	    GC_printf1("%lu msecs", (unsigned long)time_diff);	    GC_printf1("(attempt %ld)\n", (unsigned long) GC_n_attempts);	  }#	endif    	return(1);    }    return(0);  }#endif /* !SMALL_CONFIG *//* Return the minimum number of words that must be allocated between	*//* collections to amortize the collection cost.				*/static word min_words_allocd(){#   ifdef THREADS 	/* We punt, for now. */ 	register signed_word stack_size = 10000;#   else        int dummy;        register signed_word stack_size = (ptr_t)(&dummy) - GC_stackbottom;#   endif    word total_root_size;  	    /* includes double stack size,	*/    				    /* since the stack is expensive	*/    				    /* to scan.				*/    word scan_size;		/* Estimate of memory to be scanned 	*/				/* during normal GC.			*/        if (stack_size < 0) stack_size = -stack_size;    total_root_size = 2 * stack_size + GC_root_size;    scan_size = BYTES_TO_WORDS(GC_heapsize - GC_large_free_bytes			       + (GC_large_free_bytes >> 2)				   /* use a bit more of large empty heap */			       + total_root_size);    if (TRUE_INCREMENTAL) {        return scan_size / (2 * GC_free_space_divisor);    } else {        return scan_size / GC_free_space_divisor;    }}/* Return the number of words allocated, adjusted for explicit storage	*//* management, etc..  This number is used in deciding when to trigger	*//* collections.								*/word GC_adj_words_allocd(){    register signed_word result;    register signed_word expl_managed =    		BYTES_TO_WORDS((long)GC_non_gc_bytes    				- (long)GC_non_gc_bytes_at_gc);        /* Don't count what was explicitly freed, or newly allocated for	*/    /* explicit management.  Note that deallocating an explicitly	*/    /* managed object should not alter result, assuming the client	*/    /* is playing by the rules.						*/    result = (signed_word)GC_words_allocd    	     - (signed_word)GC_mem_freed 	     + (signed_word)GC_finalizer_mem_freed - expl_managed;    if (result > (signed_word)GC_words_allocd) {        result = GC_words_allocd;    	/* probably client bug or unfortunate scheduling */    }    result += GC_words_finalized;    	/* We count objects enqueued for finalization as though they	*/    	/* had been reallocated this round. Finalization is user	*/    	/* visible progress.  And if we don't count this, we have	*/    	/* stability problems for programs that finalize all objects.	*/    if ((GC_words_wasted >> 3) < result)        result += GC_words_wasted;     	/* This doesn't reflect useful work.  But if there is lots of	*/     	/* new fragmentation, the same is probably true of the heap,	*/     	/* and the collection will be correspondingly cheaper.		*/    if (result < (signed_word)(GC_words_allocd >> 3)) {    	/* Always count at least 1/8 of the allocations.  We don't want	*/    	/* to collect too infrequently, since that would inhibit	*/    	/* coalescing of free storage blocks.				*/    	/* This also makes us partially robust against client bugs.	*/        return(GC_words_allocd >> 3);    } else {        return(result);    }}/* Clear up a few frames worth of garbage left at the top of the stack.	*//* This is used to prevent us from accidentally treating garbade left	*//* on the stack by other parts of the collector as roots.  This 	*//* differs from the code in misc.c, which actually tries to keep the	*//* stack clear of long-lived, client-generated garbage.			*/void GC_clear_a_few_frames(){#   define NWORDS 64    word frames[NWORDS];    /* Some compilers will warn that frames was set but never used.	*/    /* That's the whole idea ...					*/    register int i;        for (i = 0; i < NWORDS; i++) frames[i] = 0;}/* Heap size at which we need a collection to avoid expanding past	*//* limits used by blacklisting.						*/static word GC_collect_at_heapsize = (word)(-1);/* Have we allocated enough to amortize a collection? */GC_bool GC_should_collect(){    return(GC_adj_words_allocd() >= min_words_allocd()	   || GC_heapsize >= GC_collect_at_heapsize);}void GC_notify_full_gc(){    if (GC_start_call_back != (void (*) GC_PROTO((void)))0) {	(*GC_start_call_back)();    }}GC_bool GC_is_full_gc = FALSE;/*  * Initiate a garbage collection if appropriate. * Choose judiciously * between partial, full, and stop-world collections. * Assumes lock held, signals disabled. */void GC_maybe_gc(){    static int n_partial_gcs = 0;    if (GC_should_collect()) {        if (!GC_incremental) {            GC_gcollect_inner();            n_partial_gcs = 0;            return;        } else {#   	  ifdef PARALLEL_MARK	    GC_wait_for_reclaim();#   	  endif	  if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {#   	    ifdef CONDPRINT	      if (GC_print_stats) {	        GC_printf2(	          "***>Full mark for collection %lu after %ld allocd bytes\n",     		  (unsigned long) GC_gc_no+1,	   	  (long)WORDS_TO_BYTES(GC_words_allocd));	      }#           endif	    GC_promote_black_lists();	    (void)GC_reclaim_all((GC_stop_func)0, TRUE);	    GC_clear_marks();            n_partial_gcs = 0;	    GC_notify_full_gc(); 	    GC_is_full_gc = TRUE;          } else {            n_partial_gcs++;          }	}        /* We try to mark with the world stopped.	*/        /* If we run out of time, this turns into	*/        /* incremental marking.			*/#	ifndef NO_CLOCK          if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }#	endif        if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED? 			    GC_never_stop_func : GC_timeout_stop_func)) {#           ifdef SAVE_CALL_CHAIN_IN_GC                GC_save_callers(GC_last_stack);#           endif            GC_finish_collection();        } else {	    if (!GC_is_full_gc) {		/* Count this as the first attempt */	        GC_n_attempts++;	    }	}    }}/* * Stop the world garbage collection.  Assumes lock held, signals disabled. * If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE. * Return TRUE if we successfully completed the collection. */GC_bool GC_try_to_collect_inner(stop_func)GC_stop_func stop_func;{#   ifdef CONDPRINT        CLOCK_TYPE start_time, current_time;#   endif    if (GC_dont_gc) return FALSE;    if (GC_incremental && GC_collection_in_progress()) {#   ifdef CONDPRINT      if (GC_print_stats) {	GC_printf0(	    "GC_try_to_collect_inner: finishing collection in progress\n");      }#   endif /* CONDPRINT */      /* Just finish collection already in progress.	*/    	while(GC_collection_in_progress()) {    	    if (stop_func()) return(FALSE);    	    GC_collect_a_little_inner(1);    	}    }    if (stop_func == GC_never_stop_func) GC_notify_full_gc();#   ifdef CONDPRINT      if (GC_print_stats) {        if (GC_print_stats) GET_TIME(start_time);	GC_printf2(	   "Initiating full world-stop collection %lu after %ld allocd bytes\n",	   (unsigned long) GC_gc_no+1,	   (long)WORDS_TO_BYTES(GC_words_allocd));      }#   endif    GC_promote_black_lists();    /* Make sure all blocks have been reclaimed, so sweep routines	*/    /* don't see cleared mark bits.					*/    /* If we're guaranteed to finish, then this is unnecessary.		*/    /* In the find_leak case, we have to finish to guarantee that 	*/    /* previously unmarked objects are not reported as leaks.		*/#       ifdef PARALLEL_MARK	    GC_wait_for_reclaim();#       endif 	if ((GC_find_leak || stop_func != GC_never_stop_func)

⌨️ 快捷键说明

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