diff options
Diffstat (limited to 'gc/new_hblk.c')
-rw-r--r-- | gc/new_hblk.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/gc/new_hblk.c b/gc/new_hblk.c new file mode 100644 index 0000000..9f32ae0 --- /dev/null +++ b/gc/new_hblk.c @@ -0,0 +1,244 @@ +/* + * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers + * Copyright (c) 1991-1994 by Xerox Corporation. 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 "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 = (word *)h; + 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 = (word *)h; + 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 = (word *)h; + 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 = (word *)h; + 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) { + p[0] = (word)(p-4); + p[1] = 0; + p[2] = 0; + p[3] = 0; + }; + 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 = (word *)h; + 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 = (word *)h; + register word * lim = (word *)(h + 1); + + p[0] = (word)ofl; + p[4] = (word)p; + p += 8; + for (; p < lim; p += 8) { + p[0] = (word)(p-4); + p[4] = (word)p; + }; + return((ptr_t)(p-4)); +} + +#endif /* !SMALL_CONFIG */ + +/* + * 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 word *p, + *prev; + word *last_object; /* points to last object in new hblk */ + 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)); + + /* Handle small objects sizes more efficiently. For larger objects */ + /* the difference is less significant. */ +# ifndef SMALL_CONFIG + switch (sz) { + case 1: GC_obj_kinds[kind].ok_freelist[1] = + GC_build_fl1(h, GC_obj_kinds[kind].ok_freelist[1]); + return; + case 2: if (clear) { + GC_obj_kinds[kind].ok_freelist[2] = + GC_build_fl_clear2(h, GC_obj_kinds[kind].ok_freelist[2]); + } else { + GC_obj_kinds[kind].ok_freelist[2] = + GC_build_fl2(h, GC_obj_kinds[kind].ok_freelist[2]); + } + return; + case 3: if (clear) { + GC_obj_kinds[kind].ok_freelist[3] = + GC_build_fl_clear3(h, GC_obj_kinds[kind].ok_freelist[3]); + return; + } else { + /* It's messy to do better than the default here. */ + break; + } + case 4: if (clear) { + GC_obj_kinds[kind].ok_freelist[4] = + GC_build_fl_clear4(h, GC_obj_kinds[kind].ok_freelist[4]); + } else { + GC_obj_kinds[kind].ok_freelist[4] = + GC_build_fl4(h, GC_obj_kinds[kind].ok_freelist[4]); + } + return; + 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) = GC_obj_kinds[kind].ok_freelist[sz]; + GC_obj_kinds[kind].ok_freelist[sz] = ((ptr_t)p); +} + |