2 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
3 * opyright (c) 1999-2000 by Hewlett-Packard Company. All rights reserved.
5 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
6 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
8 * Permission is hereby granted to use or copy this program
9 * for any purpose, provided the above notices are retained on all copies.
10 * Permission to modify the code and to distribute modified code is granted,
11 * provided the above notices are retained, and a notice that the code was
12 * modified is included with the above copyright notice.
18 * Some simple primitives for allocation with explicit type information.
19 * Simple objects are allocated such that they contain a GC_descr at the
20 * end (in the last allocated word). This descriptor may be a procedure
21 * which then examines an extended descriptor passed as its environment.
23 * Arrays are treated as simple objects if they have sufficiently simple
24 * structure. Otherwise they are allocated from an array kind that supplies
25 * a special mark procedure. These arrays contain a pointer to a
26 * complex_descriptor as their last word.
27 * This is done because the environment field is too small, and the collector
28 * must trace the complex_descriptor.
30 * Note that descriptors inside objects may appear cleared, if we encounter a
31 * false refrence to an object on a free list. In the GC_descr case, this
32 * is OK, since a 0 descriptor corresponds to examining no fields.
33 * In the complex_descriptor case, we explicitly check for that case.
35 * MAJOR PARTS OF THIS CODE HAVE NOT BEEN TESTED AT ALL and are not testable,
36 * since they are not accessible through the current interface.
39 #include "private/gc_pmark.h"
42 # define TYPD_EXTRA_BYTES (sizeof(word) - EXTRA_BYTES)
44 GC_bool GC_explicit_typing_initialized
= FALSE
;
46 int GC_explicit_kind
; /* Object kind for objects with indirect */
47 /* (possibly extended) descriptors. */
49 int GC_array_kind
; /* Object kind for objects with complex */
50 /* descriptors and GC_array_mark_proc. */
52 /* Extended descriptors. GC_typed_mark_proc understands these. */
53 /* These are used for simple objects that are larger than what */
54 /* can be described by a BITMAP_BITS sized bitmap. */
56 word ed_bitmap
; /* lsb corresponds to first word. */
57 GC_bool ed_continued
; /* next entry is continuation. */
60 /* Array descriptors. GC_array_mark_proc understands these. */
61 /* We may eventually need to add provisions for headers and */
62 /* trailers. Hence we provide for tree structured descriptors, */
63 /* though we don't really use them currently. */
64 typedef union ComplexDescriptor
{
65 struct LeafDescriptor
{ /* Describes simple array */
68 word ld_size
; /* bytes per element */
69 /* multiple of ALIGNMENT */
70 word ld_nelements
; /* Number of elements. */
71 GC_descr ld_descriptor
; /* A simple length, bitmap, */
72 /* or procedure descriptor. */
74 struct ComplexArrayDescriptor
{
78 union ComplexDescriptor
* ad_element_descr
;
80 struct SequenceDescriptor
{
82 # define SEQUENCE_TAG 3
83 union ComplexDescriptor
* sd_first
;
84 union ComplexDescriptor
* sd_second
;
89 ext_descr
* GC_ext_descriptors
; /* Points to array of extended */
92 word GC_ed_size
= 0; /* Current size of above arrays. */
93 # define ED_INITIAL_SIZE 100;
95 word GC_avail_descr
= 0; /* Next available slot. */
97 int GC_typed_mark_proc_index
; /* Indices of my mark */
98 int GC_array_mark_proc_index
; /* procedures. */
100 /* Add a multiword bitmap to GC_ext_descriptors arrays. Return */
101 /* starting index. */
102 /* Returns -1 on failure. */
103 /* Caller does not hold allocation lock. */
104 signed_word
GC_add_ext_descriptor(bm
, nbits
)
108 register size_t nwords
= divWORDSZ(nbits
+ WORDSZ
-1);
109 register signed_word result
;
111 register word last_part
;
112 register int extra_bits
;
117 while (GC_avail_descr
+ nwords
>= GC_ed_size
) {
120 word ed_size
= GC_ed_size
;
125 new_size
= ED_INITIAL_SIZE
;
127 new_size
= 2 * ed_size
;
128 if (new_size
> MAX_ENV
) return(-1);
130 new = (ext_descr
*) GC_malloc_atomic(new_size
* sizeof(ext_descr
));
131 if (new == 0) return(-1);
134 if (ed_size
== GC_ed_size
) {
135 if (GC_avail_descr
!= 0) {
136 BCOPY(GC_ext_descriptors
, new,
137 GC_avail_descr
* sizeof(ext_descr
));
139 GC_ed_size
= new_size
;
140 GC_ext_descriptors
= new;
141 } /* else another thread already resized it in the meantime */
143 result
= GC_avail_descr
;
144 for (i
= 0; i
< nwords
-1; i
++) {
145 GC_ext_descriptors
[result
+ i
].ed_bitmap
= bm
[i
];
146 GC_ext_descriptors
[result
+ i
].ed_continued
= TRUE
;
149 /* Clear irrelevant bits. */
150 extra_bits
= nwords
* WORDSZ
- nbits
;
151 last_part
<<= extra_bits
;
152 last_part
>>= extra_bits
;
153 GC_ext_descriptors
[result
+ i
].ed_bitmap
= last_part
;
154 GC_ext_descriptors
[result
+ i
].ed_continued
= FALSE
;
155 GC_avail_descr
+= nwords
;
161 /* Table of bitmap descriptors for n word long all pointer objects. */
162 GC_descr GC_bm_table
[WORDSZ
/2];
164 /* Return a descriptor for the concatenation of 2 nwords long objects, */
165 /* each of which is described by descriptor. */
166 /* The result is known to be short enough to fit into a bitmap */
168 /* Descriptor is a GC_DS_LENGTH or GC_DS_BITMAP descriptor. */
169 GC_descr
GC_double_descr(descriptor
, nwords
)
170 register GC_descr descriptor
;
171 register word nwords
;
173 if ((descriptor
& GC_DS_TAGS
) == GC_DS_LENGTH
) {
174 descriptor
= GC_bm_table
[BYTES_TO_WORDS((word
)descriptor
)];
176 descriptor
|= (descriptor
& ~GC_DS_TAGS
) >> nwords
;
180 complex_descriptor
* GC_make_sequence_descriptor();
182 /* Build a descriptor for an array with nelements elements, */
183 /* each of which can be described by a simple descriptor. */
184 /* We try to optimize some common cases. */
185 /* If the result is COMPLEX, then a complex_descr* is returned */
187 /* If the result is LEAF, then we built a LeafDescriptor in */
188 /* the structure pointed to by leaf. */
189 /* The tag in the leaf structure is not set. */
190 /* If the result is SIMPLE, then a GC_descr */
191 /* is returned in *simple_d. */
192 /* If the result is NO_MEM, then */
193 /* we failed to allocate the descriptor. */
194 /* The implementation knows that GC_DS_LENGTH is 0. */
195 /* *leaf, *complex_d, and *simple_d may be used as temporaries */
196 /* during the construction. */
201 int GC_make_array_descriptor(nelements
, size
, descriptor
,
202 simple_d
, complex_d
, leaf
)
207 complex_descriptor
**complex_d
;
208 struct LeafDescriptor
* leaf
;
210 # define OPT_THRESHOLD 50
211 /* For larger arrays, we try to combine descriptors of adjacent */
212 /* descriptors to speed up marking, and to reduce the amount */
213 /* of space needed on the mark stack. */
214 if ((descriptor
& GC_DS_TAGS
) == GC_DS_LENGTH
) {
215 if ((word
)descriptor
== size
) {
216 *simple_d
= nelements
* descriptor
;
218 } else if ((word
)descriptor
== 0) {
219 *simple_d
= (GC_descr
)0;
223 if (nelements
<= OPT_THRESHOLD
) {
224 if (nelements
<= 1) {
225 if (nelements
== 1) {
226 *simple_d
= descriptor
;
229 *simple_d
= (GC_descr
)0;
233 } else if (size
<= BITMAP_BITS
/2
234 && (descriptor
& GC_DS_TAGS
) != GC_DS_PROC
235 && (size
& (sizeof(word
)-1)) == 0) {
237 GC_make_array_descriptor(nelements
/2, 2*size
,
238 GC_double_descr(descriptor
,
239 BYTES_TO_WORDS(size
)),
240 simple_d
, complex_d
, leaf
);
241 if ((nelements
& 1) == 0) {
244 struct LeafDescriptor
* one_element
=
245 (struct LeafDescriptor
*)
246 GC_malloc_atomic(sizeof(struct LeafDescriptor
));
248 if (result
== NO_MEM
|| one_element
== 0) return(NO_MEM
);
249 one_element
-> ld_tag
= LEAF_TAG
;
250 one_element
-> ld_size
= size
;
251 one_element
-> ld_nelements
= 1;
252 one_element
-> ld_descriptor
= descriptor
;
256 struct LeafDescriptor
* beginning
=
257 (struct LeafDescriptor
*)
258 GC_malloc_atomic(sizeof(struct LeafDescriptor
));
259 if (beginning
== 0) return(NO_MEM
);
260 beginning
-> ld_tag
= LEAF_TAG
;
261 beginning
-> ld_size
= size
;
262 beginning
-> ld_nelements
= 1;
263 beginning
-> ld_descriptor
= *simple_d
;
264 *complex_d
= GC_make_sequence_descriptor(
265 (complex_descriptor
*)beginning
,
266 (complex_descriptor
*)one_element
);
271 struct LeafDescriptor
* beginning
=
272 (struct LeafDescriptor
*)
273 GC_malloc_atomic(sizeof(struct LeafDescriptor
));
274 if (beginning
== 0) return(NO_MEM
);
275 beginning
-> ld_tag
= LEAF_TAG
;
276 beginning
-> ld_size
= leaf
-> ld_size
;
277 beginning
-> ld_nelements
= leaf
-> ld_nelements
;
278 beginning
-> ld_descriptor
= leaf
-> ld_descriptor
;
279 *complex_d
= GC_make_sequence_descriptor(
280 (complex_descriptor
*)beginning
,
281 (complex_descriptor
*)one_element
);
285 *complex_d
= GC_make_sequence_descriptor(
287 (complex_descriptor
*)one_element
);
294 leaf
-> ld_size
= size
;
295 leaf
-> ld_nelements
= nelements
;
296 leaf
-> ld_descriptor
= descriptor
;
301 complex_descriptor
* GC_make_sequence_descriptor(first
, second
)
302 complex_descriptor
* first
;
303 complex_descriptor
* second
;
305 struct SequenceDescriptor
* result
=
306 (struct SequenceDescriptor
*)
307 GC_malloc(sizeof(struct SequenceDescriptor
));
308 /* Can't result in overly conservative marking, since tags are */
309 /* very small integers. Probably faster than maintaining type */
312 result
-> sd_tag
= SEQUENCE_TAG
;
313 result
-> sd_first
= first
;
314 result
-> sd_second
= second
;
316 return((complex_descriptor
*)result
);
320 complex_descriptor
* GC_make_complex_array_descriptor(nelements
, descr
)
322 complex_descriptor
* descr
;
324 struct ComplexArrayDescriptor
* result
=
325 (struct ComplexArrayDescriptor
*)
326 GC_malloc(sizeof(struct ComplexArrayDescriptor
));
329 result
-> ad_tag
= ARRAY_TAG
;
330 result
-> ad_nelements
= nelements
;
331 result
-> ad_element_descr
= descr
;
333 return((complex_descriptor
*)result
);
337 ptr_t
* GC_eobjfreelist
;
339 ptr_t
* GC_arobjfreelist
;
341 mse
* GC_typed_mark_proc
GC_PROTO((register word
* addr
,
342 register mse
* mark_stack_ptr
,
343 mse
* mark_stack_limit
,
346 mse
* GC_array_mark_proc
GC_PROTO((register word
* addr
,
347 register mse
* mark_stack_ptr
,
348 mse
* mark_stack_limit
,
351 GC_descr GC_generic_array_descr
;
353 /* Caller does not hold allocation lock. */
354 void GC_init_explicit_typing()
361 if (sizeof(struct LeafDescriptor
) % sizeof(word
) != 0)
362 ABORT("Bad leaf descriptor size");
366 if (GC_explicit_typing_initialized
) {
371 GC_explicit_typing_initialized
= TRUE
;
372 /* Set up object kind with simple indirect descriptor. */
373 GC_eobjfreelist
= (ptr_t
*)
374 GC_INTERNAL_MALLOC((MAXOBJSZ
+1)*sizeof(ptr_t
), PTRFREE
);
375 if (GC_eobjfreelist
== 0) ABORT("Couldn't allocate GC_eobjfreelist");
376 BZERO(GC_eobjfreelist
, (MAXOBJSZ
+1)*sizeof(ptr_t
));
377 GC_explicit_kind
= GC_n_kinds
++;
378 GC_obj_kinds
[GC_explicit_kind
].ok_freelist
= GC_eobjfreelist
;
379 GC_obj_kinds
[GC_explicit_kind
].ok_reclaim_list
= 0;
380 GC_obj_kinds
[GC_explicit_kind
].ok_descriptor
=
381 (((word
)WORDS_TO_BYTES(-1)) | GC_DS_PER_OBJECT
);
382 GC_obj_kinds
[GC_explicit_kind
].ok_relocate_descr
= TRUE
;
383 GC_obj_kinds
[GC_explicit_kind
].ok_init
= TRUE
;
384 /* Descriptors are in the last word of the object. */
385 GC_typed_mark_proc_index
= GC_n_mark_procs
;
386 GC_mark_procs
[GC_typed_mark_proc_index
] = GC_typed_mark_proc
;
388 /* Moving this up breaks DEC AXP compiler. */
389 /* Set up object kind with array descriptor. */
390 GC_arobjfreelist
= (ptr_t
*)
391 GC_INTERNAL_MALLOC((MAXOBJSZ
+1)*sizeof(ptr_t
), PTRFREE
);
392 if (GC_arobjfreelist
== 0) ABORT("Couldn't allocate GC_arobjfreelist");
393 BZERO(GC_arobjfreelist
, (MAXOBJSZ
+1)*sizeof(ptr_t
));
394 if (GC_n_mark_procs
>= MAX_MARK_PROCS
)
395 ABORT("No slot for array mark proc");
396 GC_array_mark_proc_index
= GC_n_mark_procs
++;
397 if (GC_n_kinds
>= MAXOBJKINDS
)
398 ABORT("No kind available for array objects");
399 GC_array_kind
= GC_n_kinds
++;
400 GC_obj_kinds
[GC_array_kind
].ok_freelist
= GC_arobjfreelist
;
401 GC_obj_kinds
[GC_array_kind
].ok_reclaim_list
= 0;
402 GC_obj_kinds
[GC_array_kind
].ok_descriptor
=
403 GC_MAKE_PROC(GC_array_mark_proc_index
, 0);;
404 GC_obj_kinds
[GC_array_kind
].ok_relocate_descr
= FALSE
;
405 GC_obj_kinds
[GC_array_kind
].ok_init
= TRUE
;
406 /* Descriptors are in the last word of the object. */
407 GC_mark_procs
[GC_array_mark_proc_index
] = GC_array_mark_proc
;
408 for (i
= 0; i
< WORDSZ
/2; i
++) {
409 GC_descr d
= (((word
)(-1)) >> (WORDSZ
- i
)) << (WORDSZ
- i
);
413 GC_generic_array_descr
= GC_MAKE_PROC(GC_array_mark_proc_index
, 0);
418 # if defined(__STDC__) || defined(__cplusplus)
419 mse
* GC_typed_mark_proc(register word
* addr
,
420 register mse
* mark_stack_ptr
,
421 mse
* mark_stack_limit
,
424 mse
* GC_typed_mark_proc(addr
, mark_stack_ptr
, mark_stack_limit
, env
)
425 register word
* addr
;
426 register mse
* mark_stack_ptr
;
427 mse
* mark_stack_limit
;
431 register word bm
= GC_ext_descriptors
[env
].ed_bitmap
;
432 register word
* current_p
= addr
;
433 register word current
;
434 register ptr_t greatest_ha
= GC_greatest_plausible_heap_addr
;
435 register ptr_t least_ha
= GC_least_plausible_heap_addr
;
437 for (; bm
!= 0; bm
>>= 1, current_p
++) {
439 current
= *current_p
;
440 if ((ptr_t
)current
>= least_ha
&& (ptr_t
)current
<= greatest_ha
) {
441 PUSH_CONTENTS((ptr_t
)current
, mark_stack_ptr
,
442 mark_stack_limit
, current_p
, exit1
);
446 if (GC_ext_descriptors
[env
].ed_continued
) {
447 /* Push an entry with the rest of the descriptor back onto the */
448 /* stack. Thus we never do too much work at once. Note that */
449 /* we also can't overflow the mark stack unless we actually */
450 /* mark something. */
452 if (mark_stack_ptr
>= mark_stack_limit
) {
453 mark_stack_ptr
= GC_signal_mark_stack_overflow(mark_stack_ptr
);
455 mark_stack_ptr
-> mse_start
= addr
+ WORDSZ
;
456 mark_stack_ptr
-> mse_descr
=
457 GC_MAKE_PROC(GC_typed_mark_proc_index
, env
+1);
459 return(mark_stack_ptr
);
462 /* Return the size of the object described by d. It would be faster to */
463 /* store this directly, or to compute it as part of */
464 /* GC_push_complex_descriptor, but hopefully it doesn't matter. */
465 word
GC_descr_obj_size(d
)
466 register complex_descriptor
*d
;
470 return(d
-> ld
.ld_nelements
* d
-> ld
.ld_size
);
472 return(d
-> ad
.ad_nelements
473 * GC_descr_obj_size(d
-> ad
.ad_element_descr
));
475 return(GC_descr_obj_size(d
-> sd
.sd_first
)
476 + GC_descr_obj_size(d
-> sd
.sd_second
));
478 ABORT("Bad complex descriptor");
479 /*NOTREACHED*/ return 0; /*NOTREACHED*/
483 /* Push descriptors for the object at addr with complex descriptor d */
484 /* onto the mark stack. Return 0 if the mark stack overflowed. */
485 mse
* GC_push_complex_descriptor(addr
, d
, msp
, msl
)
487 register complex_descriptor
*d
;
491 register ptr_t current
= (ptr_t
) addr
;
492 register word nelements
;
499 register GC_descr descr
= d
-> ld
.ld_descriptor
;
501 nelements
= d
-> ld
.ld_nelements
;
502 if (msl
- msp
<= (ptrdiff_t)nelements
) return(0);
503 sz
= d
-> ld
.ld_size
;
504 for (i
= 0; i
< nelements
; i
++) {
506 msp
-> mse_start
= (word
*)current
;
507 msp
-> mse_descr
= descr
;
514 register complex_descriptor
*descr
= d
-> ad
.ad_element_descr
;
516 nelements
= d
-> ad
.ad_nelements
;
517 sz
= GC_descr_obj_size(descr
);
518 for (i
= 0; i
< nelements
; i
++) {
519 msp
= GC_push_complex_descriptor((word
*)current
, descr
,
521 if (msp
== 0) return(0);
528 sz
= GC_descr_obj_size(d
-> sd
.sd_first
);
529 msp
= GC_push_complex_descriptor((word
*)current
, d
-> sd
.sd_first
,
531 if (msp
== 0) return(0);
533 msp
= GC_push_complex_descriptor((word
*)current
, d
-> sd
.sd_second
,
538 ABORT("Bad complex descriptor");
539 /*NOTREACHED*/ return 0; /*NOTREACHED*/
544 # if defined(__STDC__) || defined(__cplusplus)
545 mse
* GC_array_mark_proc(register word
* addr
,
546 register mse
* mark_stack_ptr
,
547 mse
* mark_stack_limit
,
550 mse
* GC_array_mark_proc(addr
, mark_stack_ptr
, mark_stack_limit
, env
)
551 register word
* addr
;
552 register mse
* mark_stack_ptr
;
553 mse
* mark_stack_limit
;
557 register hdr
* hhdr
= HDR(addr
);
558 register word sz
= hhdr
-> hb_sz
;
559 register complex_descriptor
* descr
= (complex_descriptor
*)(addr
[sz
-1]);
560 mse
* orig_mark_stack_ptr
= mark_stack_ptr
;
561 mse
* new_mark_stack_ptr
;
564 /* Found a reference to a free list entry. Ignore it. */
565 return(orig_mark_stack_ptr
);
567 /* In use counts were already updated when array descriptor was */
568 /* pushed. Here we only replace it by subobject descriptors, so */
569 /* no update is necessary. */
570 new_mark_stack_ptr
= GC_push_complex_descriptor(addr
, descr
,
573 if (new_mark_stack_ptr
== 0) {
574 /* Doesn't fit. Conservatively push the whole array as a unit */
575 /* and request a mark stack expansion. */
576 /* This cannot cause a mark stack overflow, since it replaces */
577 /* the original array entry. */
578 GC_mark_stack_too_small
= TRUE
;
579 new_mark_stack_ptr
= orig_mark_stack_ptr
+ 1;
580 new_mark_stack_ptr
-> mse_start
= addr
;
581 new_mark_stack_ptr
-> mse_descr
= WORDS_TO_BYTES(sz
) | GC_DS_LENGTH
;
583 /* Push descriptor itself */
584 new_mark_stack_ptr
++;
585 new_mark_stack_ptr
-> mse_start
= addr
+ sz
- 1;
586 new_mark_stack_ptr
-> mse_descr
= sizeof(word
) | GC_DS_LENGTH
;
588 return(new_mark_stack_ptr
);
591 #if defined(__STDC__) || defined(__cplusplus)
592 GC_descr
GC_make_descriptor(GC_bitmap bm
, size_t len
)
594 GC_descr
GC_make_descriptor(bm
, len
)
599 register signed_word last_set_bit
= len
- 1;
600 register word result
;
602 # define HIGH_BIT (((word)1) << (WORDSZ - 1))
604 if (!GC_explicit_typing_initialized
) GC_init_explicit_typing();
605 while (last_set_bit
>= 0 && !GC_get_bit(bm
, last_set_bit
)) last_set_bit
--;
606 if (last_set_bit
< 0) return(0 /* no pointers */);
607 # if ALIGNMENT == CPP_WORDSZ/8
609 register GC_bool all_bits_set
= TRUE
;
610 for (i
= 0; i
< last_set_bit
; i
++) {
611 if (!GC_get_bit(bm
, i
)) {
612 all_bits_set
= FALSE
;
617 /* An initial section contains all pointers. Use length descriptor. */
618 return(WORDS_TO_BYTES(last_set_bit
+1) | GC_DS_LENGTH
);
622 if (last_set_bit
< BITMAP_BITS
) {
623 /* Hopefully the common case. */
624 /* Build bitmap descriptor (with bits reversed) */
626 for (i
= last_set_bit
- 1; i
>= 0; i
--) {
628 if (GC_get_bit(bm
, i
)) result
|= HIGH_BIT
;
630 result
|= GC_DS_BITMAP
;
635 index
= GC_add_ext_descriptor(bm
, (word
)last_set_bit
+1);
636 if (index
== -1) return(WORDS_TO_BYTES(last_set_bit
+1) | GC_DS_LENGTH
);
637 /* Out of memory: use conservative */
639 result
= GC_MAKE_PROC(GC_typed_mark_proc_index
, (word
)index
);
644 ptr_t
GC_clear_stack();
646 #define GENERAL_MALLOC(lb,k) \
647 (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
649 #define GENERAL_MALLOC_IOP(lb,k) \
650 (GC_PTR)GC_clear_stack(GC_generic_malloc_ignore_off_page(lb, k))
652 #if defined(__STDC__) || defined(__cplusplus)
653 void * GC_malloc_explicitly_typed(size_t lb
, GC_descr d
)
655 char * GC_malloc_explicitly_typed(lb
, d
)
661 register ptr_t
* opp
;
665 lb
+= TYPD_EXTRA_BYTES
;
666 if( SMALL_OBJ(lb
) ) {
668 lw
= GC_size_map
[lb
];
670 lw
= ALIGNED_WORDS(lb
);
672 opp
= &(GC_eobjfreelist
[lw
]);
674 if( !FASTLOCK_SUCCEEDED() || (op
= *opp
) == 0 ) {
676 op
= (ptr_t
)GENERAL_MALLOC((word
)lb
, GC_explicit_kind
);
677 if (0 == op
) return(0);
679 lw
= GC_size_map
[lb
]; /* May have been uninitialized. */
684 GC_words_allocd
+= lw
;
688 op
= (ptr_t
)GENERAL_MALLOC((word
)lb
, GC_explicit_kind
);
690 lw
= BYTES_TO_WORDS(GC_size(op
));
693 ((word
*)op
)[lw
- 1] = d
;
697 #if defined(__STDC__) || defined(__cplusplus)
698 void * GC_malloc_explicitly_typed_ignore_off_page(size_t lb
, GC_descr d
)
700 char * GC_malloc_explicitly_typed_ignore_off_page(lb
, d
)
706 register ptr_t
* opp
;
710 lb
+= TYPD_EXTRA_BYTES
;
711 if( SMALL_OBJ(lb
) ) {
713 lw
= GC_size_map
[lb
];
715 lw
= ALIGNED_WORDS(lb
);
717 opp
= &(GC_eobjfreelist
[lw
]);
719 if( !FASTLOCK_SUCCEEDED() || (op
= *opp
) == 0 ) {
721 op
= (ptr_t
)GENERAL_MALLOC_IOP(lb
, GC_explicit_kind
);
723 lw
= GC_size_map
[lb
]; /* May have been uninitialized. */
728 GC_words_allocd
+= lw
;
732 op
= (ptr_t
)GENERAL_MALLOC_IOP(lb
, GC_explicit_kind
);
734 lw
= BYTES_TO_WORDS(GC_size(op
));
737 ((word
*)op
)[lw
- 1] = d
;
741 #if defined(__STDC__) || defined(__cplusplus)
742 void * GC_calloc_explicitly_typed(size_t n
,
746 char * GC_calloc_explicitly_typed(n
, lb
, d
)
753 register ptr_t
* opp
;
755 GC_descr simple_descr
;
756 complex_descriptor
*complex_descr
;
757 register int descr_type
;
758 struct LeafDescriptor leaf
;
761 descr_type
= GC_make_array_descriptor((word
)n
, (word
)lb
, d
,
762 &simple_descr
, &complex_descr
, &leaf
);
764 case NO_MEM
: return(0);
765 case SIMPLE
: return(GC_malloc_explicitly_typed(n
*lb
, simple_descr
));
768 lb
+= sizeof(struct LeafDescriptor
) + TYPD_EXTRA_BYTES
;
772 lb
+= TYPD_EXTRA_BYTES
;
775 if( SMALL_OBJ(lb
) ) {
777 lw
= GC_size_map
[lb
];
779 lw
= ALIGNED_WORDS(lb
);
781 opp
= &(GC_arobjfreelist
[lw
]);
783 if( !FASTLOCK_SUCCEEDED() || (op
= *opp
) == 0 ) {
785 op
= (ptr_t
)GENERAL_MALLOC((word
)lb
, GC_array_kind
);
786 if (0 == op
) return(0);
788 lw
= GC_size_map
[lb
]; /* May have been uninitialized. */
793 GC_words_allocd
+= lw
;
797 op
= (ptr_t
)GENERAL_MALLOC((word
)lb
, GC_array_kind
);
798 if (0 == op
) return(0);
799 lw
= BYTES_TO_WORDS(GC_size(op
));
801 if (descr_type
== LEAF
) {
802 /* Set up the descriptor inside the object itself. */
803 VOLATILE
struct LeafDescriptor
* lp
=
804 (struct LeafDescriptor
*)
806 + lw
- (BYTES_TO_WORDS(sizeof(struct LeafDescriptor
)) + 1));
808 lp
-> ld_tag
= LEAF_TAG
;
809 lp
-> ld_size
= leaf
.ld_size
;
810 lp
-> ld_nelements
= leaf
.ld_nelements
;
811 lp
-> ld_descriptor
= leaf
.ld_descriptor
;
812 ((VOLATILE word
*)op
)[lw
- 1] = (word
)lp
;
814 extern unsigned GC_finalization_failures
;
815 unsigned ff
= GC_finalization_failures
;
817 ((word
*)op
)[lw
- 1] = (word
)complex_descr
;
818 /* Make sure the descriptor is cleared once there is any danger */
819 /* it may have been collected. */
821 GC_general_register_disappearing_link((GC_PTR
*)
824 if (ff
!= GC_finalization_failures
) {
825 /* Couldn't register it due to lack of memory. Punt. */
826 /* This will probably fail too, but gives the recovery code */
828 return(GC_malloc(n
*lb
));