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

📄 reclaim.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved. * Copyright (c) 1996-1999 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 <stdio.h>#include "private/gc_priv.h"signed_word GC_mem_found = 0;			/* Number of words of memory reclaimed     */#if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)  word GC_fl_builder_count = 0;	/* Number of threads currently building free lists without 	*/	/* holding GC lock.  It is not safe to collect if this is 	*/	/* nonzero.							*/#endif /* PARALLEL_MARK *//* We defer printing of leaked objects until we're done with the GC	*//* cycle, since the routine for printing objects needs to run outside	*//* the collector, e.g. without the allocation lock.			*/#define MAX_LEAKED 40ptr_t GC_leaked[MAX_LEAKED];unsigned GC_n_leaked = 0;GC_bool GC_have_errors = FALSE;void GC_add_leaked(leaked)ptr_t leaked;{    if (GC_n_leaked < MAX_LEAKED) {      GC_have_errors = TRUE;      GC_leaked[GC_n_leaked++] = leaked;      /* Make sure it's not reclaimed this cycle */        GC_set_mark_bit(leaked);    }}static GC_bool printing_errors = FALSE;/* Print all objects on the list after printing any smashed objs. 	*//* Clear both lists.							*/void GC_print_all_errors (){    unsigned i;    LOCK();    if (printing_errors) {	UNLOCK();	return;    }    printing_errors = TRUE;    UNLOCK();    if (GC_debugging_started) GC_print_all_smashed();    for (i = 0; i < GC_n_leaked; ++i) {	ptr_t p = GC_leaked[i];	if (HDR(p) -> hb_obj_kind == PTRFREE) {	    GC_err_printf0("Leaked atomic object at ");	} else {	    GC_err_printf0("Leaked composite object at ");	}	GC_print_heap_obj(p);	GC_err_printf0("\n");	GC_free(p);	GC_leaked[i] = 0;    }    GC_n_leaked = 0;    printing_errors = FALSE;}#   define FOUND_FREE(hblk, word_no) \      { \         GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \      }/* * reclaim phase * *//* * Test whether a block is completely empty, i.e. contains no marked * objects.  This does not require the block to be in physical * memory. */ GC_bool GC_block_empty(hhdr)register hdr * hhdr;{    /* We treat hb_marks as an array of words here, even if it is 	*/    /* actually an array of bytes.  Since we only check for zero, there	*/    /* are no endian-ness issues.					*/    register word *p = (word *)(&(hhdr -> hb_marks[0]));    register word * plim =	    (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));    while (p < plim) {	if (*p++) return(FALSE);    }    return(TRUE);}/* The following functions sometimes return a DONT_KNOW value. */#define DONT_KNOW  2#ifdef SMALL_CONFIG# define GC_block_nearly_full1(hhdr, pat1) DONT_KNOW# define GC_block_nearly_full3(hhdr, pat1, pat2) DONT_KNOW# define GC_block_nearly_full(hhdr) DONT_KNOW#endif#if !defined(SMALL_CONFIG) && defined(USE_MARK_BYTES)# define GC_block_nearly_full1(hhdr, pat1) GC_block_nearly_full(hhdr)# define GC_block_nearly_full3(hhdr, pat1, pat2) GC_block_nearly_full(hhdr) GC_bool GC_block_nearly_full(hhdr)register hdr * hhdr;{    /* We again treat hb_marks as an array of words, even though it	*/    /* isn't.  We first sum up all the words, resulting in a word 	*/    /* containing 4 or 8 separate partial sums. 			*/    /* We then sum the bytes in the word of partial sums.		*/    /* This is still endian independant.  This fails if the partial	*/    /* sums can overflow.						*/#   if (BYTES_TO_WORDS(MARK_BITS_SZ)) >= 256	--> potential overflow; fix the code#   endif    register word *p = (word *)(&(hhdr -> hb_marks[0]));    register word * plim =	    (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));    word sum_vector = 0;    unsigned sum;    while (p < plim) {	sum_vector += *p;	++p;    }    sum = 0;    while (sum_vector > 0) {	sum += sum_vector & 0xff;	sum_vector >>= 8;    }    return (sum > BYTES_TO_WORDS(7*HBLKSIZE/8)/(hhdr -> hb_sz));}#endif  /* USE_MARK_BYTES */#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)/* * Test whether nearly all of the mark words consist of the same * repeating pattern. */#define FULL_THRESHOLD (MARK_BITS_SZ/16)GC_bool GC_block_nearly_full1(hhdr, pat1)hdr *hhdr;word pat1;{    unsigned i;    unsigned misses = 0;    GC_ASSERT((MARK_BITS_SZ & 1) == 0);    for (i = 0; i < MARK_BITS_SZ; ++i) {	if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {	    if (++misses > FULL_THRESHOLD) return FALSE;	}    }    return TRUE;}/* * Test whether the same repeating 3 word pattern occurs in nearly * all the mark bit slots. * This is used as a heuristic, so we're a bit sloppy and ignore * the last one or two words. */GC_bool GC_block_nearly_full3(hhdr, pat1, pat2, pat3)hdr *hhdr;word pat1, pat2, pat3;{    unsigned i;    unsigned misses = 0;    if (MARK_BITS_SZ < 4) {      return DONT_KNOW;    }    for (i = 0; i < MARK_BITS_SZ - 2; i += 3) {	if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {	    if (++misses > FULL_THRESHOLD) return FALSE;	}	if ((hhdr -> hb_marks[i+1] | ~pat2) != ONES) {	    if (++misses > FULL_THRESHOLD) return FALSE;	}	if ((hhdr -> hb_marks[i+2] | ~pat3) != ONES) {	    if (++misses > FULL_THRESHOLD) return FALSE;	}    }    return TRUE;}/* Check whether a small object block is nearly full by looking at only *//* the mark bits.							*//* We manually precomputed the mark bit patterns that need to be 	*//* checked for, and we give up on the ones that are unlikely to occur,	*//* or have period > 3.							*//* This would be a lot easier with a mark bit per object instead of per	*//* word, but that would rewuire computing object numbers in the mark	*//* loop, which would require different data structures ...		*/GC_bool GC_block_nearly_full(hhdr)hdr *hhdr;{    int sz = hhdr -> hb_sz;#   if CPP_WORDSZ != 32 && CPP_WORDSZ != 64      return DONT_KNOW;	/* Shouldn't be used in any standard config.	*/#   endif#   if CPP_WORDSZ == 32      switch(sz) {        case 1:	  return GC_block_nearly_full1(hhdr, 0xffffffffl);	case 2:	  return GC_block_nearly_full1(hhdr, 0x55555555l);	case 4:	  return GC_block_nearly_full1(hhdr, 0x11111111l);	case 6:	  return GC_block_nearly_full3(hhdr, 0x41041041l,					      0x10410410l,					       0x04104104l);	case 8:	  return GC_block_nearly_full1(hhdr, 0x01010101l);	case 12:	  return GC_block_nearly_full3(hhdr, 0x01001001l,					      0x10010010l,					       0x00100100l);	case 16:	  return GC_block_nearly_full1(hhdr, 0x00010001l);	case 32:	  return GC_block_nearly_full1(hhdr, 0x00000001l);	default:	  return DONT_KNOW;      }#   endif#   if CPP_WORDSZ == 64      switch(sz) {        case 1:	  return GC_block_nearly_full1(hhdr, 0xffffffffffffffffl);	case 2:	  return GC_block_nearly_full1(hhdr, 0x5555555555555555l);	case 4:	  return GC_block_nearly_full1(hhdr, 0x1111111111111111l);	case 6:	  return GC_block_nearly_full3(hhdr, 0x1041041041041041l,					       0x4104104104104104l,					         0x0410410410410410l);	case 8:	  return GC_block_nearly_full1(hhdr, 0x0101010101010101l);	case 12:	  return GC_block_nearly_full3(hhdr, 0x1001001001001001l,					       0x0100100100100100l,					         0x0010010010010010l);	case 16:	  return GC_block_nearly_full1(hhdr, 0x0001000100010001l);	case 32:	  return GC_block_nearly_full1(hhdr, 0x0000000100000001l);	default:	  return DONT_KNOW;      }#   endif}#endif /* !SMALL_CONFIG  && !USE_MARK_BYTES *//* We keep track of reclaimed memory if we are either asked to, or	*//* we are using the parallel marker.  In the latter case, we assume	*//* that most allocation goes through GC_malloc_many for scalability.	*//* GC_malloc_many needs the count anyway.				*/# if defined(GATHERSTATS) || defined(PARALLEL_MARK)#   define INCR_WORDS(sz) n_words_found += (sz)#   define COUNT_PARAM , count#   define COUNT_ARG , count#   define COUNT_DECL signed_word * count;#   define NWORDS_DECL signed_word n_words_found = 0;#   define COUNT_UPDATE *count += n_words_found;#   define MEM_FOUND_ADDR , &GC_mem_found# else#   define INCR_WORDS(sz)#   define COUNT_PARAM#   define COUNT_ARG#   define COUNT_DECL#   define NWORDS_DECL#   define COUNT_UPDATE#   define MEM_FOUND_ADDR# endif/* * Restore unmarked small objects in h of size sz to the object * free list.  Returns the new list. * Clears unmarked objects. *//*ARGSUSED*/ptr_t GC_reclaim_clear(hbp, hhdr, sz, list COUNT_PARAM)register struct hblk *hbp;	/* ptr to current heap block		*/register hdr * hhdr;register ptr_t list;register word sz;COUNT_DECL{    register int word_no;    register word *p, *q, *plim;    NWORDS_DECL        GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp));    p = (word *)(hbp->hb_body);    word_no = 0;    plim = (word *)((((word)hbp) + HBLKSIZE)		   - WORDS_TO_BYTES(sz));    /* go through all words in block */	while( p <= plim )  {	    if( mark_bit_from_hdr(hhdr, word_no) ) {		p += sz;	    } else {		INCR_WORDS(sz);		/* object is available - put on list */		    obj_link(p) = list;		    list = ((ptr_t)p);		/* Clear object, advance p to next object in the process */		    q = p + sz;#		    ifdef USE_MARK_BYTES		      GC_ASSERT(!(sz & 1)				&& !((word)p & (2 * sizeof(word) - 1)));		      p[1] = 0;                      p += 2;                      while (p < q) {			CLEAR_DOUBLE(p);			p += 2;		      }#		    else                      p++; /* Skip link field */                      while (p < q) {			*p++ = 0;		      }#		    endif	    }	    word_no += sz;	}    COUNT_UPDATE    return(list);}#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)/* * A special case for 2 word composite objects (e.g. cons cells): *//*ARGSUSED*/ptr_t GC_reclaim_clear2(hbp, hhdr, list COUNT_PARAM)register struct hblk *hbp;	/* ptr to current heap block		*/hdr * hhdr;register ptr_t list;COUNT_DECL{    register word * mark_word_addr = &(hhdr->hb_marks[0]);    register word *p, *plim;    register word mark_word;    register int i;    NWORDS_DECL#   define DO_OBJ(start_displ) \	if (!(mark_word & ((word)1 << start_displ))) { \	    p[start_displ] = (word)list; \	    list = (ptr_t)(p+start_displ); \	    p[start_displ+1] = 0; \	    INCR_WORDS(2); \	}        p = (word *)(hbp->hb_body);    plim = (word *)(((word)hbp) + HBLKSIZE);    /* go through all words in block */	while( p < plim )  {	    mark_word = *mark_word_addr++;	    for (i = 0; i < WORDSZ; i += 8) {		DO_OBJ(0);		DO_OBJ(2);		DO_OBJ(4);		DO_OBJ(6);		p += 8;		mark_word >>= 8;	    }	}	            COUNT_UPDATE    return(list);#   undef DO_OBJ}/* * Another special case for 4 word composite objects: *//*ARGSUSED*/ptr_t GC_reclaim_clear4(hbp, hhdr, list COUNT_PARAM)register struct hblk *hbp;	/* ptr to current heap block		*/hdr * hhdr;register ptr_t list;COUNT_DECL{    register word * mark_word_addr = &(hhdr->hb_marks[0]);    register word *p, *plim;    register word mark_word;    NWORDS_DECL#   define DO_OBJ(start_displ) \	if (!(mark_word & ((word)1 << start_displ))) { \	    p[start_displ] = (word)list; \	    list = (ptr_t)(p+start_displ); \	    p[start_displ+1] = 0; \	    CLEAR_DOUBLE(p + start_displ + 2); \	    INCR_WORDS(4); \	}        p = (word *)(hbp->hb_body);    plim = (word *)(((word)hbp) + HBLKSIZE);    /* go through all words in block */	while( p < plim )  {	    mark_word = *mark_word_addr++;	    DO_OBJ(0);	    DO_OBJ(4);	    DO_OBJ(8);	    DO_OBJ(12);	    DO_OBJ(16);	    DO_OBJ(20);	    DO_OBJ(24);	    DO_OBJ(28);#	    if CPP_WORDSZ == 64	      DO_OBJ(32);	      DO_OBJ(36);	      DO_OBJ(40);	      DO_OBJ(44);	      DO_OBJ(48);	      DO_OBJ(52);	      DO_OBJ(56);	      DO_OBJ(60);#	    endif	    p += WORDSZ;	}	            COUNT_UPDATE    return(list);#   undef DO_OBJ}#endif /* !SMALL_CONFIG && !USE_MARK_BYTES *//* The same thing, but don't clear objects: *//*ARGSUSED*/ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_PARAM)register struct hblk *hbp;	/* ptr to current heap block		*/register hdr * hhdr;register ptr_t list;register word sz;COUNT_DECL{    register int word_no = 0;    register word *p, *plim;    NWORDS_DECL        p = (word *)(hbp->hb_body);    plim = (word *)((((word)hbp) + HBLKSIZE)		   - WORDS_TO_BYTES(sz));    /* go through all words in block */	while( p <= plim )  {	    if( !mark_bit_from_hdr(hhdr, word_no) ) {		INCR_WORDS(sz);		/* object is available - put on list */		    obj_link(p) = list;		    list = ((ptr_t)p);	    }	    p += sz;	    word_no += sz;	}    COUNT_UPDATE    return(list);}/* Don't really reclaim objects, just check for unmarked ones: *//*ARGSUSED*/void GC_reclaim_check(hbp, hhdr, sz)register struct hblk *hbp;	/* ptr to current heap block		*/register hdr * hhdr;register word sz;{    register int word_no = 0;    register word *p, *plim;#   ifdef GATHERSTATS        register int n_words_found = 0;#   endif        p = (word *)(hbp->hb_body);    plim = (word *)((((word)hbp) + HBLKSIZE)		   - WORDS_TO_BYTES(sz));    /* go through all words in block */	while( p <= plim )  {	    if( !mark_bit_from_hdr(hhdr, word_no) ) {		FOUND_FREE(hbp, word_no);	    }	    p += sz;	    word_no += sz;	}}#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)/* * Another special case for 2 word atomic objects: *//*ARGSUSED*/ptr_t GC_reclaim_uninit2(hbp, hhdr, list COUNT_PARAM)register struct hblk *hbp;	/* ptr to current heap block		*/hdr * hhdr;register ptr_t list;COUNT_DECL{    register word * mark_word_addr = &(hhdr->hb_marks[0]);

⌨️ 快捷键说明

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