LCOV - code coverage report
Current view: top level - mm/boehm-gc - typd_mlc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 301 0.0 %
Date: 2015-06-10 18:10:59 Functions: 0 14 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
       3             :  * opyright (c) 1999-2000 by Hewlett-Packard Company.  All rights reserved.
       4             :  *
       5             :  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
       6             :  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
       7             :  *
       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.
      13             :  *
      14             :  */
      15             : 
      16             : #include "private/gc_pmark.h"
      17             : 
      18             : /*
      19             :  * Some simple primitives for allocation with explicit type information.
      20             :  * Simple objects are allocated such that they contain a GC_descr at the
      21             :  * end (in the last allocated word).  This descriptor may be a procedure
      22             :  * which then examines an extended descriptor passed as its environment.
      23             :  *
      24             :  * Arrays are treated as simple objects if they have sufficiently simple
      25             :  * structure.  Otherwise they are allocated from an array kind that supplies
      26             :  * a special mark procedure.  These arrays contain a pointer to a
      27             :  * complex_descriptor as their last word.
      28             :  * This is done because the environment field is too small, and the collector
      29             :  * must trace the complex_descriptor.
      30             :  *
      31             :  * Note that descriptors inside objects may appear cleared, if we encounter a
      32             :  * false reference to an object on a free list.  In the GC_descr case, this
      33             :  * is OK, since a 0 descriptor corresponds to examining no fields.
      34             :  * In the complex_descriptor case, we explicitly check for that case.
      35             :  *
      36             :  * MAJOR PARTS OF THIS CODE HAVE NOT BEEN TESTED AT ALL and are not testable,
      37             :  * since they are not accessible through the current interface.
      38             :  */
      39             : 
      40             : #include "gc_typed.h"
      41             : 
      42             : #define TYPD_EXTRA_BYTES (sizeof(word) - EXTRA_BYTES)
      43             : 
      44             : STATIC GC_bool GC_explicit_typing_initialized = FALSE;
      45             : 
      46             : STATIC int GC_explicit_kind = 0;
      47             :                         /* Object kind for objects with indirect        */
      48             :                         /* (possibly extended) descriptors.             */
      49             : 
      50             : STATIC int GC_array_kind = 0;
      51             :                         /* Object kind for objects with complex         */
      52             :                         /* descriptors and GC_array_mark_proc.          */
      53             : 
      54             : /* Extended descriptors.  GC_typed_mark_proc understands these. */
      55             : /* These are used for simple objects that are larger than what  */
      56             : /* can be described by a BITMAP_BITS sized bitmap.              */
      57             : typedef struct {
      58             :         word ed_bitmap; /* lsb corresponds to first word.       */
      59             :         GC_bool ed_continued;   /* next entry is continuation.  */
      60             : } ext_descr;
      61             : 
      62             : /* Array descriptors.  GC_array_mark_proc understands these.    */
      63             : /* We may eventually need to add provisions for headers and     */
      64             : /* trailers.  Hence we provide for tree structured descriptors, */
      65             : /* though we don't really use them currently.                   */
      66             : typedef union ComplexDescriptor {
      67             :     struct LeafDescriptor {     /* Describes simple array       */
      68             :         word ld_tag;
      69             : #       define LEAF_TAG 1
      70             :         size_t ld_size;         /* bytes per element    */
      71             :                                 /* multiple of ALIGNMENT        */
      72             :         size_t ld_nelements;    /* Number of elements.  */
      73             :         GC_descr ld_descriptor; /* A simple length, bitmap,     */
      74             :                                 /* or procedure descriptor.     */
      75             :     } ld;
      76             :     struct ComplexArrayDescriptor {
      77             :         word ad_tag;
      78             : #       define ARRAY_TAG 2
      79             :         size_t ad_nelements;
      80             :         union ComplexDescriptor * ad_element_descr;
      81             :     } ad;
      82             :     struct SequenceDescriptor {
      83             :         word sd_tag;
      84             : #       define SEQUENCE_TAG 3
      85             :         union ComplexDescriptor * sd_first;
      86             :         union ComplexDescriptor * sd_second;
      87             :     } sd;
      88             : } complex_descriptor;
      89             : #define TAG ld.ld_tag
      90             : 
      91             : STATIC ext_descr * GC_ext_descriptors = NULL;
      92             :                                         /* Points to array of extended  */
      93             :                                         /* descriptors.                 */
      94             : 
      95             : STATIC size_t GC_ed_size = 0;   /* Current size of above arrays.        */
      96             : #define ED_INITIAL_SIZE 100
      97             : 
      98             : STATIC size_t GC_avail_descr = 0;       /* Next available slot.         */
      99             : 
     100             : STATIC int GC_typed_mark_proc_index = 0; /* Indices of my mark          */
     101             : STATIC int GC_array_mark_proc_index = 0; /* procedures.                 */
     102             : 
     103           0 : STATIC void GC_push_typed_structures_proc(void)
     104             : {
     105           0 :   GC_push_all((ptr_t)&GC_ext_descriptors,
     106             :               (ptr_t)&GC_ext_descriptors + sizeof(word));
     107           0 : }
     108             : 
     109             : /* Add a multiword bitmap to GC_ext_descriptors arrays.  Return */
     110             : /* starting index.                                              */
     111             : /* Returns -1 on failure.                                       */
     112             : /* Caller does not hold allocation lock.                        */
     113           0 : STATIC signed_word GC_add_ext_descriptor(GC_bitmap bm, word nbits)
     114             : {
     115           0 :     size_t nwords = divWORDSZ(nbits + WORDSZ-1);
     116             :     signed_word result;
     117             :     size_t i;
     118             :     word last_part;
     119             :     size_t extra_bits;
     120             :     DCL_LOCK_STATE;
     121             : 
     122           0 :     LOCK();
     123           0 :     while (GC_avail_descr + nwords >= GC_ed_size) {
     124             :         ext_descr * new;
     125             :         size_t new_size;
     126           0 :         word ed_size = GC_ed_size;
     127             : 
     128           0 :         if (ed_size == 0) {
     129           0 :             GC_push_typed_structures = GC_push_typed_structures_proc;
     130           0 :             UNLOCK();
     131           0 :             new_size = ED_INITIAL_SIZE;
     132             :         } else {
     133           0 :             UNLOCK();
     134           0 :             new_size = 2 * ed_size;
     135           0 :             if (new_size > MAX_ENV) return(-1);
     136             :         }
     137           0 :         new = (ext_descr *) GC_malloc_atomic(new_size * sizeof(ext_descr));
     138           0 :         if (new == 0) return(-1);
     139           0 :         LOCK();
     140           0 :         if (ed_size == GC_ed_size) {
     141           0 :             if (GC_avail_descr != 0) {
     142           0 :                 BCOPY(GC_ext_descriptors, new,
     143             :                       GC_avail_descr * sizeof(ext_descr));
     144             :             }
     145           0 :             GC_ed_size = new_size;
     146           0 :             GC_ext_descriptors = new;
     147             :         }  /* else another thread already resized it in the meantime */
     148             :     }
     149           0 :     result = GC_avail_descr;
     150           0 :     for (i = 0; i < nwords-1; i++) {
     151           0 :         GC_ext_descriptors[result + i].ed_bitmap = bm[i];
     152           0 :         GC_ext_descriptors[result + i].ed_continued = TRUE;
     153             :     }
     154           0 :     last_part = bm[i];
     155             :     /* Clear irrelevant bits. */
     156           0 :     extra_bits = nwords * WORDSZ - nbits;
     157           0 :     last_part <<= extra_bits;
     158           0 :     last_part >>= extra_bits;
     159           0 :     GC_ext_descriptors[result + i].ed_bitmap = last_part;
     160           0 :     GC_ext_descriptors[result + i].ed_continued = FALSE;
     161           0 :     GC_avail_descr += nwords;
     162           0 :     UNLOCK();
     163           0 :     return(result);
     164             : }
     165             : 
     166             : /* Table of bitmap descriptors for n word long all pointer objects.     */
     167             : STATIC GC_descr GC_bm_table[WORDSZ/2];
     168             : 
     169             : /* Return a descriptor for the concatenation of 2 nwords long objects,  */
     170             : /* each of which is described by descriptor.                            */
     171             : /* The result is known to be short enough to fit into a bitmap          */
     172             : /* descriptor.                                                          */
     173             : /* Descriptor is a GC_DS_LENGTH or GC_DS_BITMAP descriptor.             */
     174           0 : STATIC GC_descr GC_double_descr(GC_descr descriptor, word nwords)
     175             : {
     176           0 :     if ((descriptor & GC_DS_TAGS) == GC_DS_LENGTH) {
     177           0 :         descriptor = GC_bm_table[BYTES_TO_WORDS((word)descriptor)];
     178             :     };
     179           0 :     descriptor |= (descriptor & ~GC_DS_TAGS) >> nwords;
     180           0 :     return(descriptor);
     181             : }
     182             : 
     183             : STATIC complex_descriptor *
     184             : GC_make_sequence_descriptor(complex_descriptor *first,
     185             :                             complex_descriptor *second);
     186             : 
     187             : /* Build a descriptor for an array with nelements elements,     */
     188             : /* each of which can be described by a simple descriptor.       */
     189             : /* We try to optimize some common cases.                        */
     190             : /* If the result is COMPLEX, then a complex_descr* is returned  */
     191             : /* in *complex_d.                                                       */
     192             : /* If the result is LEAF, then we built a LeafDescriptor in     */
     193             : /* the structure pointed to by leaf.                            */
     194             : /* The tag in the leaf structure is not set.                    */
     195             : /* If the result is SIMPLE, then a GC_descr                     */
     196             : /* is returned in *simple_d.                                    */
     197             : /* If the result is NO_MEM, then                                */
     198             : /* we failed to allocate the descriptor.                        */
     199             : /* The implementation knows that GC_DS_LENGTH is 0.             */
     200             : /* *leaf, *complex_d, and *simple_d may be used as temporaries  */
     201             : /* during the construction.                                     */
     202             : #define COMPLEX 2
     203             : #define LEAF    1
     204             : #define SIMPLE  0
     205             : #define NO_MEM  (-1)
     206           0 : STATIC int GC_make_array_descriptor(size_t nelements, size_t size,
     207             :                                     GC_descr descriptor, GC_descr *simple_d,
     208             :                                     complex_descriptor **complex_d,
     209             :                                     struct LeafDescriptor * leaf)
     210             : {
     211             : #   define OPT_THRESHOLD 50
     212             :         /* For larger arrays, we try to combine descriptors of adjacent */
     213             :         /* descriptors to speed up marking, and to reduce the amount    */
     214             :         /* of space needed on the mark stack.                           */
     215           0 :     if ((descriptor & GC_DS_TAGS) == GC_DS_LENGTH) {
     216           0 :       if (descriptor == (GC_descr)size) {
     217           0 :         *simple_d = nelements * descriptor;
     218           0 :         return(SIMPLE);
     219           0 :       } else if ((word)descriptor == 0) {
     220           0 :         *simple_d = (GC_descr)0;
     221           0 :         return(SIMPLE);
     222             :       }
     223             :     }
     224           0 :     if (nelements <= OPT_THRESHOLD) {
     225           0 :       if (nelements <= 1) {
     226           0 :         if (nelements == 1) {
     227           0 :             *simple_d = descriptor;
     228           0 :             return(SIMPLE);
     229             :         } else {
     230           0 :             *simple_d = (GC_descr)0;
     231           0 :             return(SIMPLE);
     232             :         }
     233             :       }
     234           0 :     } else if (size <= BITMAP_BITS/2
     235           0 :                && (descriptor & GC_DS_TAGS) != GC_DS_PROC
     236           0 :                && (size & (sizeof(word)-1)) == 0) {
     237             :       int result =
     238           0 :           GC_make_array_descriptor(nelements/2, 2*size,
     239             :                                    GC_double_descr(descriptor,
     240             :                                                    BYTES_TO_WORDS(size)),
     241           0 :                                    simple_d, complex_d, leaf);
     242           0 :       if ((nelements & 1) == 0) {
     243           0 :           return(result);
     244             :       } else {
     245             :           struct LeafDescriptor * one_element =
     246           0 :               (struct LeafDescriptor *)
     247           0 :                 GC_malloc_atomic(sizeof(struct LeafDescriptor));
     248             : 
     249           0 :           if (result == NO_MEM || one_element == 0) return(NO_MEM);
     250           0 :           one_element -> ld_tag = LEAF_TAG;
     251           0 :           one_element -> ld_size = size;
     252           0 :           one_element -> ld_nelements = 1;
     253           0 :           one_element -> ld_descriptor = descriptor;
     254           0 :           switch(result) {
     255             :             case SIMPLE:
     256             :             {
     257             :               struct LeafDescriptor * beginning =
     258           0 :                 (struct LeafDescriptor *)
     259           0 :                   GC_malloc_atomic(sizeof(struct LeafDescriptor));
     260           0 :               if (beginning == 0) return(NO_MEM);
     261           0 :               beginning -> ld_tag = LEAF_TAG;
     262           0 :               beginning -> ld_size = size;
     263           0 :               beginning -> ld_nelements = 1;
     264           0 :               beginning -> ld_descriptor = *simple_d;
     265           0 :               *complex_d = GC_make_sequence_descriptor(
     266             :                                 (complex_descriptor *)beginning,
     267             :                                 (complex_descriptor *)one_element);
     268           0 :               break;
     269             :             }
     270             :             case LEAF:
     271             :             {
     272             :               struct LeafDescriptor * beginning =
     273           0 :                 (struct LeafDescriptor *)
     274           0 :                   GC_malloc_atomic(sizeof(struct LeafDescriptor));
     275           0 :               if (beginning == 0) return(NO_MEM);
     276           0 :               beginning -> ld_tag = LEAF_TAG;
     277           0 :               beginning -> ld_size = leaf -> ld_size;
     278           0 :               beginning -> ld_nelements = leaf -> ld_nelements;
     279           0 :               beginning -> ld_descriptor = leaf -> ld_descriptor;
     280           0 :               *complex_d = GC_make_sequence_descriptor(
     281             :                                 (complex_descriptor *)beginning,
     282             :                                 (complex_descriptor *)one_element);
     283           0 :               break;
     284             :             }
     285             :             case COMPLEX:
     286           0 :               *complex_d = GC_make_sequence_descriptor(
     287             :                                 *complex_d,
     288             :                                 (complex_descriptor *)one_element);
     289             :               break;
     290             :           }
     291           0 :           return(COMPLEX);
     292             :       }
     293             :     }
     294             : 
     295           0 :     leaf -> ld_size = size;
     296           0 :     leaf -> ld_nelements = nelements;
     297           0 :     leaf -> ld_descriptor = descriptor;
     298           0 :     return(LEAF);
     299             : }
     300             : 
     301             : STATIC complex_descriptor *
     302           0 : GC_make_sequence_descriptor(complex_descriptor *first,
     303             :                             complex_descriptor *second)
     304             : {
     305             :     struct SequenceDescriptor * result =
     306           0 :         (struct SequenceDescriptor *)
     307           0 :                 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       */
     310             :     /* info.                                                            */
     311           0 :     if (result != 0) {
     312           0 :         result -> sd_tag = SEQUENCE_TAG;
     313           0 :         result -> sd_first = first;
     314           0 :         result -> sd_second = second;
     315             :     }
     316           0 :     return((complex_descriptor *)result);
     317             : }
     318             : 
     319             : #ifdef UNDEFINED
     320             :   complex_descriptor * GC_make_complex_array_descriptor(word nelements,
     321             :                                                 complex_descriptor *descr)
     322             :   {
     323             :     struct ComplexArrayDescriptor * result =
     324             :         (struct ComplexArrayDescriptor *)
     325             :                 GC_malloc(sizeof(struct ComplexArrayDescriptor));
     326             : 
     327             :     if (result != 0) {
     328             :         result -> ad_tag = ARRAY_TAG;
     329             :         result -> ad_nelements = nelements;
     330             :         result -> ad_element_descr = descr;
     331             :     }
     332             :     return((complex_descriptor *)result);
     333             :   }
     334             : #endif
     335             : 
     336             : STATIC ptr_t * GC_eobjfreelist = NULL;
     337             : 
     338             : STATIC ptr_t * GC_arobjfreelist = NULL;
     339             : 
     340             : STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
     341             :                                 mse * mark_stack_limit, word env);
     342             : 
     343             : STATIC mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr,
     344             :                                 mse * mark_stack_limit, word env);
     345             : 
     346             : /* Caller does not hold allocation lock. */
     347           0 : STATIC void GC_init_explicit_typing(void)
     348             : {
     349             :     register unsigned i;
     350             :     DCL_LOCK_STATE;
     351             : 
     352             :     GC_STATIC_ASSERT(sizeof(struct LeafDescriptor) % sizeof(word) == 0);
     353           0 :     LOCK();
     354           0 :     if (GC_explicit_typing_initialized) {
     355           0 :       UNLOCK();
     356           0 :       return;
     357             :     }
     358           0 :     GC_explicit_typing_initialized = TRUE;
     359             :     /* Set up object kind with simple indirect descriptor. */
     360           0 :       GC_eobjfreelist = (ptr_t *)GC_new_free_list_inner();
     361           0 :       GC_explicit_kind = GC_new_kind_inner(
     362             :                             (void **)GC_eobjfreelist,
     363             :                             (((word)WORDS_TO_BYTES(-1)) | GC_DS_PER_OBJECT),
     364             :                             TRUE, TRUE);
     365             :                 /* Descriptors are in the last word of the object. */
     366           0 :       GC_typed_mark_proc_index = GC_new_proc_inner(GC_typed_mark_proc);
     367             :     /* Set up object kind with array descriptor. */
     368           0 :       GC_arobjfreelist = (ptr_t *)GC_new_free_list_inner();
     369           0 :       GC_array_mark_proc_index = GC_new_proc_inner(GC_array_mark_proc);
     370           0 :       GC_array_kind = GC_new_kind_inner(
     371             :                             (void **)GC_arobjfreelist,
     372           0 :                             GC_MAKE_PROC(GC_array_mark_proc_index, 0),
     373             :                             FALSE, TRUE);
     374           0 :       for (i = 0; i < WORDSZ/2; i++) {
     375           0 :           GC_descr d = (((word)(-1)) >> (WORDSZ - i)) << (WORDSZ - i);
     376           0 :           d |= GC_DS_BITMAP;
     377           0 :           GC_bm_table[i] = d;
     378             :       }
     379           0 :     UNLOCK();
     380             : }
     381             : 
     382           0 : STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
     383             :                                 mse * mark_stack_limit, word env)
     384             : {
     385           0 :     word bm = GC_ext_descriptors[env].ed_bitmap;
     386           0 :     word * current_p = addr;
     387             :     word current;
     388           0 :     ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
     389           0 :     ptr_t least_ha = GC_least_plausible_heap_addr;
     390             :     DECLARE_HDR_CACHE;
     391             : 
     392           0 :     INIT_HDR_CACHE;
     393           0 :     for (; bm != 0; bm >>= 1, current_p++) {
     394           0 :         if (bm & 1) {
     395           0 :             current = *current_p;
     396             :             FIXUP_POINTER(current);
     397           0 :             if ((ptr_t)current >= least_ha && (ptr_t)current <= greatest_ha) {
     398           0 :                 PUSH_CONTENTS((ptr_t)current, mark_stack_ptr,
     399             :                               mark_stack_limit, (ptr_t)current_p, exit1);
     400             :             }
     401             :         }
     402             :     }
     403           0 :     if (GC_ext_descriptors[env].ed_continued) {
     404             :         /* Push an entry with the rest of the descriptor back onto the  */
     405             :         /* stack.  Thus we never do too much work at once.  Note that   */
     406             :         /* we also can't overflow the mark stack unless we actually     */
     407             :         /* mark something.                                              */
     408           0 :         mark_stack_ptr++;
     409           0 :         if (mark_stack_ptr >= mark_stack_limit) {
     410           0 :             mark_stack_ptr = GC_signal_mark_stack_overflow(mark_stack_ptr);
     411             :         }
     412           0 :         mark_stack_ptr -> mse_start = (ptr_t)(addr + WORDSZ);
     413           0 :         mark_stack_ptr -> mse_descr =
     414           0 :                 GC_MAKE_PROC(GC_typed_mark_proc_index, env+1);
     415             :     }
     416           0 :     return(mark_stack_ptr);
     417             : }
     418             : 
     419             : /* Return the size of the object described by d.  It would be faster to */
     420             : /* store this directly, or to compute it as part of                     */
     421             : /* GC_push_complex_descriptor, but hopefully it doesn't matter.         */
     422           0 : STATIC word GC_descr_obj_size(complex_descriptor *d)
     423             : {
     424           0 :     switch(d -> TAG) {
     425             :       case LEAF_TAG:
     426           0 :         return(d -> ld.ld_nelements * d -> ld.ld_size);
     427             :       case ARRAY_TAG:
     428           0 :         return(d -> ad.ad_nelements
     429           0 :                * GC_descr_obj_size(d -> ad.ad_element_descr));
     430             :       case SEQUENCE_TAG:
     431           0 :         return(GC_descr_obj_size(d -> sd.sd_first)
     432           0 :                + GC_descr_obj_size(d -> sd.sd_second));
     433             :       default:
     434           0 :         ABORT("Bad complex descriptor");
     435           0 :         /*NOTREACHED*/ return 0; /*NOTREACHED*/
     436             :     }
     437             : }
     438             : 
     439             : /* Push descriptors for the object at addr with complex descriptor d    */
     440             : /* onto the mark stack.  Return 0 if the mark stack overflowed.         */
     441           0 : STATIC mse * GC_push_complex_descriptor(word *addr, complex_descriptor *d,
     442             :                                         mse *msp, mse *msl)
     443             : {
     444           0 :     register ptr_t current = (ptr_t) addr;
     445             :     register word nelements;
     446             :     register word sz;
     447             :     register word i;
     448             : 
     449           0 :     switch(d -> TAG) {
     450             :       case LEAF_TAG:
     451             :         {
     452           0 :           register GC_descr descr = d -> ld.ld_descriptor;
     453             : 
     454           0 :           nelements = d -> ld.ld_nelements;
     455           0 :           if (msl - msp <= (ptrdiff_t)nelements) return(0);
     456           0 :           sz = d -> ld.ld_size;
     457           0 :           for (i = 0; i < nelements; i++) {
     458           0 :               msp++;
     459           0 :               msp -> mse_start = current;
     460           0 :               msp -> mse_descr = descr;
     461           0 :               current += sz;
     462             :           }
     463           0 :           return(msp);
     464             :         }
     465             :       case ARRAY_TAG:
     466             :         {
     467           0 :           register complex_descriptor *descr = d -> ad.ad_element_descr;
     468             : 
     469           0 :           nelements = d -> ad.ad_nelements;
     470           0 :           sz = GC_descr_obj_size(descr);
     471           0 :           for (i = 0; i < nelements; i++) {
     472           0 :               msp = GC_push_complex_descriptor((word *)current, descr,
     473             :                                                 msp, msl);
     474           0 :               if (msp == 0) return(0);
     475           0 :               current += sz;
     476             :           }
     477           0 :           return(msp);
     478             :         }
     479             :       case SEQUENCE_TAG:
     480             :         {
     481           0 :           sz = GC_descr_obj_size(d -> sd.sd_first);
     482           0 :           msp = GC_push_complex_descriptor((word *)current, d -> sd.sd_first,
     483             :                                            msp, msl);
     484           0 :           if (msp == 0) return(0);
     485           0 :           current += sz;
     486           0 :           msp = GC_push_complex_descriptor((word *)current, d -> sd.sd_second,
     487             :                                            msp, msl);
     488           0 :           return(msp);
     489             :         }
     490             :       default:
     491           0 :         ABORT("Bad complex descriptor");
     492           0 :         /*NOTREACHED*/ return 0; /*NOTREACHED*/
     493             :    }
     494             : }
     495             : 
     496             : /*ARGSUSED*/
     497           0 : STATIC mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr,
     498             :                                 mse * mark_stack_limit, word env)
     499             : {
     500           0 :     hdr * hhdr = HDR(addr);
     501           0 :     size_t sz = hhdr -> hb_sz;
     502           0 :     size_t nwords = BYTES_TO_WORDS(sz);
     503           0 :     complex_descriptor * descr = (complex_descriptor *)(addr[nwords-1]);
     504           0 :     mse * orig_mark_stack_ptr = mark_stack_ptr;
     505             :     mse * new_mark_stack_ptr;
     506             : 
     507           0 :     if (descr == 0) {
     508             :         /* Found a reference to a free list entry.  Ignore it. */
     509           0 :         return(orig_mark_stack_ptr);
     510             :     }
     511             :     /* In use counts were already updated when array descriptor was     */
     512             :     /* pushed.  Here we only replace it by subobject descriptors, so    */
     513             :     /* no update is necessary.                                          */
     514           0 :     new_mark_stack_ptr = GC_push_complex_descriptor(addr, descr,
     515             :                                                     mark_stack_ptr,
     516             :                                                     mark_stack_limit-1);
     517           0 :     if (new_mark_stack_ptr == 0) {
     518             :         /* Doesn't fit.  Conservatively push the whole array as a unit  */
     519             :         /* and request a mark stack expansion.                          */
     520             :         /* This cannot cause a mark stack overflow, since it replaces   */
     521             :         /* the original array entry.                                    */
     522           0 :         GC_mark_stack_too_small = TRUE;
     523           0 :         new_mark_stack_ptr = orig_mark_stack_ptr + 1;
     524           0 :         new_mark_stack_ptr -> mse_start = (ptr_t)addr;
     525           0 :         new_mark_stack_ptr -> mse_descr = sz | GC_DS_LENGTH;
     526             :     } else {
     527             :         /* Push descriptor itself */
     528           0 :         new_mark_stack_ptr++;
     529           0 :         new_mark_stack_ptr -> mse_start = (ptr_t)(addr + nwords - 1);
     530           0 :         new_mark_stack_ptr -> mse_descr = sizeof(word) | GC_DS_LENGTH;
     531             :     }
     532           0 :     return new_mark_stack_ptr;
     533             : }
     534             : 
     535           0 : GC_API GC_descr GC_CALL GC_make_descriptor(GC_bitmap bm, size_t len)
     536             : {
     537           0 :     signed_word last_set_bit = len - 1;
     538             :     GC_descr result;
     539             :     signed_word i;
     540             : #   define HIGH_BIT (((word)1) << (WORDSZ - 1))
     541             : 
     542           0 :     if (!GC_explicit_typing_initialized) GC_init_explicit_typing();
     543           0 :     while (last_set_bit >= 0 && !GC_get_bit(bm, last_set_bit))
     544           0 :       last_set_bit--;
     545           0 :     if (last_set_bit < 0) return(0 /* no pointers */);
     546             : #   if ALIGNMENT == CPP_WORDSZ/8
     547             :     {
     548           0 :       register GC_bool all_bits_set = TRUE;
     549           0 :       for (i = 0; i < last_set_bit; i++) {
     550           0 :         if (!GC_get_bit(bm, i)) {
     551           0 :             all_bits_set = FALSE;
     552           0 :             break;
     553             :         }
     554             :       }
     555           0 :       if (all_bits_set) {
     556             :         /* An initial section contains all pointers.  Use length descriptor. */
     557           0 :         return (WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH);
     558             :       }
     559             :     }
     560             : #   endif
     561           0 :     if ((word)last_set_bit < BITMAP_BITS) {
     562             :         /* Hopefully the common case.                   */
     563             :         /* Build bitmap descriptor (with bits reversed) */
     564           0 :         result = HIGH_BIT;
     565           0 :         for (i = last_set_bit - 1; i >= 0; i--) {
     566           0 :             result >>= 1;
     567           0 :             if (GC_get_bit(bm, i)) result |= HIGH_BIT;
     568             :         }
     569           0 :         result |= GC_DS_BITMAP;
     570           0 :         return(result);
     571             :     } else {
     572             :         signed_word index;
     573             : 
     574           0 :         index = GC_add_ext_descriptor(bm, (word)last_set_bit+1);
     575           0 :         if (index == -1) return(WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH);
     576             :                                 /* Out of memory: use conservative      */
     577             :                                 /* approximation.                       */
     578           0 :         result = GC_MAKE_PROC(GC_typed_mark_proc_index, (word)index);
     579           0 :         return result;
     580             :     }
     581             : }
     582             : 
     583           0 : GC_API void * GC_CALL GC_malloc_explicitly_typed(size_t lb, GC_descr d)
     584             : {
     585             :     ptr_t op;
     586             :     ptr_t * opp;
     587             :     size_t lg;
     588             :     DCL_LOCK_STATE;
     589             : 
     590           0 :     lb += TYPD_EXTRA_BYTES;
     591           0 :     if(SMALL_OBJ(lb)) {
     592           0 :         lg = GC_size_map[lb];
     593           0 :         opp = &(GC_eobjfreelist[lg]);
     594           0 :         LOCK();
     595           0 :         if( (op = *opp) == 0 ) {
     596           0 :             UNLOCK();
     597           0 :             op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
     598           0 :             if (0 == op) return 0;
     599           0 :             lg = GC_size_map[lb];       /* May have been uninitialized. */
     600             :         } else {
     601           0 :             *opp = obj_link(op);
     602           0 :             obj_link(op) = 0;
     603           0 :             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
     604           0 :             UNLOCK();
     605             :         }
     606           0 :         ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     607             :    } else {
     608           0 :        op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
     609           0 :        if (op != NULL) {
     610           0 :             lg = BYTES_TO_GRANULES(GC_size(op));
     611           0 :             ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     612             :        }
     613             :    }
     614           0 :    return((void *) op);
     615             : }
     616             : 
     617           0 : GC_API void * GC_CALL GC_malloc_explicitly_typed_ignore_off_page(size_t lb,
     618             :                                                                  GC_descr d)
     619             : {
     620             :     ptr_t op;
     621             :     ptr_t * opp;
     622             :     size_t lg;
     623             :     DCL_LOCK_STATE;
     624             : 
     625           0 :     lb += TYPD_EXTRA_BYTES;
     626           0 :     if( SMALL_OBJ(lb) ) {
     627           0 :         lg = GC_size_map[lb];
     628           0 :         opp = &(GC_eobjfreelist[lg]);
     629           0 :         LOCK();
     630           0 :         if( (op = *opp) == 0 ) {
     631           0 :             UNLOCK();
     632           0 :             op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
     633           0 :             if (0 == op) return 0;
     634           0 :             lg = GC_size_map[lb];       /* May have been uninitialized. */
     635             :         } else {
     636           0 :             *opp = obj_link(op);
     637           0 :             obj_link(op) = 0;
     638           0 :             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
     639           0 :             UNLOCK();
     640             :         }
     641           0 :         ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     642             :    } else {
     643           0 :        op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
     644           0 :        if (op != NULL) {
     645           0 :          lg = BYTES_TO_WORDS(GC_size(op));
     646           0 :          ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     647             :        }
     648             :    }
     649           0 :    return((void *) op);
     650             : }
     651             : 
     652           0 : GC_API void * GC_CALL GC_calloc_explicitly_typed(size_t n, size_t lb,
     653             :                                                  GC_descr d)
     654             : {
     655             :     ptr_t op;
     656             :     ptr_t * opp;
     657             :     size_t lg;
     658             :     GC_descr simple_descr;
     659             :     complex_descriptor *complex_descr;
     660             :     register int descr_type;
     661             :     struct LeafDescriptor leaf;
     662             :     DCL_LOCK_STATE;
     663             : 
     664           0 :     descr_type = GC_make_array_descriptor((word)n, (word)lb, d,
     665             :                                           &simple_descr, &complex_descr, &leaf);
     666           0 :     switch(descr_type) {
     667           0 :         case NO_MEM: return(0);
     668           0 :         case SIMPLE: return(GC_malloc_explicitly_typed(n*lb, simple_descr));
     669             :         case LEAF:
     670           0 :             lb *= n;
     671           0 :             lb += sizeof(struct LeafDescriptor) + TYPD_EXTRA_BYTES;
     672           0 :             break;
     673             :         case COMPLEX:
     674           0 :             lb *= n;
     675           0 :             lb += TYPD_EXTRA_BYTES;
     676             :             break;
     677             :     }
     678           0 :     if( SMALL_OBJ(lb) ) {
     679           0 :         lg = GC_size_map[lb];
     680           0 :         opp = &(GC_arobjfreelist[lg]);
     681           0 :         LOCK();
     682           0 :         if( (op = *opp) == 0 ) {
     683           0 :             UNLOCK();
     684           0 :             op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind);
     685           0 :             if (0 == op) return(0);
     686           0 :             lg = GC_size_map[lb];       /* May have been uninitialized. */
     687             :         } else {
     688           0 :             *opp = obj_link(op);
     689           0 :             obj_link(op) = 0;
     690           0 :             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
     691           0 :             UNLOCK();
     692             :         }
     693             :    } else {
     694           0 :        op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind);
     695           0 :        if (0 == op) return(0);
     696           0 :        lg = BYTES_TO_GRANULES(GC_size(op));
     697             :    }
     698           0 :    if (descr_type == LEAF) {
     699             :        /* Set up the descriptor inside the object itself. */
     700             :        volatile struct LeafDescriptor * lp =
     701             :            (struct LeafDescriptor *)
     702             :                ((word *)op
     703           0 :                 + GRANULES_TO_WORDS(lg)
     704           0 :                 - (BYTES_TO_WORDS(sizeof(struct LeafDescriptor)) + 1));
     705             : 
     706           0 :        lp -> ld_tag = LEAF_TAG;
     707           0 :        lp -> ld_size = leaf.ld_size;
     708           0 :        lp -> ld_nelements = leaf.ld_nelements;
     709           0 :        lp -> ld_descriptor = leaf.ld_descriptor;
     710           0 :        ((volatile word *)op)[GRANULES_TO_WORDS(lg) - 1] = (word)lp;
     711             :    } else {
     712           0 :        size_t lw = GRANULES_TO_WORDS(lg);
     713             : 
     714           0 :        ((word *)op)[lw - 1] = (word)complex_descr;
     715             :        /* Make sure the descriptor is cleared once there is any danger  */
     716             :        /* it may have been collected.                                   */
     717           0 :        if (GC_general_register_disappearing_link((void * *)((word *)op+lw-1),
     718             :                                                  op) == GC_NO_MEMORY) {
     719             :            /* Couldn't register it due to lack of memory.  Punt.        */
     720             :            /* This will probably fail too, but gives the recovery code  */
     721             :            /* a chance.                                                 */
     722           0 :            return(GC_malloc(n*lb));
     723             :        }
     724             :    }
     725           0 :    return((void *) op);
     726             : }

Generated by: LCOV version 1.11