summaryrefslogtreecommitdiff
path: root/obj_map.c
blob: 40b2d881af5a361fbb5de08aab8f37ec935c7b10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* 
 * 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);
        if (GC_invalid_map == 0) {
            GC_err_printf0(
            	"Cant initialize GC_invalid_map: insufficient memory\n");
            EXIT();
        }
        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] = BYTES_TO_WORDS(offset);
             } 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] = BYTES_TO_WORDS(offset);
                 }
               }
             }
          }
      }
    }
# endif
}


/* Add a heap block map for objects of size sz to obj_map.	*/
/* Return FALSE on failure.					*/
bool 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(TRUE);
    }
    new_map = GC_scratch_alloc(MAP_SIZE);
    if (new_map == 0) return(FALSE);
#   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;
    return(TRUE);
}