LCOV - code coverage report
Current view: top level - mm/boehm-gc - typd_mlc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 303 0.0 %
Date: 2017-07-14 10:03:36 Functions: 0 14 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
       3             :  * Copyright (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(const GC_word * 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             :             GC_ASSERT((word)&GC_ext_descriptors % sizeof(word) == 0);
     130           0 :             GC_push_typed_structures = GC_push_typed_structures_proc;
     131           0 :             UNLOCK();
     132           0 :             new_size = ED_INITIAL_SIZE;
     133             :         } else {
     134           0 :             UNLOCK();
     135           0 :             new_size = 2 * ed_size;
     136           0 :             if (new_size > MAX_ENV) return(-1);
     137             :         }
     138           0 :         new = (ext_descr *) GC_malloc_atomic(new_size * sizeof(ext_descr));
     139           0 :         if (new == 0) return(-1);
     140           0 :         LOCK();
     141           0 :         if (ed_size == GC_ed_size) {
     142           0 :             if (GC_avail_descr != 0) {
     143           0 :                 BCOPY(GC_ext_descriptors, new,
     144             :                       GC_avail_descr * sizeof(ext_descr));
     145             :             }
     146           0 :             GC_ed_size = new_size;
     147           0 :             GC_ext_descriptors = new;
     148             :         }  /* else another thread already resized it in the meantime */
     149             :     }
     150           0 :     result = GC_avail_descr;
     151           0 :     for (i = 0; i < nwords-1; i++) {
     152           0 :         GC_ext_descriptors[result + i].ed_bitmap = bm[i];
     153           0 :         GC_ext_descriptors[result + i].ed_continued = TRUE;
     154             :     }
     155           0 :     last_part = bm[i];
     156             :     /* Clear irrelevant bits. */
     157           0 :     extra_bits = nwords * WORDSZ - nbits;
     158           0 :     last_part <<= extra_bits;
     159           0 :     last_part >>= extra_bits;
     160           0 :     GC_ext_descriptors[result + i].ed_bitmap = last_part;
     161           0 :     GC_ext_descriptors[result + i].ed_continued = FALSE;
     162           0 :     GC_avail_descr += nwords;
     163           0 :     UNLOCK();
     164           0 :     return(result);
     165             : }
     166             : 
     167             : /* Table of bitmap descriptors for n word long all pointer objects.     */
     168             : STATIC GC_descr GC_bm_table[WORDSZ/2];
     169             : 
     170             : /* Return a descriptor for the concatenation of 2 nwords long objects,  */
     171             : /* each of which is described by descriptor.                            */
     172             : /* The result is known to be short enough to fit into a bitmap          */
     173             : /* descriptor.                                                          */
     174             : /* Descriptor is a GC_DS_LENGTH or GC_DS_BITMAP descriptor.             */
     175           0 : STATIC GC_descr GC_double_descr(GC_descr descriptor, word nwords)
     176             : {
     177           0 :     if ((descriptor & GC_DS_TAGS) == GC_DS_LENGTH) {
     178           0 :         descriptor = GC_bm_table[BYTES_TO_WORDS((word)descriptor)];
     179             :     };
     180           0 :     descriptor |= (descriptor & ~GC_DS_TAGS) >> nwords;
     181           0 :     return(descriptor);
     182             : }
     183             : 
     184             : STATIC complex_descriptor *
     185             : GC_make_sequence_descriptor(complex_descriptor *first,
     186             :                             complex_descriptor *second);
     187             : 
     188             : /* Build a descriptor for an array with nelements elements,     */
     189             : /* each of which can be described by a simple descriptor.       */
     190             : /* We try to optimize some common cases.                        */
     191             : /* If the result is COMPLEX, then a complex_descr* is returned  */
     192             : /* in *complex_d.                                                       */
     193             : /* If the result is LEAF, then we built a LeafDescriptor in     */
     194             : /* the structure pointed to by leaf.                            */
     195             : /* The tag in the leaf structure is not set.                    */
     196             : /* If the result is SIMPLE, then a GC_descr                     */
     197             : /* is returned in *simple_d.                                    */
     198             : /* If the result is NO_MEM, then                                */
     199             : /* we failed to allocate the descriptor.                        */
     200             : /* The implementation knows that GC_DS_LENGTH is 0.             */
     201             : /* *leaf, *complex_d, and *simple_d may be used as temporaries  */
     202             : /* during the construction.                                     */
     203             : #define COMPLEX 2
     204             : #define LEAF    1
     205             : #define SIMPLE  0
     206             : #define NO_MEM  (-1)
     207           0 : STATIC int GC_make_array_descriptor(size_t nelements, size_t size,
     208             :                                     GC_descr descriptor, GC_descr *simple_d,
     209             :                                     complex_descriptor **complex_d,
     210             :                                     struct LeafDescriptor * leaf)
     211             : {
     212             : #   define OPT_THRESHOLD 50
     213             :         /* For larger arrays, we try to combine descriptors of adjacent */
     214             :         /* descriptors to speed up marking, and to reduce the amount    */
     215             :         /* of space needed on the mark stack.                           */
     216           0 :     if ((descriptor & GC_DS_TAGS) == GC_DS_LENGTH) {
     217           0 :       if (descriptor == (GC_descr)size) {
     218           0 :         *simple_d = nelements * descriptor;
     219           0 :         return(SIMPLE);
     220           0 :       } else if ((word)descriptor == 0) {
     221           0 :         *simple_d = (GC_descr)0;
     222           0 :         return(SIMPLE);
     223             :       }
     224             :     }
     225           0 :     if (nelements <= OPT_THRESHOLD) {
     226           0 :       if (nelements <= 1) {
     227           0 :         if (nelements == 1) {
     228           0 :             *simple_d = descriptor;
     229           0 :             return(SIMPLE);
     230             :         } else {
     231           0 :             *simple_d = (GC_descr)0;
     232           0 :             return(SIMPLE);
     233             :         }
     234             :       }
     235           0 :     } else if (size <= BITMAP_BITS/2
     236           0 :                && (descriptor & GC_DS_TAGS) != GC_DS_PROC
     237           0 :                && (size & (sizeof(word)-1)) == 0) {
     238             :       int result =
     239           0 :           GC_make_array_descriptor(nelements/2, 2*size,
     240             :                                    GC_double_descr(descriptor,
     241             :                                                    BYTES_TO_WORDS(size)),
     242           0 :                                    simple_d, complex_d, leaf);
     243           0 :       if ((nelements & 1) == 0) {
     244           0 :           return(result);
     245             :       } else {
     246             :           struct LeafDescriptor * one_element =
     247           0 :               (struct LeafDescriptor *)
     248           0 :                 GC_malloc_atomic(sizeof(struct LeafDescriptor));
     249             : 
     250           0 :           if (result == NO_MEM || one_element == 0) return(NO_MEM);
     251           0 :           one_element -> ld_tag = LEAF_TAG;
     252           0 :           one_element -> ld_size = size;
     253           0 :           one_element -> ld_nelements = 1;
     254           0 :           one_element -> ld_descriptor = descriptor;
     255           0 :           switch(result) {
     256             :             case SIMPLE:
     257             :             {
     258             :               struct LeafDescriptor * beginning =
     259           0 :                 (struct LeafDescriptor *)
     260           0 :                   GC_malloc_atomic(sizeof(struct LeafDescriptor));
     261           0 :               if (beginning == 0) return(NO_MEM);
     262           0 :               beginning -> ld_tag = LEAF_TAG;
     263           0 :               beginning -> ld_size = size;
     264           0 :               beginning -> ld_nelements = 1;
     265           0 :               beginning -> ld_descriptor = *simple_d;
     266           0 :               *complex_d = GC_make_sequence_descriptor(
     267             :                                 (complex_descriptor *)beginning,
     268             :                                 (complex_descriptor *)one_element);
     269           0 :               break;
     270             :             }
     271             :             case LEAF:
     272             :             {
     273             :               struct LeafDescriptor * beginning =
     274           0 :                 (struct LeafDescriptor *)
     275           0 :                   GC_malloc_atomic(sizeof(struct LeafDescriptor));
     276           0 :               if (beginning == 0) return(NO_MEM);
     277           0 :               beginning -> ld_tag = LEAF_TAG;
     278           0 :               beginning -> ld_size = leaf -> ld_size;
     279           0 :               beginning -> ld_nelements = leaf -> ld_nelements;
     280           0 :               beginning -> ld_descriptor = leaf -> ld_descriptor;
     281           0 :               *complex_d = GC_make_sequence_descriptor(
     282             :                                 (complex_descriptor *)beginning,
     283             :                                 (complex_descriptor *)one_element);
     284           0 :               break;
     285             :             }
     286             :             case COMPLEX:
     287           0 :               *complex_d = GC_make_sequence_descriptor(
     288             :                                 *complex_d,
     289             :                                 (complex_descriptor *)one_element);
     290             :               break;
     291             :           }
     292           0 :           return(COMPLEX);
     293             :       }
     294             :     }
     295             : 
     296           0 :     leaf -> ld_size = size;
     297           0 :     leaf -> ld_nelements = nelements;
     298           0 :     leaf -> ld_descriptor = descriptor;
     299           0 :     return(LEAF);
     300             : }
     301             : 
     302             : STATIC complex_descriptor *
     303           0 : GC_make_sequence_descriptor(complex_descriptor *first,
     304             :                             complex_descriptor *second)
     305             : {
     306             :     struct SequenceDescriptor * result =
     307           0 :         (struct SequenceDescriptor *)
     308           0 :                 GC_malloc(sizeof(struct SequenceDescriptor));
     309             :     /* Can't result in overly conservative marking, since tags are      */
     310             :     /* very small integers. Probably faster than maintaining type       */
     311             :     /* info.                                                            */
     312           0 :     if (result != 0) {
     313           0 :         result -> sd_tag = SEQUENCE_TAG;
     314           0 :         result -> sd_first = first;
     315           0 :         result -> sd_second = second;
     316             :     }
     317           0 :     return((complex_descriptor *)result);
     318             : }
     319             : 
     320             : #ifdef UNDEFINED
     321             :   complex_descriptor * GC_make_complex_array_descriptor(word nelements,
     322             :                                                 complex_descriptor *descr)
     323             :   {
     324             :     struct ComplexArrayDescriptor * result =
     325             :         (struct ComplexArrayDescriptor *)
     326             :                 GC_malloc(sizeof(struct ComplexArrayDescriptor));
     327             : 
     328             :     if (result != 0) {
     329             :         result -> ad_tag = ARRAY_TAG;
     330             :         result -> ad_nelements = nelements;
     331             :         result -> ad_element_descr = descr;
     332             :     }
     333             :     return((complex_descriptor *)result);
     334             :   }
     335             : #endif
     336             : 
     337             : STATIC ptr_t * GC_eobjfreelist = NULL;
     338             : 
     339             : STATIC ptr_t * GC_arobjfreelist = NULL;
     340             : 
     341             : STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
     342             :                                 mse * mark_stack_limit, word env);
     343             : 
     344             : STATIC mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr,
     345             :                                 mse * mark_stack_limit, word env);
     346             : 
     347             : /* Caller does not hold allocation lock. */
     348           0 : STATIC void GC_init_explicit_typing(void)
     349             : {
     350             :     register unsigned i;
     351             :     DCL_LOCK_STATE;
     352             : 
     353             :     GC_STATIC_ASSERT(sizeof(struct LeafDescriptor) % sizeof(word) == 0);
     354           0 :     LOCK();
     355           0 :     if (GC_explicit_typing_initialized) {
     356           0 :       UNLOCK();
     357           0 :       return;
     358             :     }
     359           0 :     GC_explicit_typing_initialized = TRUE;
     360             :     /* Set up object kind with simple indirect descriptor. */
     361           0 :       GC_eobjfreelist = (ptr_t *)GC_new_free_list_inner();
     362           0 :       GC_explicit_kind = GC_new_kind_inner(
     363             :                             (void **)GC_eobjfreelist,
     364             :                             (WORDS_TO_BYTES((word)-1) | GC_DS_PER_OBJECT),
     365             :                             TRUE, TRUE);
     366             :                 /* Descriptors are in the last word of the object. */
     367           0 :       GC_typed_mark_proc_index = GC_new_proc_inner(GC_typed_mark_proc);
     368             :     /* Set up object kind with array descriptor. */
     369           0 :       GC_arobjfreelist = (ptr_t *)GC_new_free_list_inner();
     370           0 :       GC_array_mark_proc_index = GC_new_proc_inner(GC_array_mark_proc);
     371           0 :       GC_array_kind = GC_new_kind_inner(
     372             :                             (void **)GC_arobjfreelist,
     373           0 :                             GC_MAKE_PROC(GC_array_mark_proc_index, 0),
     374             :                             FALSE, TRUE);
     375           0 :       for (i = 0; i < WORDSZ/2; i++) {
     376           0 :           GC_bm_table[i] = (((word)-1) << (WORDSZ - i)) | GC_DS_BITMAP;
     377             :       }
     378           0 :     UNLOCK();
     379             : }
     380             : 
     381           0 : STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
     382             :                                 mse * mark_stack_limit, word env)
     383             : {
     384           0 :     word bm = GC_ext_descriptors[env].ed_bitmap;
     385           0 :     word * current_p = addr;
     386             :     word current;
     387           0 :     ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
     388           0 :     ptr_t least_ha = GC_least_plausible_heap_addr;
     389             :     DECLARE_HDR_CACHE;
     390             : 
     391           0 :     INIT_HDR_CACHE;
     392           0 :     for (; bm != 0; bm >>= 1, current_p++) {
     393           0 :         if (bm & 1) {
     394           0 :             current = *current_p;
     395             :             FIXUP_POINTER(current);
     396           0 :             if (current >= (word)least_ha && current <= (word)greatest_ha) {
     397           0 :                 PUSH_CONTENTS((ptr_t)current, mark_stack_ptr,
     398             :                               mark_stack_limit, (ptr_t)current_p, exit1);
     399             :             }
     400             :         }
     401             :     }
     402           0 :     if (GC_ext_descriptors[env].ed_continued) {
     403             :         /* Push an entry with the rest of the descriptor back onto the  */
     404             :         /* stack.  Thus we never do too much work at once.  Note that   */
     405             :         /* we also can't overflow the mark stack unless we actually     */
     406             :         /* mark something.                                              */
     407           0 :         mark_stack_ptr++;
     408           0 :         if ((word)mark_stack_ptr >= (word)mark_stack_limit) {
     409           0 :             mark_stack_ptr = GC_signal_mark_stack_overflow(mark_stack_ptr);
     410             :         }
     411           0 :         mark_stack_ptr -> mse_start = (ptr_t)(addr + WORDSZ);
     412           0 :         mark_stack_ptr -> mse_descr.w =
     413           0 :                         GC_MAKE_PROC(GC_typed_mark_proc_index, env + 1);
     414             :     }
     415           0 :     return(mark_stack_ptr);
     416             : }
     417             : 
     418             : /* Return the size of the object described by d.  It would be faster to */
     419             : /* store this directly, or to compute it as part of                     */
     420             : /* GC_push_complex_descriptor, but hopefully it doesn't matter.         */
     421           0 : STATIC word GC_descr_obj_size(complex_descriptor *d)
     422             : {
     423           0 :     switch(d -> TAG) {
     424             :       case LEAF_TAG:
     425           0 :         return(d -> ld.ld_nelements * d -> ld.ld_size);
     426             :       case ARRAY_TAG:
     427           0 :         return(d -> ad.ad_nelements
     428           0 :                * GC_descr_obj_size(d -> ad.ad_element_descr));
     429             :       case SEQUENCE_TAG:
     430           0 :         return(GC_descr_obj_size(d -> sd.sd_first)
     431           0 :                + GC_descr_obj_size(d -> sd.sd_second));
     432             :       default:
     433           0 :         ABORT_RET("Bad complex descriptor");
     434           0 :         return 0;
     435             :     }
     436             : }
     437             : 
     438             : /* Push descriptors for the object at addr with complex descriptor d    */
     439             : /* onto the mark stack.  Return 0 if the mark stack overflowed.         */
     440           0 : STATIC mse * GC_push_complex_descriptor(word *addr, complex_descriptor *d,
     441             :                                         mse *msp, mse *msl)
     442             : {
     443           0 :     register ptr_t current = (ptr_t) addr;
     444             :     register word nelements;
     445             :     register word sz;
     446             :     register word i;
     447             : 
     448           0 :     switch(d -> TAG) {
     449             :       case LEAF_TAG:
     450             :         {
     451           0 :           register GC_descr descr = d -> ld.ld_descriptor;
     452             : 
     453           0 :           nelements = d -> ld.ld_nelements;
     454           0 :           if (msl - msp <= (ptrdiff_t)nelements) return(0);
     455           0 :           sz = d -> ld.ld_size;
     456           0 :           for (i = 0; i < nelements; i++) {
     457           0 :               msp++;
     458           0 :               msp -> mse_start = current;
     459           0 :               msp -> mse_descr.w = descr;
     460           0 :               current += sz;
     461             :           }
     462           0 :           return(msp);
     463             :         }
     464             :       case ARRAY_TAG:
     465             :         {
     466           0 :           register complex_descriptor *descr = d -> ad.ad_element_descr;
     467             : 
     468           0 :           nelements = d -> ad.ad_nelements;
     469           0 :           sz = GC_descr_obj_size(descr);
     470           0 :           for (i = 0; i < nelements; i++) {
     471           0 :               msp = GC_push_complex_descriptor((word *)current, descr,
     472             :                                                 msp, msl);
     473           0 :               if (msp == 0) return(0);
     474           0 :               current += sz;
     475             :           }
     476           0 :           return(msp);
     477             :         }
     478             :       case SEQUENCE_TAG:
     479             :         {
     480           0 :           sz = GC_descr_obj_size(d -> sd.sd_first);
     481           0 :           msp = GC_push_complex_descriptor((word *)current, d -> sd.sd_first,
     482             :                                            msp, msl);
     483           0 :           if (msp == 0) return(0);
     484           0 :           current += sz;
     485           0 :           msp = GC_push_complex_descriptor((word *)current, d -> sd.sd_second,
     486             :                                            msp, msl);
     487           0 :           return(msp);
     488             :         }
     489             :       default:
     490           0 :         ABORT_RET("Bad complex descriptor");
     491           0 :         return 0;
     492             :    }
     493             : }
     494             : 
     495           0 : STATIC mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr,
     496             :                                 mse * mark_stack_limit,
     497             :                                 word env GC_ATTR_UNUSED)
     498             : {
     499           0 :     hdr * hhdr = HDR(addr);
     500           0 :     size_t sz = hhdr -> hb_sz;
     501           0 :     size_t nwords = BYTES_TO_WORDS(sz);
     502           0 :     complex_descriptor * descr = (complex_descriptor *)(addr[nwords-1]);
     503           0 :     mse * orig_mark_stack_ptr = mark_stack_ptr;
     504             :     mse * new_mark_stack_ptr;
     505             : 
     506           0 :     if (descr == 0) {
     507             :         /* Found a reference to a free list entry.  Ignore it. */
     508           0 :         return(orig_mark_stack_ptr);
     509             :     }
     510             :     /* In use counts were already updated when array descriptor was     */
     511             :     /* pushed.  Here we only replace it by subobject descriptors, so    */
     512             :     /* no update is necessary.                                          */
     513           0 :     new_mark_stack_ptr = GC_push_complex_descriptor(addr, descr,
     514             :                                                     mark_stack_ptr,
     515             :                                                     mark_stack_limit-1);
     516           0 :     if (new_mark_stack_ptr == 0) {
     517             :         /* Doesn't fit.  Conservatively push the whole array as a unit  */
     518             :         /* and request a mark stack expansion.                          */
     519             :         /* This cannot cause a mark stack overflow, since it replaces   */
     520             :         /* the original array entry.                                    */
     521           0 :         GC_mark_stack_too_small = TRUE;
     522           0 :         new_mark_stack_ptr = orig_mark_stack_ptr + 1;
     523           0 :         new_mark_stack_ptr -> mse_start = (ptr_t)addr;
     524           0 :         new_mark_stack_ptr -> mse_descr.w = sz | GC_DS_LENGTH;
     525             :     } else {
     526             :         /* Push descriptor itself */
     527           0 :         new_mark_stack_ptr++;
     528           0 :         new_mark_stack_ptr -> mse_start = (ptr_t)(addr + nwords - 1);
     529           0 :         new_mark_stack_ptr -> mse_descr.w = sizeof(word) | GC_DS_LENGTH;
     530             :     }
     531           0 :     return new_mark_stack_ptr;
     532             : }
     533             : 
     534           0 : GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * bm, size_t len)
     535             : {
     536           0 :     signed_word last_set_bit = len - 1;
     537             :     GC_descr result;
     538             :     signed_word i;
     539             : #   define HIGH_BIT (((word)1) << (WORDSZ - 1))
     540             : 
     541           0 :     if (!EXPECT(GC_explicit_typing_initialized, TRUE))
     542           0 :       GC_init_explicit_typing();
     543             : 
     544           0 :     while (last_set_bit >= 0 && !GC_get_bit(bm, last_set_bit))
     545           0 :       last_set_bit--;
     546           0 :     if (last_set_bit < 0) return(0 /* no pointers */);
     547             : #   if ALIGNMENT == CPP_WORDSZ/8
     548             :     {
     549           0 :       register GC_bool all_bits_set = TRUE;
     550           0 :       for (i = 0; i < last_set_bit; i++) {
     551           0 :         if (!GC_get_bit(bm, i)) {
     552           0 :             all_bits_set = FALSE;
     553           0 :             break;
     554             :         }
     555             :       }
     556           0 :       if (all_bits_set) {
     557             :         /* An initial section contains all pointers.  Use length descriptor. */
     558           0 :         return (WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH);
     559             :       }
     560             :     }
     561             : #   endif
     562           0 :     if ((word)last_set_bit < BITMAP_BITS) {
     563             :         /* Hopefully the common case.                   */
     564             :         /* Build bitmap descriptor (with bits reversed) */
     565           0 :         result = HIGH_BIT;
     566           0 :         for (i = last_set_bit - 1; i >= 0; i--) {
     567           0 :             result >>= 1;
     568           0 :             if (GC_get_bit(bm, i)) result |= HIGH_BIT;
     569             :         }
     570           0 :         result |= GC_DS_BITMAP;
     571           0 :         return(result);
     572             :     } else {
     573             :         signed_word index;
     574             : 
     575           0 :         index = GC_add_ext_descriptor(bm, (word)last_set_bit+1);
     576           0 :         if (index == -1) return(WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH);
     577             :                                 /* Out of memory: use conservative      */
     578             :                                 /* approximation.                       */
     579           0 :         result = GC_MAKE_PROC(GC_typed_mark_proc_index, (word)index);
     580           0 :         return result;
     581             :     }
     582             : }
     583             : 
     584           0 : GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_explicitly_typed(size_t lb,
     585             :                                                                 GC_descr d)
     586             : {
     587             :     ptr_t op;
     588             :     ptr_t * opp;
     589             :     size_t lg;
     590             :     DCL_LOCK_STATE;
     591             : 
     592           0 :     lb += TYPD_EXTRA_BYTES;
     593           0 :     if(SMALL_OBJ(lb)) {
     594             :         GC_DBG_COLLECT_AT_MALLOC(lb);
     595           0 :         lg = GC_size_map[lb];
     596           0 :         opp = &(GC_eobjfreelist[lg]);
     597           0 :         LOCK();
     598           0 :         op = *opp;
     599           0 :         if (EXPECT(0 == op, FALSE)) {
     600           0 :             UNLOCK();
     601           0 :             op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
     602           0 :             if (0 == op) return 0;
     603           0 :             lg = GC_size_map[lb];       /* May have been uninitialized. */
     604             :         } else {
     605           0 :             *opp = obj_link(op);
     606           0 :             obj_link(op) = 0;
     607           0 :             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
     608           0 :             UNLOCK();
     609             :         }
     610           0 :         ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     611             :    } else {
     612           0 :        op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
     613           0 :        if (op != NULL) {
     614           0 :             lg = BYTES_TO_GRANULES(GC_size(op));
     615           0 :             ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     616             :        }
     617             :    }
     618           0 :    return((void *) op);
     619             : }
     620             : 
     621             : GC_API GC_ATTR_MALLOC void * GC_CALL
     622           0 :     GC_malloc_explicitly_typed_ignore_off_page(size_t lb, GC_descr d)
     623             : {
     624             :     ptr_t op;
     625             :     ptr_t * opp;
     626             :     size_t lg;
     627             :     DCL_LOCK_STATE;
     628             : 
     629           0 :     lb += TYPD_EXTRA_BYTES;
     630           0 :     if( SMALL_OBJ(lb) ) {
     631             :         GC_DBG_COLLECT_AT_MALLOC(lb);
     632           0 :         lg = GC_size_map[lb];
     633           0 :         opp = &(GC_eobjfreelist[lg]);
     634           0 :         LOCK();
     635           0 :         op = *opp;
     636           0 :         if (EXPECT(0 == op, FALSE)) {
     637           0 :             UNLOCK();
     638           0 :             op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
     639           0 :             if (0 == op) return 0;
     640           0 :             lg = GC_size_map[lb];       /* May have been uninitialized. */
     641             :         } else {
     642           0 :             *opp = obj_link(op);
     643           0 :             obj_link(op) = 0;
     644           0 :             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
     645           0 :             UNLOCK();
     646             :         }
     647           0 :         ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     648             :    } else {
     649           0 :        op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
     650           0 :        if (op != NULL) {
     651           0 :          lg = BYTES_TO_GRANULES(GC_size(op));
     652           0 :          ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
     653             :        }
     654             :    }
     655           0 :    return((void *) op);
     656             : }
     657             : 
     658           0 : GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_explicitly_typed(size_t n,
     659             :                                                         size_t lb, GC_descr d)
     660             : {
     661             :     ptr_t op;
     662             :     ptr_t * opp;
     663             :     size_t lg;
     664             :     GC_descr simple_descr;
     665             :     complex_descriptor *complex_descr;
     666             :     register int descr_type;
     667             :     struct LeafDescriptor leaf;
     668             :     DCL_LOCK_STATE;
     669             : 
     670           0 :     descr_type = GC_make_array_descriptor((word)n, (word)lb, d,
     671             :                                           &simple_descr, &complex_descr, &leaf);
     672           0 :     switch(descr_type) {
     673           0 :         case NO_MEM: return(0);
     674           0 :         case SIMPLE: return(GC_malloc_explicitly_typed(n*lb, simple_descr));
     675             :         case LEAF:
     676           0 :             lb *= n;
     677           0 :             lb += sizeof(struct LeafDescriptor) + TYPD_EXTRA_BYTES;
     678           0 :             break;
     679             :         case COMPLEX:
     680           0 :             lb *= n;
     681           0 :             lb += TYPD_EXTRA_BYTES;
     682             :             break;
     683             :     }
     684           0 :     if( SMALL_OBJ(lb) ) {
     685           0 :         lg = GC_size_map[lb];
     686           0 :         opp = &(GC_arobjfreelist[lg]);
     687           0 :         LOCK();
     688           0 :         op = *opp;
     689           0 :         if (EXPECT(0 == op, FALSE)) {
     690           0 :             UNLOCK();
     691           0 :             op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind);
     692           0 :             if (0 == op) return(0);
     693           0 :             lg = GC_size_map[lb];       /* May have been uninitialized. */
     694             :         } else {
     695           0 :             *opp = obj_link(op);
     696           0 :             obj_link(op) = 0;
     697           0 :             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
     698           0 :             UNLOCK();
     699             :         }
     700             :    } else {
     701           0 :        op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind);
     702           0 :        if (0 == op) return(0);
     703           0 :        lg = BYTES_TO_GRANULES(GC_size(op));
     704             :    }
     705           0 :    if (descr_type == LEAF) {
     706             :        /* Set up the descriptor inside the object itself. */
     707             :        volatile struct LeafDescriptor * lp =
     708             :            (struct LeafDescriptor *)
     709             :                ((word *)op
     710           0 :                 + GRANULES_TO_WORDS(lg)
     711           0 :                 - (BYTES_TO_WORDS(sizeof(struct LeafDescriptor)) + 1));
     712             : 
     713           0 :        lp -> ld_tag = LEAF_TAG;
     714           0 :        lp -> ld_size = leaf.ld_size;
     715           0 :        lp -> ld_nelements = leaf.ld_nelements;
     716           0 :        lp -> ld_descriptor = leaf.ld_descriptor;
     717           0 :        ((volatile word *)op)[GRANULES_TO_WORDS(lg) - 1] = (word)lp;
     718             :    } else {
     719             : #    ifndef GC_NO_FINALIZATION
     720           0 :        size_t lw = GRANULES_TO_WORDS(lg);
     721             : 
     722           0 :        ((word *)op)[lw - 1] = (word)complex_descr;
     723             :        /* Make sure the descriptor is cleared once there is any danger  */
     724             :        /* it may have been collected.                                   */
     725           0 :        if (GC_general_register_disappearing_link((void * *)((word *)op+lw-1),
     726             :                                                  op) == GC_NO_MEMORY)
     727             : #    endif
     728             :        {
     729             :            /* Couldn't register it due to lack of memory.  Punt.        */
     730             :            /* This will probably fail too, but gives the recovery code  */
     731             :            /* a chance.                                                 */
     732           0 :            return(GC_malloc(n*lb));
     733             :        }
     734             :    }
     735           0 :    return((void *) op);
     736             : }

Generated by: LCOV version 1.11