OSDN Git Service

* config/c4x/c4x.c (c4x_emit_move_sequence): Use loadqi_big_constant
[pf3gnuchains/gcc-fork.git] / boehm-gc / ptr_chck.c
1 /* 
2  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
3  *
4  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
6  *
7  * Permission is hereby granted to use or copy this program
8  * for any purpose,  provided the above notices are retained on all copies.
9  * Permission to modify the code and to distribute modified code is granted,
10  * provided the above notices are retained, and a notice that the code was
11  * modified is included with the above copyright notice.
12  */
13 /* Boehm, September 19, 1995 1:26 pm PDT */
14
15 #include "gc_priv.h"
16 #include "gc_mark.h"
17
18 #ifdef __STDC__
19 void GC_default_same_obj_print_proc(GC_PTR p, GC_PTR q)
20 #else
21 void GC_default_same_obj_print_proc (p, q)
22 GC_PTR p, q;
23 #endif
24 {
25     GC_err_printf2("0x%lx and 0x%lx are not in the same object\n",
26                    (unsigned long)p, (unsigned long)q);
27     ABORT("GC_same_obj test failed");
28 }
29
30 void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR, GC_PTR))
31                 = GC_default_same_obj_print_proc;
32
33 /* Check that p and q point to the same object.  Call           */
34 /* *GC_same_obj_print_proc if they don't.                       */
35 /* Returns the first argument.  (Return value may be hard       */
36 /* to use,due to typing issues.  But if we had a suitable       */
37 /* preprocessor ...)                                            */
38 /* Succeeds if neither p nor q points to the heap.              */
39 /* We assume this is performance critical.  (It shouldn't       */
40 /* be called by production code, but this can easily make       */
41 /* debugging intolerably slow.)                                 */
42 #ifdef __STDC__
43   GC_PTR GC_same_obj(register void *p, register void *q)
44 #else
45   GC_PTR GC_same_obj(p, q)
46   register char *p, *q;
47 #endif
48 {
49     register struct hblk *h;
50     register hdr *hhdr;
51     register ptr_t base, limit;
52     register word sz;
53     
54     if (!GC_is_initialized) GC_init();
55     hhdr = HDR((word)p);
56     if (hhdr == 0) {
57         if (divHBLKSZ((word)p) != divHBLKSZ((word)q)
58             && HDR((word)q) != 0) {
59             goto fail;
60         }
61         return(p);
62     }
63     /* If it's a pointer to the middle of a large object, move it       */
64     /* to the beginning.                                                */
65     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
66         h = HBLKPTR(p) - (word)hhdr;
67         hhdr = HDR(h);
68         while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
69            h = FORWARDED_ADDR(h, hhdr);
70            hhdr = HDR(h);
71         }
72         limit = (ptr_t)((word *)h + HDR_WORDS + hhdr -> hb_sz);
73         if ((ptr_t)p >= limit || (ptr_t)q >= limit || (ptr_t)q < (ptr_t)h ) {
74             goto fail;
75         }
76         return(p);
77     }
78     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
79     if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
80       base = (ptr_t)HBLKPTR(p);
81       limit = base + sz;
82       if ((ptr_t)p >= limit) {
83         goto fail;
84       }
85     } else {
86 #     ifdef ALL_INTERIOR_POINTERS
87         register map_entry_type map_entry;
88         register int pdispl;
89         
90         pdispl = HBLKDISPL(p);
91         map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
92         if (map_entry == OBJ_INVALID) {
93             goto fail;
94         } else {
95             base = (char *)((word)p & ~(WORDS_TO_BYTES(1) - 1));
96             base -= WORDS_TO_BYTES(map_entry);
97         }
98 #     else
99         register int offset = HBLKDISPL(p) - HDR_BYTES;
100         register word correction = offset % sz;
101         
102         if (HBLKPTR(p) != HBLKPTR(q)) {
103             /* The following computation otherwise fails in this case */
104             goto fail;
105         }
106         base = (ptr_t)p - correction;
107 #     endif
108       limit = base + sz;
109     }
110     /* [base, limit) delimits the object containing p, if any.  */
111     /* If p is not inside a valid object, then either q is      */
112     /* also outside any valid object, or it is outside          */
113     /* [base, limit).                                           */
114     if ((ptr_t)q >= limit || (ptr_t)q < base) {
115         goto fail;
116     }
117     return(p);
118 fail:
119     (*GC_same_obj_print_proc)((ptr_t)p, (ptr_t)q);
120     return(p);
121 }
122
123 #ifdef __STDC__
124 void GC_default_is_valid_displacement_print_proc (GC_PTR p)
125 #else
126 void GC_default_is_valid_displacement_print_proc (p)
127 GC_PTR p;
128 #endif
129 {
130     GC_err_printf1("0x%lx does not point to valid object displacement\n",
131                    (unsigned long)p);
132     ABORT("GC_is_valid_displacement test failed");
133 }
134
135 void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) = 
136         GC_default_is_valid_displacement_print_proc;
137
138 /* Check that if p is a pointer to a heap page, then it points to       */
139 /* a valid displacement within a heap object.                           */
140 /* Uninteresting with ALL_INTERIOR_POINTERS.                            */
141 /* Always returns its argument.                                         */
142 /* Note that we don't lock, since nothing relevant about the header     */
143 /* should change while we have a valid object pointer to the block.     */
144 #ifdef __STDC__
145   void * GC_is_valid_displacement(void *p)
146 #else
147   char *GC_is_valid_displacement(p)
148   char *p;
149 #endif
150 {
151     register hdr *hhdr;
152     register word pdispl;
153     register struct hblk *h;
154     register map_entry_type map_entry;
155     register word sz;
156     
157     if (!GC_is_initialized) GC_init();
158     hhdr = HDR((word)p);
159     if (hhdr == 0) return(p);
160     h = HBLKPTR(p);
161 #   ifdef ALL_INTERIOR_POINTERS
162         while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
163            h = FORWARDED_ADDR(h, hhdr);
164            hhdr = HDR(h);
165         }
166 #   endif
167     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
168         goto fail;
169     }
170     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
171     pdispl = HBLKDISPL(p);
172     map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
173     if (map_entry == OBJ_INVALID
174         || sz > MAXOBJSZ && (ptr_t)p >= (ptr_t)h + sz) {
175         goto fail;
176     }
177     return(p);
178 fail:
179     (*GC_is_valid_displacement_print_proc)((ptr_t)p);
180     return(p);
181 }
182
183 #ifdef __STDC__
184 void GC_default_is_visible_print_proc(GC_PTR p)
185 #else
186 void GC_default_is_visible_print_proc(p)
187 GC_PTR p;
188 #endif
189 {
190     GC_err_printf1("0x%lx is not a GC visible pointer location\n",
191                    (unsigned long)p);
192     ABORT("GC_is_visible test failed");
193 }
194
195 void (*GC_is_visible_print_proc) GC_PROTO((GC_PTR p)) = 
196         GC_default_is_visible_print_proc;
197
198 /* Could p be a stack address? */
199 GC_bool GC_on_stack(p)
200 ptr_t p;
201 {
202 #   ifdef THREADS
203         return(TRUE);
204 #   else
205         int dummy;
206 #       ifdef STACK_GROWS_DOWN
207             if ((ptr_t)p >= (ptr_t)(&dummy) && (ptr_t)p < GC_stackbottom ) {
208                 return(TRUE);
209             }
210 #       else
211             if ((ptr_t)p <= (ptr_t)(&dummy) && (ptr_t)p > GC_stackbottom ) {
212                 return(TRUE);
213             }
214 #       endif
215         return(FALSE);
216 #   endif
217 }
218
219 /* Check that p is visible                                              */
220 /* to the collector as a possibly pointer containing location.          */
221 /* If it isn't invoke *GC_is_visible_print_proc.                        */
222 /* Returns the argument in all cases.  May erroneously succeed          */
223 /* in hard cases.  (This is intended for debugging use with             */
224 /* untyped allocations.  The idea is that it should be possible, though */
225 /* slow, to add such a call to all indirect pointer stores.)            */
226 /* Currently useless for multithreaded worlds.                          */
227 #ifdef __STDC__
228   void * GC_is_visible(void *p)
229 #else
230   char *GC_is_visible(p)
231   char *p;
232 #endif
233 {
234     register hdr *hhdr;
235     
236     if ((word)p & (ALIGNMENT - 1)) goto fail;
237     if (!GC_is_initialized) GC_init();
238 #   ifdef THREADS
239         hhdr = HDR((word)p);
240         if (hhdr != 0 && GC_base(p) == 0) {
241             goto fail;
242         } else {
243             /* May be inside thread stack.  We can't do much. */
244             return(p);
245         }
246 #   else
247         /* Check stack first: */
248           if (GC_on_stack(p)) return(p);
249         hhdr = HDR((word)p);
250         if (hhdr == 0) {
251             GC_bool result;
252             
253             if (GC_is_static_root(p)) return(p);
254             /* Else do it again correctly:      */
255 #           if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(PCR)) \
256                 && !defined(SRC_M3)
257                 DISABLE_SIGNALS();
258                 GC_register_dynamic_libraries();
259                 result = GC_is_static_root(p);
260                 ENABLE_SIGNALS();
261                 if (result) return(p);
262 #           endif
263             goto fail;
264         } else {
265             /* p points to the heap. */
266             word descr;
267             ptr_t base = GC_base(p);    /* Should be manually inlined? */
268             
269             if (base == 0) goto fail;
270             if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
271             descr = hhdr -> hb_descr;
272     retry:
273             switch(descr & DS_TAGS) {
274                 case DS_LENGTH:
275                     if ((word)((ptr_t)p - (ptr_t)base) > (word)descr) goto fail;
276                     break;
277                 case DS_BITMAP:
278                     if ((ptr_t)p - (ptr_t)base
279                          >= WORDS_TO_BYTES(BITMAP_BITS)
280                          || ((word)p & (sizeof(word) - 1))) goto fail;
281                     if (!((1 << (WORDSZ - ((ptr_t)p - (ptr_t)base) - 1))
282                           & descr)) goto fail;
283                     break;
284                 case DS_PROC:
285                     /* We could try to decipher this partially.         */
286                     /* For now we just punt.                            */
287                     break;
288                 case DS_PER_OBJECT:
289                     descr = *(word *)((ptr_t)base + (descr & ~DS_TAGS));
290                     goto retry;
291             }
292             return(p);
293         }
294 #   endif
295 fail:
296     (*GC_is_visible_print_proc)((ptr_t)p);
297     return(p);
298 }
299
300
301 GC_PTR GC_pre_incr (p, how_much)
302 GC_PTR *p;
303 size_t how_much;
304 {
305     GC_PTR initial = *p;
306     GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
307     
308 #   ifndef ALL_INTERIOR_POINTERS
309         (void) GC_is_valid_displacement(result);
310 #   endif
311     return (*p = result);
312 }
313
314 GC_PTR GC_post_incr (p, how_much)
315 GC_PTR *p;
316 size_t how_much;
317 {
318     GC_PTR initial = *p;
319     GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
320  
321 #   ifndef ALL_INTERIOR_POINTERS
322         (void) GC_is_valid_displacement(result);
323 #   endif   
324     *p = result;
325     return(initial);
326 }