* Moved boehm-gc from src/ to src/mm/.
[cacao.git] / src / mm / boehm-gc / obj_map.c
1 /* 
2  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3  * Copyright (c) 1991, 1992 by Xerox Corporation.  All rights reserved.
4  * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
5  *
6  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
8  *
9  * Permission is hereby granted to use or copy this program
10  * for any purpose,  provided the above notices are retained on all copies.
11  * Permission to modify the code and to distribute modified code is granted,
12  * provided the above notices are retained, and a notice that the code was
13  * modified is included with the above copyright notice.
14  */
15   
16 /* Routines for maintaining maps describing heap block
17  * layouts for various object sizes.  Allows fast pointer validity checks
18  * and fast location of object start locations on machines (such as SPARC)
19  * with slow division.
20  */
21
22 #include "config.h"
23  
24 # include "private/gc_priv.h"
25
26 map_entry_type * GC_invalid_map = 0;
27
28 /* Invalidate the object map associated with a block.   Free blocks     */
29 /* are identified by invalid maps.                                      */
30 void GC_invalidate_map(hhdr)
31 hdr *hhdr;
32 {
33     register int displ;
34     
35     if (GC_invalid_map == 0) {
36         GC_invalid_map = (map_entry_type *)GC_scratch_alloc(MAP_SIZE);
37         if (GC_invalid_map == 0) {
38             GC_err_printf0(
39                 "Cant initialize GC_invalid_map: insufficient memory\n");
40             EXIT();
41         }
42         for (displ = 0; displ < HBLKSIZE; displ++) {
43             MAP_ENTRY(GC_invalid_map, displ) = OBJ_INVALID;
44         }
45     }
46     hhdr -> hb_map = GC_invalid_map;
47 }
48
49 /* Consider pointers that are offset bytes displaced from the beginning */
50 /* of an object to be valid.                                            */
51
52 # if defined(__STDC__) || defined(__cplusplus)
53     void GC_register_displacement(GC_word offset)
54 # else
55     void GC_register_displacement(offset) 
56     GC_word offset;
57 # endif
58 {
59     DCL_LOCK_STATE;
60     
61     DISABLE_SIGNALS();
62     LOCK();
63     GC_register_displacement_inner(offset);
64     UNLOCK();
65     ENABLE_SIGNALS();
66 }
67
68 void GC_register_displacement_inner(offset) 
69 word offset;
70 {
71     register unsigned i;
72     word map_entry = BYTES_TO_WORDS(offset);
73     
74     if (offset >= VALID_OFFSET_SZ) {
75         ABORT("Bad argument to GC_register_displacement");
76     }
77     if (map_entry > MAX_OFFSET) map_entry = OFFSET_TOO_BIG;
78     if (!GC_valid_offsets[offset]) {
79       GC_valid_offsets[offset] = TRUE;
80       GC_modws_valid_offsets[offset % sizeof(word)] = TRUE;
81       if (!GC_all_interior_pointers) {
82         for (i = 0; i <= MAXOBJSZ; i++) {
83           if (GC_obj_map[i] != 0) {
84              if (i == 0) {
85                GC_obj_map[i][offset] = (map_entry_type)map_entry;
86              } else {
87                register unsigned j;
88                register unsigned lb = WORDS_TO_BYTES(i);
89                
90                if (offset < lb) {
91                  for (j = offset; j < HBLKSIZE; j += lb) {
92                    GC_obj_map[i][j] = (map_entry_type)map_entry;
93                  }
94                }
95              }
96           }
97         }
98       }
99     }
100 }
101
102
103 /* Add a heap block map for objects of size sz to obj_map.      */
104 /* Return FALSE on failure.                                     */
105 GC_bool GC_add_map_entry(sz)
106 word sz;
107 {
108     register unsigned obj_start;
109     register unsigned displ;
110     register map_entry_type * new_map;
111     word map_entry;
112     
113     if (sz > MAXOBJSZ) sz = 0;
114     if (GC_obj_map[sz] != 0) {
115         return(TRUE);
116     }
117     new_map = (map_entry_type *)GC_scratch_alloc(MAP_SIZE);
118     if (new_map == 0) return(FALSE);
119 #   ifdef PRINTSTATS
120         GC_printf1("Adding block map for size %lu\n", (unsigned long)sz);
121 #   endif
122     for (displ = 0; displ < HBLKSIZE; displ++) {
123         MAP_ENTRY(new_map,displ) = OBJ_INVALID;
124     }
125     if (sz == 0) {
126         for(displ = 0; displ <= HBLKSIZE; displ++) {
127             if (OFFSET_VALID(displ)) {
128                 map_entry = BYTES_TO_WORDS(displ);
129                 if (map_entry > MAX_OFFSET) map_entry = OFFSET_TOO_BIG;
130                 MAP_ENTRY(new_map,displ) = (map_entry_type)map_entry;
131             }
132         }
133     } else {
134         for (obj_start = 0;
135              obj_start + WORDS_TO_BYTES(sz) <= HBLKSIZE;
136              obj_start += WORDS_TO_BYTES(sz)) {
137              for (displ = 0; displ < WORDS_TO_BYTES(sz); displ++) {
138                  if (OFFSET_VALID(displ)) {
139                      map_entry = BYTES_TO_WORDS(displ);
140                      if (map_entry > MAX_OFFSET) map_entry = OFFSET_TOO_BIG;
141                      MAP_ENTRY(new_map, obj_start + displ) =
142                                                 (map_entry_type)map_entry;
143                  }
144              }
145         }
146     }
147     GC_obj_map[sz] = new_map;
148     return(TRUE);
149 }