new Stack memory allocation, use of unused arg regs as temp disabled
[cacao.git] / src / boehm-gc / malloc.c
1 /* 
2  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
4  * Copyright (c) 2000 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 /* Boehm, February 7, 1996 4:32 pm PST */
16
17 #include "config.h"
18  
19 #include <stdio.h>
20 #include "private/gc_priv.h"
21
22 extern ptr_t GC_clear_stack();  /* in misc.c, behaves like identity */
23 void GC_extend_size_map();      /* in misc.c. */
24
25 /* Allocate reclaim list for kind:      */
26 /* Return TRUE on success               */
27 GC_bool GC_alloc_reclaim_list(kind)
28 register struct obj_kind * kind;
29 {
30     struct hblk ** result = (struct hblk **)
31                 GC_scratch_alloc((MAXOBJSZ+1) * sizeof(struct hblk *));
32     if (result == 0) return(FALSE);
33     BZERO(result, (MAXOBJSZ+1)*sizeof(struct hblk *));
34     kind -> ok_reclaim_list = result;
35     return(TRUE);
36 }
37
38 /* Allocate a large block of size lw words.     */
39 /* The block is not cleared.                    */
40 /* Flags is 0 or IGNORE_OFF_PAGE.               */
41 /* We hold the allocation lock.                 */
42 ptr_t GC_alloc_large(lw, k, flags)
43 word lw;
44 int k;
45 unsigned flags;
46 {
47     struct hblk * h;
48     word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
49     ptr_t result;
50         
51     if (!GC_is_initialized) GC_init_inner();
52     /* Do our share of marking work */
53         if(GC_incremental && !GC_dont_gc)
54             GC_collect_a_little_inner((int)n_blocks);
55     h = GC_allochblk(lw, k, flags);
56 #   ifdef USE_MUNMAP
57         if (0 == h) {
58             GC_merge_unmapped();
59             h = GC_allochblk(lw, k, flags);
60         }
61 #   endif
62     while (0 == h && GC_collect_or_expand(n_blocks, (flags != 0))) {
63         h = GC_allochblk(lw, k, flags);
64     }
65     if (h == 0) {
66         result = 0;
67     } else {
68         int total_bytes = n_blocks * HBLKSIZE;
69         if (n_blocks > 1) {
70             GC_large_allocd_bytes += total_bytes;
71             if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)
72                 GC_max_large_allocd_bytes = GC_large_allocd_bytes;
73         }
74         result = (ptr_t) (h -> hb_body);
75         GC_words_wasted += BYTES_TO_WORDS(total_bytes) - lw;
76     }
77     return result;
78 }
79
80
81 /* Allocate a large block of size lb bytes.  Clear if appropriate.      */
82 /* We hold the allocation lock.                                         */
83 ptr_t GC_alloc_large_and_clear(lw, k, flags)
84 word lw;
85 int k;
86 unsigned flags;
87 {
88     ptr_t result = GC_alloc_large(lw, k, flags);
89     word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
90
91     if (0 == result) return 0;
92     if (GC_debugging_started || GC_obj_kinds[k].ok_init) {
93         /* Clear the whole block, in case of GC_realloc call. */
94         BZERO(result, n_blocks * HBLKSIZE);
95     }
96     return result;
97 }
98
99 /* allocate lb bytes for an object of kind k.   */
100 /* Should not be used to directly to allocate   */
101 /* objects such as STUBBORN objects that        */
102 /* require special handling on allocation.      */
103 /* First a version that assumes we already      */
104 /* hold lock:                                   */
105 ptr_t GC_generic_malloc_inner(lb, k)
106 register word lb;
107 register int k;
108 {
109 register word lw;
110 register ptr_t op;
111 register ptr_t *opp;
112
113     if( SMALL_OBJ(lb) ) {
114         register struct obj_kind * kind = GC_obj_kinds + k;
115 #       ifdef MERGE_SIZES
116           lw = GC_size_map[lb];
117 #       else
118           lw = ALIGNED_WORDS(lb);
119           if (lw == 0) lw = MIN_WORDS;
120 #       endif
121         opp = &(kind -> ok_freelist[lw]);
122         if( (op = *opp) == 0 ) {
123 #           ifdef MERGE_SIZES
124               if (GC_size_map[lb] == 0) {
125                 if (!GC_is_initialized)  GC_init_inner();
126                 if (GC_size_map[lb] == 0) GC_extend_size_map(lb);
127                 return(GC_generic_malloc_inner(lb, k));
128               }
129 #           else
130               if (!GC_is_initialized) {
131                 GC_init_inner();
132                 return(GC_generic_malloc_inner(lb, k));
133               }
134 #           endif
135             if (kind -> ok_reclaim_list == 0) {
136                 if (!GC_alloc_reclaim_list(kind)) goto out;
137             }
138             op = GC_allocobj(lw, k);
139             if (op == 0) goto out;
140         }
141         /* Here everything is in a consistent state.    */
142         /* We assume the following assignment is        */
143         /* atomic.  If we get aborted                   */
144         /* after the assignment, we lose an object,     */
145         /* but that's benign.                           */
146         /* Volatile declarations may need to be added   */
147         /* to prevent the compiler from breaking things.*/
148         /* If we only execute the second of the         */
149         /* following assignments, we lose the free      */
150         /* list, but that should still be OK, at least  */
151         /* for garbage collected memory.                */
152         *opp = obj_link(op);
153         obj_link(op) = 0;
154     } else {
155         lw = ROUNDED_UP_WORDS(lb);
156         op = (ptr_t)GC_alloc_large_and_clear(lw, k, 0);
157     }
158     GC_words_allocd += lw;
159     
160 out:
161     return op;
162 }
163
164 /* Allocate a composite object of size n bytes.  The caller guarantees  */
165 /* that pointers past the first page are not relevant.  Caller holds    */
166 /* allocation lock.                                                     */
167 ptr_t GC_generic_malloc_inner_ignore_off_page(lb, k)
168 register size_t lb;
169 register int k;
170 {
171     register word lw;
172     ptr_t op;
173
174     if (lb <= HBLKSIZE)
175         return(GC_generic_malloc_inner((word)lb, k));
176     lw = ROUNDED_UP_WORDS(lb);
177     op = (ptr_t)GC_alloc_large_and_clear(lw, k, IGNORE_OFF_PAGE);
178     GC_words_allocd += lw;
179     return op;
180 }
181
182 ptr_t GC_generic_malloc(lb, k)
183 register word lb;
184 register int k;
185 {
186     ptr_t result;
187     DCL_LOCK_STATE;
188
189     if (GC_have_errors) GC_print_all_errors();
190     GC_INVOKE_FINALIZERS();
191     if (SMALL_OBJ(lb)) {
192         DISABLE_SIGNALS();
193         LOCK();
194         result = GC_generic_malloc_inner((word)lb, k);
195         UNLOCK();
196         ENABLE_SIGNALS();
197     } else {
198         word lw;
199         word n_blocks;
200         GC_bool init;
201         lw = ROUNDED_UP_WORDS(lb);
202         n_blocks = OBJ_SZ_TO_BLOCKS(lw);
203         init = GC_obj_kinds[k].ok_init;
204         DISABLE_SIGNALS();
205         LOCK();
206         result = (ptr_t)GC_alloc_large(lw, k, 0);
207         if (0 != result) {
208           if (GC_debugging_started) {
209             BZERO(result, n_blocks * HBLKSIZE);
210           } else {
211 #           ifdef THREADS
212               /* Clear any memory that might be used for GC descriptors */
213               /* before we release the lock.                          */
214                 ((word *)result)[0] = 0;
215                 ((word *)result)[1] = 0;
216                 ((word *)result)[lw-1] = 0;
217                 ((word *)result)[lw-2] = 0;
218 #           endif
219           }
220         }
221         GC_words_allocd += lw;
222         UNLOCK();
223         ENABLE_SIGNALS();
224         if (init && !GC_debugging_started && 0 != result) {
225             BZERO(result, n_blocks * HBLKSIZE);
226         }
227     }
228     if (0 == result) {
229         return((*GC_oom_fn)(lb));
230     } else {
231         return(result);
232     }
233 }   
234
235
236 #define GENERAL_MALLOC(lb,k) \
237     (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
238 /* We make the GC_clear_stack_call a tail call, hoping to get more of   */
239 /* the stack.                                                           */
240
241 /* Allocate lb bytes of atomic (pointerfree) data */
242 # ifdef __STDC__
243     GC_PTR GC_malloc_atomic(size_t lb)
244 # else
245     GC_PTR GC_malloc_atomic(lb)
246     size_t lb;
247 # endif
248 {
249 register ptr_t op;
250 register ptr_t * opp;
251 register word lw;
252 DCL_LOCK_STATE;
253
254     if( EXPECT(SMALL_OBJ(lb), 1) ) {
255 #       ifdef MERGE_SIZES
256           lw = GC_size_map[lb];
257 #       else
258           lw = ALIGNED_WORDS(lb);
259 #       endif
260         opp = &(GC_aobjfreelist[lw]);
261         FASTLOCK();
262         if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
263             FASTUNLOCK();
264             return(GENERAL_MALLOC((word)lb, PTRFREE));
265         }
266         /* See above comment on signals.        */
267         *opp = obj_link(op);
268         GC_words_allocd += lw;
269         FASTUNLOCK();
270         return((GC_PTR) op);
271    } else {
272        return(GENERAL_MALLOC((word)lb, PTRFREE));
273    }
274 }
275
276 /* Allocate lb bytes of composite (pointerful) data */
277 # ifdef __STDC__
278     GC_PTR GC_malloc(size_t lb)
279 # else
280     GC_PTR GC_malloc(lb)
281     size_t lb;
282 # endif
283 {
284 register ptr_t op;
285 register ptr_t *opp;
286 register word lw;
287 DCL_LOCK_STATE;
288
289     if( EXPECT(SMALL_OBJ(lb), 1) ) {
290 #       ifdef MERGE_SIZES
291           lw = GC_size_map[lb];
292 #       else
293           lw = ALIGNED_WORDS(lb);
294 #       endif
295         opp = &(GC_objfreelist[lw]);
296         FASTLOCK();
297         if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
298             FASTUNLOCK();
299             return(GENERAL_MALLOC((word)lb, NORMAL));
300         }
301         /* See above comment on signals.        */
302         GC_ASSERT(0 == obj_link(op)
303                   || (word)obj_link(op)
304                         <= (word)GC_greatest_plausible_heap_addr
305                      && (word)obj_link(op)
306                         >= (word)GC_least_plausible_heap_addr);
307         *opp = obj_link(op);
308         obj_link(op) = 0;
309         GC_words_allocd += lw;
310         FASTUNLOCK();
311         return((GC_PTR) op);
312    } else {
313        return(GENERAL_MALLOC((word)lb, NORMAL));
314    }
315 }
316
317 # ifdef REDIRECT_MALLOC
318
319 /* Avoid unnecessary nested procedure calls here, by #defining some     */
320 /* malloc replacements.  Otherwise we end up saving a                   */
321 /* meaningless return address in the object.  It also speeds things up, */
322 /* but it is admittedly quite ugly.                                     */
323 # ifdef GC_ADD_CALLER
324 #   define RA GC_RETURN_ADDR,
325 # else
326 #   define RA
327 # endif
328 # define GC_debug_malloc_replacement(lb) \
329         GC_debug_malloc(lb, RA "unknown", 0)
330
331 # ifdef __STDC__
332     GC_PTR malloc(size_t lb)
333 # else
334     GC_PTR malloc(lb)
335     size_t lb;
336 # endif
337   {
338     /* It might help to manually inline the GC_malloc call here.        */
339     /* But any decent compiler should reduce the extra procedure call   */
340     /* to at most a jump instruction in this case.                      */
341 #   if defined(I386) && defined(GC_SOLARIS_THREADS)
342       /*
343        * Thread initialisation can call malloc before
344        * we're ready for it.
345        * It's not clear that this is enough to help matters.
346        * The thread implementation may well call malloc at other
347        * inopportune times.
348        */
349       if (!GC_is_initialized) return sbrk(lb);
350 #   endif /* I386 && GC_SOLARIS_THREADS */
351     return((GC_PTR)REDIRECT_MALLOC(lb));
352   }
353
354 # ifdef __STDC__
355     GC_PTR calloc(size_t n, size_t lb)
356 # else
357     GC_PTR calloc(n, lb)
358     size_t n, lb;
359 # endif
360   {
361     return((GC_PTR)REDIRECT_MALLOC(n*lb));
362   }
363
364 #ifndef strdup
365 # include <string.h>
366 # ifdef __STDC__
367     char *strdup(const char *s)
368 # else
369     char *strdup(s)
370     char *s;
371 # endif
372   {
373     size_t len = strlen(s) + 1;
374     char * result = ((char *)REDIRECT_MALLOC(len+1));
375     BCOPY(s, result, len+1);
376     return result;
377   }
378 #endif /* !defined(strdup) */
379  /* If strdup is macro defined, we assume that it actually calls malloc, */
380  /* and thus the right thing will happen even without overriding it.     */
381  /* This seems to be true on most Linux systems.                         */
382
383 #undef GC_debug_malloc_replacement
384
385 # endif /* REDIRECT_MALLOC */
386
387 /* Explicitly deallocate an object p.                           */
388 # ifdef __STDC__
389     void GC_free(GC_PTR p)
390 # else
391     void GC_free(p)
392     GC_PTR p;
393 # endif
394 {
395     register struct hblk *h;
396     register hdr *hhdr;
397     register signed_word sz;
398     register ptr_t * flh;
399     register int knd;
400     register struct obj_kind * ok;
401     DCL_LOCK_STATE;
402
403     if (p == 0) return;
404         /* Required by ANSI.  It's not my fault ...     */
405     h = HBLKPTR(p);
406     hhdr = HDR(h);
407     GC_ASSERT(GC_base(p) == p);
408 #   if defined(REDIRECT_MALLOC) && \
409         (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
410          || defined(__MINGW32__)) /* Should this be MSWIN32 in general? */
411         /* For Solaris, we have to redirect malloc calls during         */
412         /* initialization.  For the others, this seems to happen        */
413         /* implicitly.                                                  */
414         /* Don't try to deallocate that memory.                         */
415         if (0 == hhdr) return;
416 #   endif
417     knd = hhdr -> hb_obj_kind;
418     sz = hhdr -> hb_sz;
419     ok = &GC_obj_kinds[knd];
420     if (EXPECT((sz <= MAXOBJSZ), 1)) {
421 #       ifdef THREADS
422             DISABLE_SIGNALS();
423             LOCK();
424 #       endif
425         GC_mem_freed += sz;
426         /* A signal here can make GC_mem_freed and GC_non_gc_bytes      */
427         /* inconsistent.  We claim this is benign.                      */
428         if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
429                 /* Its unnecessary to clear the mark bit.  If the       */
430                 /* object is reallocated, it doesn't matter.  O.w. the  */
431                 /* collector will do it, since it's on a free list.     */
432         if (ok -> ok_init) {
433             BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
434         }
435         flh = &(ok -> ok_freelist[sz]);
436         obj_link(p) = *flh;
437         *flh = (ptr_t)p;
438 #       ifdef THREADS
439             UNLOCK();
440             ENABLE_SIGNALS();
441 #       endif
442     } else {
443         DISABLE_SIGNALS();
444         LOCK();
445         GC_mem_freed += sz;
446         if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
447         GC_freehblk(h);
448         UNLOCK();
449         ENABLE_SIGNALS();
450     }
451 }
452
453 /* Explicitly deallocate an object p when we already hold lock.         */
454 /* Only used for internally allocated objects, so we can take some      */
455 /* shortcuts.                                                           */
456 #ifdef THREADS
457 void GC_free_inner(GC_PTR p)
458 {
459     register struct hblk *h;
460     register hdr *hhdr;
461     register signed_word sz;
462     register ptr_t * flh;
463     register int knd;
464     register struct obj_kind * ok;
465     DCL_LOCK_STATE;
466
467     h = HBLKPTR(p);
468     hhdr = HDR(h);
469     knd = hhdr -> hb_obj_kind;
470     sz = hhdr -> hb_sz;
471     ok = &GC_obj_kinds[knd];
472     if (sz <= MAXOBJSZ) {
473         GC_mem_freed += sz;
474         if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
475         if (ok -> ok_init) {
476             BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
477         }
478         flh = &(ok -> ok_freelist[sz]);
479         obj_link(p) = *flh;
480         *flh = (ptr_t)p;
481     } else {
482         GC_mem_freed += sz;
483         if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
484         GC_freehblk(h);
485     }
486 }
487 #endif /* THREADS */
488
489 # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
490 #   define REDIRECT_FREE GC_free
491 # endif
492 # ifdef REDIRECT_FREE
493 #   ifdef __STDC__
494       void free(GC_PTR p)
495 #   else
496       void free(p)
497       GC_PTR p;
498 #   endif
499   {
500 #   ifndef IGNORE_FREE
501       REDIRECT_FREE(p);
502 #   endif
503   }
504 # endif  /* REDIRECT_MALLOC */