/* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991, 1992 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 copy this garbage collector for any purpose, * provided the above notices are retained on all copies. */ /* Routines for maintaining maps describing heap block * layouts for various object sizes. Allows fast pointer validity checks * and fast location of object start locations on machines (such as SPARC) * with slow division. * * Boehm, February 6, 1992 1:00:09 pm PST */ # include "gc←private.h" char * GC←invalid←map = 0; /* Invalidate the object map associated with a block. Free blocks */ /* are identified by invalid maps. */ void GC←invalidate←map(hhdr) hdr *hhdr; { register int displ; if (GC←invalid←map == 0) { GC←invalid←map = GC←scratch←alloc(MAP←SIZE); for (displ = 0; displ < HBLKSIZE; displ++) { MAP←ENTRY(GC←invalid←map, displ) = OBJ←INVALID; } } hhdr -> hb←map = GC←invalid←map; } /* Consider pointers that are offset bytes displaced from the beginning */ /* of an object to be valid. */ void GC←register←displacement(offset) word offset; { # ifndef ALL←INTERIOR←POINTERS DCL←LOCK←STATE; DISABLE←SIGNALS(); LOCK(); GC←register←displacement←inner(offset); UNLOCK(); ENABLE←SIGNALS(); # endif } void GC←register←displacement←inner(offset) word offset; { # ifndef ALL←INTERIOR←POINTERS register int i; if (offset > MAX←OFFSET) { ABORT("Bad argument to GC←register←displacement"); } if (!GC←valid←offsets[offset]) { GC←valid←offsets[offset] = TRUE; GC←modws←valid←offsets[offset % sizeof(word)] = TRUE; for (i = 0; i <= MAXOBJSZ; i++) { if (GC←obj←map[i] != 0) { if (i == 0) { GC←obj←map[i][offset + HDR←BYTES] = offset >> 2; } else { register int j; register int lb = WORDS←TO←BYTES(i); if (offset < lb) { for (j = offset + HDR←BYTES; j < HBLKSIZE; j += lb) { GC←obj←map[i][j] = offset >> 2; } } } } } } # endif } /* Add a heap block map for objects of size sz to obj←map. */ void GC←add←map←entry(sz) word sz; { register int obj←start; register int displ; register char * new←map; if (sz > MAXOBJSZ) sz = 0; if (GC←obj←map[sz] != 0) { return; } new←map = GC←scratch←alloc(MAP←SIZE); # ifdef PRINTSTATS GC←printf1("Adding block map for size %lu\n", (unsigned long)sz); # endif for (displ = 0; displ < HBLKSIZE; displ++) { MAP←ENTRY(new←map,displ) = OBJ←INVALID; } if (sz == 0) { for(displ = 0; displ <= MAX←OFFSET; displ++) { if (OFFSET←VALID(displ)) { MAP←ENTRY(new←map,displ+HDR←BYTES) = BYTES←TO←WORDS(displ); } } } else { for (obj←start = HDR←BYTES; obj←start + WORDS←TO←BYTES(sz) <= HBLKSIZE; obj←start += WORDS←TO←BYTES(sz)) { for (displ = 0; displ < WORDS←TO←BYTES(sz); displ++) { if (OFFSET←VALID(displ)) { MAP←ENTRY(new←map, obj←start + displ) = BYTES←TO←WORDS(displ); } } } } GC←obj←map[sz] = new←map; }