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

📄 reclaim.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 2 页
字号:
    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); \	    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 atomic objects: *//*ARGSUSED*/ptr_t GC_reclaim_uninit4(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); \	    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}/* Finally the one word case, which never requires any clearing: *//*ARGSUSED*/ptr_t GC_reclaim1(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); \	    INCR_WORDS(1); \	}        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 += 4) {		DO_OBJ(0);		DO_OBJ(1);		DO_OBJ(2);		DO_OBJ(3);		p += 4;		mark_word >>= 4;	    }	}	            COUNT_UPDATE    return(list);#   undef DO_OBJ}#endif /* !SMALL_CONFIG && !USE_MARK_BYTES *//* * Generic procedure to rebuild a free list in hbp. * Also called directly from GC_malloc_many. */ptr_t GC_reclaim_generic(hbp, hhdr, sz, init, list COUNT_PARAM)struct hblk *hbp;	/* ptr to current heap block		*/hdr * hhdr;GC_bool init;ptr_t list;word sz;COUNT_DECL{    ptr_t result = list;    GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr);    GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */);    if (init) {      switch(sz) {#      if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)        case 1:	    /* We now issue the hint even if GC_nearly_full returned	*/	    /* DONT_KNOW.						*/            result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);            break;        case 2:            result = GC_reclaim_clear2(hbp, hhdr, list COUNT_ARG);            break;        case 4:            result = GC_reclaim_clear4(hbp, hhdr, list COUNT_ARG);            break;#      endif /* !SMALL_CONFIG && !USE_MARK_BYTES */        default:            result = GC_reclaim_clear(hbp, hhdr, sz, list COUNT_ARG);            break;      }    } else {      GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */);      switch(sz) {#      if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)        case 1:            result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);            break;        case 2:            result = GC_reclaim_uninit2(hbp, hhdr, list COUNT_ARG);            break;        case 4:            result = GC_reclaim_uninit4(hbp, hhdr, list COUNT_ARG);            break;#      endif /* !SMALL_CONFIG && !USE_MARK_BYTES */        default:            result = GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_ARG);            break;      }    }     if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr);    return result;}/* * Restore unmarked small objects in the block pointed to by hbp * to the appropriate object free list. * If entirely empty blocks are to be completely deallocated, then * caller should perform that check. */void GC_reclaim_small_nonempty_block(hbp, report_if_found COUNT_PARAM)register struct hblk *hbp;	/* ptr to current heap block		*/int report_if_found;		/* Abort if a reclaimable object is found */COUNT_DECL{    hdr *hhdr = HDR(hbp);    word sz = hhdr -> hb_sz;    int kind = hhdr -> hb_obj_kind;    struct obj_kind * ok = &GC_obj_kinds[kind];    ptr_t * flh = &(ok -> ok_freelist[sz]);        hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;    if (report_if_found) {	GC_reclaim_check(hbp, hhdr, sz);    } else {        *flh = GC_reclaim_generic(hbp, hhdr, sz,				  (ok -> ok_init || GC_debugging_started),	 			  *flh MEM_FOUND_ADDR);    }}/* * Restore an unmarked large object or an entirely empty blocks of small objects * to the heap block free list. * Otherwise enqueue the block for later processing * by GC_reclaim_small_nonempty_block. * If report_if_found is TRUE, then process any block immediately, and * simply report free objects; do not actually reclaim them. */# if defined(__STDC__) || defined(__cplusplus)    void GC_reclaim_block(register struct hblk *hbp, word report_if_found)# else    void GC_reclaim_block(hbp, report_if_found)    register struct hblk *hbp;	/* ptr to current heap block		*/    word report_if_found;	/* Abort if a reclaimable object is found */# endif{    register hdr * hhdr;    register word sz;		/* size of objects in current block	*/    register struct obj_kind * ok;    struct hblk ** rlh;    hhdr = HDR(hbp);    sz = hhdr -> hb_sz;    ok = &GC_obj_kinds[hhdr -> hb_obj_kind];    if( sz > MAXOBJSZ ) {  /* 1 big object */        if( !mark_bit_from_hdr(hhdr, 0) ) {	    if (report_if_found) {	      FOUND_FREE(hbp, 0);	    } else {	      word blocks = OBJ_SZ_TO_BLOCKS(sz);	      if (blocks > 1) {	        GC_large_allocd_bytes -= blocks * HBLKSIZE;	      }#	      ifdef GATHERSTATS	        GC_mem_found += sz;#	      endif	      GC_freehblk(hbp);	    }	}    } else {        GC_bool empty = GC_block_empty(hhdr);        if (report_if_found) {    	  GC_reclaim_small_nonempty_block(hbp, (int)report_if_found					  MEM_FOUND_ADDR);        } else if (empty) {#	  ifdef GATHERSTATS            GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);#	  endif          GC_freehblk(hbp);        } else if (TRUE != GC_block_nearly_full(hhdr)){          /* group of smaller objects, enqueue the real work */          rlh = &(ok -> ok_reclaim_list[sz]);          hhdr -> hb_next = *rlh;          *rlh = hbp;        } /* else not worth salvaging. */	/* We used to do the nearly_full check later, but we 	*/	/* already have the right cache context here.  Also	*/	/* doing it here avoids some silly lock contention in	*/	/* GC_malloc_many.					*/    }}#if !defined(NO_DEBUGGING)/* Routines to gather and print heap block info 	*//* intended for debugging.  Otherwise should be called	*//* with lock.						*/struct Print_stats{	size_t number_of_blocks;	size_t total_bytes;};#ifdef USE_MARK_BYTES/* Return the number of set mark bits in the given header	*/int GC_n_set_marks(hhdr)hdr * hhdr;{    register int result = 0;    register int i;        for (i = 0; i < MARK_BITS_SZ; i++) {        result += hhdr -> hb_marks[i];    }    return(result);}#else/* Number of set bits in a word.  Not performance critical.	*/static int set_bits(n)word n;{    register word m = n;    register int result = 0;        while (m > 0) {    	if (m & 1) result++;    	m >>= 1;    }    return(result);}/* Return the number of set mark bits in the given header	*/int GC_n_set_marks(hhdr)hdr * hhdr;{    register int result = 0;    register int i;        for (i = 0; i < MARK_BITS_SZ; i++) {        result += set_bits(hhdr -> hb_marks[i]);    }    return(result);}#endif /* !USE_MARK_BYTES  *//*ARGSUSED*/# if defined(__STDC__) || defined(__cplusplus)    void GC_print_block_descr(struct hblk *h, word dummy)# else    void GC_print_block_descr(h, dummy)    struct hblk *h;    word dummy;# endif{    register hdr * hhdr = HDR(h);    register size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);    struct Print_stats *ps;        GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr -> hb_obj_kind),    			        (unsigned long)bytes,    			        (unsigned long)(GC_n_set_marks(hhdr)));    bytes += HBLKSIZE-1;    bytes &= ~(HBLKSIZE-1);    ps = (struct Print_stats *)dummy;    ps->total_bytes += bytes;    ps->number_of_blocks++;}void GC_print_block_list(){    struct Print_stats pstats;    GC_printf1("(kind(0=ptrfree,1=normal,2=unc.,%lu=stubborn):size_in_bytes, #_marks_set)\n", STUBBORN);    pstats.number_of_blocks = 0;    pstats.total_bytes = 0;    GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);    GC_printf2("\nblocks = %lu, bytes = %lu\n",    	       (unsigned long)pstats.number_of_blocks,    	       (unsigned long)pstats.total_bytes);}#endif /* NO_DEBUGGING *//* * Clear all obj_link pointers in the list of free objects *flp. * Clear *flp. * This must be done before dropping a list of free gcj-style objects, * since may otherwise end up with dangling "descriptor" pointers. * It may help for other pointer-containing objects. */void GC_clear_fl_links(flp)ptr_t *flp;{    ptr_t next = *flp;    while (0 != next) {       *flp = 0;       flp = &(obj_link(next));       next = *flp;    }}/* * Perform GC_reclaim_block on the entire heap, after first clearing * small object free lists (if we are not just looking for leaks). */void GC_start_reclaim(report_if_found)int report_if_found;		/* Abort if a GC_reclaimable object is found */{    int kind;    #   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)      GC_ASSERT(0 == GC_fl_builder_count);#   endif    /* Clear reclaim- and free-lists */      for (kind = 0; kind < GC_n_kinds; kind++) {        ptr_t *fop;        ptr_t *lim;        struct hblk ** rlp;        struct hblk ** rlim;        struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;	GC_bool should_clobber = (GC_obj_kinds[kind].ok_descriptor != 0);                if (rlist == 0) continue;	/* This kind not used.	*/        if (!report_if_found) {            lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);	    for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {	      if (*fop != 0) {		if (should_clobber) {		  GC_clear_fl_links(fop);		} else {	          *fop = 0;		}	      }	    }	} /* otherwise free list objects are marked, 	*/	  /* and its safe to leave them			*/	rlim = rlist + MAXOBJSZ+1;	for( rlp = rlist; rlp < rlim; rlp++ ) {	    *rlp = 0;	}      }    #   ifdef PRINTBLOCKS        GC_printf0("GC_reclaim: current block sizes:\n");        GC_print_block_list();#   endif  /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */  /* or enqueue the block for later processing.				   */    GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found);# ifdef EAGER_SWEEP    /* This is a very stupid thing to do.  We make it possible anyway,	*/    /* so that you can convince yourself that it really is very stupid.	*/    GC_reclaim_all((GC_stop_func)0, FALSE);# endif# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)    GC_ASSERT(0 == GC_fl_builder_count);# endif    }/* * Sweep blocks of the indicated object size and kind until either the * appropriate free list is nonempty, or there are no more blocks to * sweep. */void GC_continue_reclaim(sz, kind)word sz;	/* words */int kind;{    register hdr * hhdr;    register struct hblk * hbp;    register struct obj_kind * ok = &(GC_obj_kinds[kind]);    struct hblk ** rlh = ok -> ok_reclaim_list;    ptr_t *flh = &(ok -> ok_freelist[sz]);        if (rlh == 0) return;	/* No blocks of this kind.	*/    rlh += sz;    while ((hbp = *rlh) != 0) {        hhdr = HDR(hbp);        *rlh = hhdr -> hb_next;        GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);        if (*flh != 0) break;    }}/* * Reclaim all small blocks waiting to be reclaimed. * Abort and return FALSE when/if (*stop_func)() returns TRUE. * If this returns TRUE, then it's safe to restart the world * with incorrectly cleared mark bits. * If ignore_old is TRUE, then reclaim only blocks that have been  * recently reclaimed, and discard the rest. * Stop_func may be 0. */GC_bool GC_reclaim_all(stop_func, ignore_old)GC_stop_func stop_func;GC_bool ignore_old;{    register word sz;    register int kind;    register hdr * hhdr;    register struct hblk * hbp;    register struct obj_kind * ok;    struct hblk ** rlp;    struct hblk ** rlh;#   ifdef PRINTTIMES	CLOCK_TYPE start_time;	CLOCK_TYPE done_time;		GET_TIME(start_time);#   endif        for (kind = 0; kind < GC_n_kinds; kind++) {    	ok = &(GC_obj_kinds[kind]);    	rlp = ok -> ok_reclaim_list;    	if (rlp == 0) continue;    	for (sz = 1; sz <= MAXOBJSZ; sz++) {    	    rlh = rlp + sz;    	    while ((hbp = *rlh) != 0) {    	        if (stop_func != (GC_stop_func)0 && (*stop_func)()) {    	            return(FALSE);    	        }        	hhdr = HDR(hbp);        	*rlh = hhdr -> hb_next;        	if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) {        	    /* It's likely we'll need it this time, too	*/        	    /* It's been touched recently, so this	*/        	    /* shouldn't trigger paging.		*/        	    GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);        	}            }        }    }#   ifdef PRINTTIMES	GET_TIME(done_time);	GC_printf1("Disposing of reclaim lists took %lu msecs\n",	           MS_TIME_DIFF(done_time,start_time));#   endif    return(TRUE);}

⌨️ 快捷键说明

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