263 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
 | |
|  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 | |
|  * Copyright (c) 2000 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.
 | |
|  *
 | |
|  * This file contains the functions:
 | |
|  *	ptr_t GC_build_flXXX(h, old_fl)
 | |
|  *	void GC_new_hblk(n)
 | |
|  */
 | |
| /* Boehm, May 19, 1994 2:09 pm PDT */
 | |
| 
 | |
| 
 | |
| # include <stdio.h>
 | |
| # include "private/gc_priv.h"
 | |
| 
 | |
| #ifndef SMALL_CONFIG
 | |
| /*
 | |
|  * Build a free list for size 1 objects inside hblk h.  Set the last link to
 | |
|  * be ofl.  Return a pointer tpo the first free list entry.
 | |
|  */
 | |
| ptr_t GC_build_fl1(h, ofl)
 | |
| struct hblk *h;
 | |
| ptr_t ofl;
 | |
| {
 | |
|     register word * p = h -> hb_body;
 | |
|     register word * lim = (word *)(h + 1);
 | |
|     
 | |
|     p[0] = (word)ofl;
 | |
|     p[1] = (word)(p);
 | |
|     p[2] = (word)(p+1);
 | |
|     p[3] = (word)(p+2);
 | |
|     p += 4;
 | |
|     for (; p < lim; p += 4) {
 | |
|         p[0] = (word)(p-1);
 | |
|         p[1] = (word)(p);
 | |
|         p[2] = (word)(p+1);
 | |
|         p[3] = (word)(p+2);
 | |
|     };
 | |
|     return((ptr_t)(p-1));
 | |
| }
 | |
| 
 | |
| /* The same for size 2 cleared objects */
 | |
| ptr_t GC_build_fl_clear2(h, ofl)
 | |
| struct hblk *h;
 | |
| ptr_t ofl;
 | |
| {
 | |
|     register word * p = h -> hb_body;
 | |
|     register word * lim = (word *)(h + 1);
 | |
|     
 | |
|     p[0] = (word)ofl;
 | |
|     p[1] = 0;
 | |
|     p[2] = (word)p;
 | |
|     p[3] = 0;
 | |
|     p += 4;
 | |
|     for (; p < lim; p += 4) {
 | |
|         p[0] = (word)(p-2);
 | |
|         p[1] = 0;
 | |
|         p[2] = (word)p;
 | |
|         p[3] = 0;
 | |
|     };
 | |
|     return((ptr_t)(p-2));
 | |
| }
 | |
| 
 | |
| /* The same for size 3 cleared objects */
 | |
| ptr_t GC_build_fl_clear3(h, ofl)
 | |
| struct hblk *h;
 | |
| ptr_t ofl;
 | |
| {
 | |
|     register word * p = h -> hb_body;
 | |
|     register word * lim = (word *)(h + 1) - 2;
 | |
|     
 | |
|     p[0] = (word)ofl;
 | |
|     p[1] = 0;
 | |
|     p[2] = 0;
 | |
|     p += 3;
 | |
|     for (; p < lim; p += 3) {
 | |
|         p[0] = (word)(p-3);
 | |
|         p[1] = 0;
 | |
|         p[2] = 0;
 | |
|     };
 | |
|     return((ptr_t)(p-3));
 | |
| }
 | |
| 
 | |
| /* The same for size 4 cleared objects */
 | |
| ptr_t GC_build_fl_clear4(h, ofl)
 | |
| struct hblk *h;
 | |
| ptr_t ofl;
 | |
| {
 | |
|     register word * p = h -> hb_body;
 | |
|     register word * lim = (word *)(h + 1);
 | |
|     
 | |
|     p[0] = (word)ofl;
 | |
|     p[1] = 0;
 | |
|     p[2] = 0;
 | |
|     p[3] = 0;
 | |
|     p += 4;
 | |
|     for (; p < lim; p += 4) {
 | |
| 	PREFETCH_FOR_WRITE(p+64);
 | |
|         p[0] = (word)(p-4);
 | |
|         p[1] = 0;
 | |
| 	CLEAR_DOUBLE(p+2);
 | |
|     };
 | |
|     return((ptr_t)(p-4));
 | |
| }
 | |
| 
 | |
| /* The same for size 2 uncleared objects */
 | |
| ptr_t GC_build_fl2(h, ofl)
 | |
| struct hblk *h;
 | |
| ptr_t ofl;
 | |
| {
 | |
|     register word * p = h -> hb_body;
 | |
|     register word * lim = (word *)(h + 1);
 | |
|     
 | |
|     p[0] = (word)ofl;
 | |
|     p[2] = (word)p;
 | |
|     p += 4;
 | |
|     for (; p < lim; p += 4) {
 | |
|         p[0] = (word)(p-2);
 | |
|         p[2] = (word)p;
 | |
|     };
 | |
|     return((ptr_t)(p-2));
 | |
| }
 | |
| 
 | |
| /* The same for size 4 uncleared objects */
 | |
| ptr_t GC_build_fl4(h, ofl)
 | |
| struct hblk *h;
 | |
| ptr_t ofl;
 | |
| {
 | |
|     register word * p = h -> hb_body;
 | |
|     register word * lim = (word *)(h + 1);
 | |
|     
 | |
|     p[0] = (word)ofl;
 | |
|     p[4] = (word)p;
 | |
|     p += 8;
 | |
|     for (; p < lim; p += 8) {
 | |
| 	PREFETCH_FOR_WRITE(p+64);
 | |
|         p[0] = (word)(p-4);
 | |
|         p[4] = (word)p;
 | |
|     };
 | |
|     return((ptr_t)(p-4));
 | |
| }
 | |
| 
 | |
| #endif /* !SMALL_CONFIG */
 | |
| 
 | |
| 
 | |
| /* Build a free list for objects of size sz inside heap block h.	*/
 | |
| /* Clear objects inside h if clear is set.  Add list to the end of	*/
 | |
| /* the free list we build.  Return the new free list.			*/
 | |
| /* This could be called without the main GC lock, if we ensure that	*/
 | |
| /* there is no concurrent collection which might reclaim objects that	*/
 | |
| /* we have not yet allocated.						*/
 | |
| ptr_t GC_build_fl(h, sz, clear, list)
 | |
| struct hblk *h;
 | |
| word sz;
 | |
| GC_bool clear;
 | |
| ptr_t list;
 | |
| {
 | |
|   word *p, *prev;
 | |
|   word *last_object;		/* points to last object in new hblk	*/
 | |
| 
 | |
|   /* Do a few prefetches here, just because its cheap.  	*/
 | |
|   /* If we were more serious about it, these should go inside	*/
 | |
|   /* the loops.  But write prefetches usually don't seem to	*/
 | |
|   /* matter much.						*/
 | |
|     PREFETCH_FOR_WRITE((char *)h);
 | |
|     PREFETCH_FOR_WRITE((char *)h + 128);
 | |
|     PREFETCH_FOR_WRITE((char *)h + 256);
 | |
|     PREFETCH_FOR_WRITE((char *)h + 378);
 | |
|   /* Handle small objects sizes more efficiently.  For larger objects 	*/
 | |
|   /* the difference is less significant.				*/
 | |
| #  ifndef SMALL_CONFIG
 | |
|     switch (sz) {
 | |
|         case 1: return GC_build_fl1(h, list);
 | |
|         case 2: if (clear) {
 | |
|         	    return GC_build_fl_clear2(h, list);
 | |
|         	} else {
 | |
|         	    return GC_build_fl2(h, list);
 | |
|         	}
 | |
|         case 3: if (clear) {
 | |
|          	    return GC_build_fl_clear3(h, list);
 | |
|         	} else {
 | |
|         	    /* It's messy to do better than the default here. */
 | |
|         	    break;
 | |
|         	}
 | |
|         case 4: if (clear) {
 | |
|         	    return GC_build_fl_clear4(h, list);
 | |
|         	} else {
 | |
|         	    return GC_build_fl4(h, list);
 | |
|         	}
 | |
|         default:
 | |
|         	break;
 | |
|     }
 | |
| #  endif /* !SMALL_CONFIG */
 | |
|     
 | |
|   /* Clear the page if necessary. */
 | |
|     if (clear) BZERO(h, HBLKSIZE);
 | |
|     
 | |
|   /* Add objects to free list */
 | |
|     p = &(h -> hb_body[sz]);	/* second object in *h	*/
 | |
|     prev = &(h -> hb_body[0]);       	/* One object behind p	*/
 | |
|     last_object = (word *)((char *)h + HBLKSIZE);
 | |
|     last_object -= sz;
 | |
| 			    /* Last place for last object to start */
 | |
| 
 | |
|   /* make a list of all objects in *h with head as last object */
 | |
|     while (p <= last_object) {
 | |
|       /* current object's link points to last object */
 | |
|         obj_link(p) = (ptr_t)prev;
 | |
| 	prev = p;
 | |
| 	p += sz;
 | |
|     }
 | |
|     p -= sz;			/* p now points to last object */
 | |
| 
 | |
|   /*
 | |
|    * put p (which is now head of list of objects in *h) as first
 | |
|    * pointer in the appropriate free list for this size.
 | |
|    */
 | |
|       obj_link(h -> hb_body) = list;
 | |
|       return ((ptr_t)p);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Allocate a new heapblock for small objects of size n.
 | |
|  * Add all of the heapblock's objects to the free list for objects
 | |
|  * of that size.
 | |
|  * Set all mark bits if objects are uncollectable.
 | |
|  * Will fail to do anything if we are out of memory.
 | |
|  */
 | |
| void GC_new_hblk(sz, kind)
 | |
| register word sz;
 | |
| int kind;
 | |
| {
 | |
|     register struct hblk *h;	/* the new heap block			*/
 | |
|     register GC_bool clear = GC_obj_kinds[kind].ok_init;
 | |
| 
 | |
| #   ifdef PRINTSTATS
 | |
| 	if ((sizeof (struct hblk)) > HBLKSIZE) {
 | |
| 	    ABORT("HBLK SZ inconsistency");
 | |
|         }
 | |
| #   endif
 | |
| 
 | |
|   /* Allocate a new heap block */
 | |
|     h = GC_allochblk(sz, kind, 0);
 | |
|     if (h == 0) return;
 | |
| 
 | |
|   /* Mark all objects if appropriate. */
 | |
|       if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));
 | |
| 
 | |
|   /* Build the free list */
 | |
|       GC_obj_kinds[kind].ok_freelist[sz] =
 | |
| 	GC_build_fl(h, sz, clear, GC_obj_kinds[kind].ok_freelist[sz]);
 | |
| }
 | |
| 
 |