Back to index

plt-scheme  4.2.1
Defines | Functions | Variables
mark.c File Reference
#include <stdio.h>
#include "private/gc_pmark.h"

Go to the source code of this file.

Defines

#define INITIAL_MARK_STACK_SIZE   (1*HBLKSIZE)
#define PROF(n)
#define SPLIT_RANGE_WORDS   128 /* Must be power of 2. */
#define PREF_DIST   4
#define GC_PUSH_ALL(b, t)   GC_push_all(b,t);
#define BASE(p)   (word)GC_base((char *)(p))
#define source   0
#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_least_plausible_heap_addr   least_ha
#define GC_mark_stack_top   mark_stack_top
#define GC_mark_stack_limit   mark_stack_limit
#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_least_plausible_heap_addr   least_ha
#define GC_mark_stack_top   mark_stack_top
#define GC_mark_stack_limit   mark_stack_limit
#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_least_plausible_heap_addr   least_ha
#define GC_mark_stack_top   mark_stack_top
#define GC_mark_stack_limit   mark_stack_limit
#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_least_plausible_heap_addr   least_ha

Functions

void GC_noop ()
void GC_noop1 (word x)
GC_bool GC_collection_in_progress ()
void GC_clear_hdr_marks (hdr *hhdr)
void GC_set_hdr_marks (hdr *hhdr)
static void clear_marks_for_block (struct hblk *h, word dummy)
void GC_set_mark_bit (ptr_t p)
void GC_clear_mark_bit (ptr_t p)
GC_bool GC_is_marked (ptr_t p)
void GC_clear_marks ()
void GC_initiate_gc ()
static void alloc_mark_stack ()
GC_bool GC_mark_some (ptr_t cold_gc_frame)
GC_bool GC_mark_stack_empty ()
ptr_t GC_find_start (ptr_t current, hdr *hhdr, hdr **new_hdr_p)
void GC_invalidate_mark_state ()
mseGC_signal_mark_stack_overflow (mse *msp)
int GC_did_mark_stack_overflow (void)
void GC_mark_from_mark_stack (void)
void GC_mark_overflow_recover (void *p)
mseGC_mark_from (mse *mark_stack_top, mse *mark_stack, mse *mark_stack_limit)
static void alloc_mark_stack (word n)
void GC_mark_init ()
void GC_push_all (ptr_t bottom, ptr_t top)
void GC_push_selected (ptr_t bottom, ptr_t top, dirty_fn, void *push_fn)
void GC_push_conditional (ptr_t bottom, ptr_t top, int all)
void GC_push_one (word p)
struct GC_ms_entryGC_mark_and_push (GC_PTR obj, struct GC_ms_entry *mark_stack_ptr, struct GC_ms_entry *mark_stack_limit, GC_PTR *src)
void GC_mark_and_push_stack (word p)
void GC_push_all_eager (ptr_t bottom, ptr_t top)
void GC_push_all_stack_partially_eager (ptr_t bottom, ptr_t top, ptr_t cold_gc_frame)
void GC_push_all_stack (ptr_t bottom, ptr_t top)
void GC_push_marked1 (struct hblk *h, hdr *hhdr)
void GC_push_marked2 (struct hblk *h, hdr *hhdr)
void GC_push_marked4 (struct hblk *h, hdr *hhdr)
void GC_push_marked (struct hblk *h, hdr *hhdr)
GC_bool GC_block_was_dirty (struct hblk *h, hdr *hhdr)
struct hblkGC_push_next_marked (struct hblk *h)
struct hblkGC_push_next_marked_dirty (struct hblk *h)
struct hblkGC_push_next_marked_uncollectable (struct hblk *h)

Variables

word GC_n_mark_procs = GC_RESERVED_MARK_PROCS
int GC_n_kinds = 3
word GC_n_rescuing_pages
mseGC_mark_stack
mseGC_mark_stack_limit
word GC_mark_stack_size = 0
mseGC_mark_stack_top
static struct hblkscan_ptr
mark_state_t GC_mark_state = MS_NONE
GC_bool GC_mark_stack_too_small = FALSE
GC_bool GC_objects_are_marked = FALSE

Define Documentation

#define BASE (   p)    (word)GC_base((char *)(p))

Definition at line 1345 of file mark.c.

#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_greatest_plausible_heap_addr   greatest_ha
#define GC_least_plausible_heap_addr   least_ha
#define GC_least_plausible_heap_addr   least_ha
#define GC_least_plausible_heap_addr   least_ha
#define GC_least_plausible_heap_addr   least_ha
#define GC_mark_stack_limit   mark_stack_limit
#define GC_mark_stack_limit   mark_stack_limit
#define GC_mark_stack_limit   mark_stack_limit
#define GC_mark_stack_top   mark_stack_top
#define GC_mark_stack_top   mark_stack_top
#define GC_mark_stack_top   mark_stack_top
#define GC_PUSH_ALL (   b,
 
)    GC_push_all(b,t);

Definition at line 1294 of file mark.c.

Definition at line 87 of file mark.c.

#define PREF_DIST   4
#define PROF (   n)

Definition at line 537 of file mark.c.

#define source   0
#define SPLIT_RANGE_WORDS   128 /* Must be power of 2. */

Function Documentation

static void alloc_mark_stack ( ) [static]

Here is the caller graph for this function:

static void alloc_mark_stack ( word  n) [static]

Definition at line 1150 of file mark.c.

{
    mse * new_stack = (mse *)GC_scratch_alloc(n * sizeof(struct GC_ms_entry));
    
    GC_mark_stack_too_small = FALSE;
    if (GC_mark_stack_size != 0) {
        if (new_stack != 0) {
          word displ = (word)GC_mark_stack & (GC_page_size - 1);
          signed_word size = GC_mark_stack_size * sizeof(struct GC_ms_entry);
          
          /* Recycle old space */
             if (0 != displ) displ = GC_page_size - displ;
             size = (size - displ) & ~(GC_page_size - 1);
             if (size > 0) {
               GC_add_to_heap((struct hblk *)
                            ((word)GC_mark_stack + displ), (word)size);
             }
          GC_mark_stack = new_stack;
          GC_mark_stack_size = n;
         GC_mark_stack_limit = new_stack + n;
#        ifdef CONDPRINT
           if (GC_print_stats) {
             GC_printf1("Grew mark stack to %lu frames\n",
                      (unsigned long) GC_mark_stack_size);
           }
#        endif
        } else {
#        ifdef CONDPRINT
           if (GC_print_stats) {
             GC_printf1("Failed to grow mark stack to %lu frames\n",
                      (unsigned long) n);
           }
#        endif
        }
    } else {
        if (new_stack == 0) {
            GC_err_printf0("No space for mark stack\n");
            EXIT();
        }
        GC_mark_stack = new_stack;
        GC_mark_stack_size = n;
       GC_mark_stack_limit = new_stack + n;
    }
    GC_mark_stack_top = GC_mark_stack-1;
}

Here is the call graph for this function:

static void clear_marks_for_block ( struct hblk h,
word  dummy 
) [static]

Definition at line 167 of file mark.c.

{
    register hdr * hhdr = HDR(h);
    
    if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) return;
        /* Mark bit for these is cleared only once the object is      */
        /* explicitly deallocated.  This either frees the block, or   */
        /* the bit is cleared once the object is on the free list.    */
    GC_clear_hdr_marks(hhdr);
}

Here is the call graph for this function:

Here is the caller graph for this function:

GC_bool GC_block_was_dirty ( struct hblk h,
hdr hhdr 
)

Definition at line 1750 of file mark.c.

{
    register int sz = hhdr -> hb_sz;
    
    if (sz <= MAXOBJSZ) {
         return(GC_page_was_dirty(h));
    } else {
        register ptr_t p = (ptr_t)h;
         sz = WORDS_TO_BYTES(sz);
         while (p < (ptr_t)h + sz) {
             if (GC_page_was_dirty((struct hblk *)p)) return(TRUE);
             p += HBLKSIZE;
         }
         return(FALSE);
    }
}

Here is the caller graph for this function:

Definition at line 135 of file mark.c.

{
#   ifdef USE_MARK_BYTES
      BZERO(hhdr -> hb_marks, MARK_BITS_SZ);
#   else
      BZERO(hhdr -> hb_marks, MARK_BITS_SZ*sizeof(word));
#   endif
}

Here is the caller graph for this function:

Definition at line 192 of file mark.c.

{
    register struct hblk *h = HBLKPTR(p);
    register hdr * hhdr = HDR(h);
    register int word_no = (word *)p - (word *)h;
    
    clear_mark_bit_from_hdr(hhdr, word_no);
}

Here is the caller graph for this function:

Definition at line 218 of file mark.c.

{
    GC_apply_to_all_blocks(clear_marks_for_block, (word)0);
    GC_objects_are_marked = FALSE;
    GC_mark_state = MS_INVALID;
    scan_ptr = 0;
#   ifdef GATHERSTATS
       /* Counters reflect currently marked objects: reset here */
        GC_composite_in_use = 0;
        GC_atomic_in_use = 0;
#   endif

}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 129 of file mark.c.

{
    return(GC_mark_state != MS_NONE);
}

Here is the caller graph for this function:

Definition at line 599 of file mark.c.

{
  return GC_mark_state == MS_INVALID;
}

Here is the caller graph for this function:

ptr_t GC_find_start ( ptr_t  current,
hdr hhdr,
hdr **  new_hdr_p 
)

Definition at line 548 of file mark.c.

{
    if (GC_all_interior_pointers) {
       if (hhdr != 0) {
           register ptr_t orig = current;
           
           current = (ptr_t)HBLKPTR(current);
           do {
             current = current - HBLKSIZE*(word)hhdr;
             hhdr = HDR(current);
           } while(IS_FORWARDING_ADDR_OR_NIL(hhdr));
           /* current points to near the start of the large object */
           if (hhdr -> hb_flags & IGNORE_OFF_PAGE) return(orig);
           if ((word *)orig - (word *)current
                >= (ptrdiff_t)(hhdr->hb_sz)) {
               /* Pointer past the end of the block */
               return(orig);
           }
           *new_hdr_p = hhdr;
           return(current);
       } else {
           return(current);
        }
    } else {
        return(current);
    }
}

Definition at line 235 of file mark.c.

{
    if (GC_dirty_maintained) GC_read_dirty();
#   ifdef STUBBORN_ALLOC
       GC_read_changed();
#   endif
#   ifdef CHECKSUMS
       {
           extern void GC_check_dirty();
           
           if (GC_dirty_maintained) GC_check_dirty();
       }
#   endif
    GC_n_rescuing_pages = 0;
    if (GC_mark_state == MS_NONE) {
        GC_mark_state = MS_PUSH_RESCUERS;
    } else if (GC_mark_state != MS_INVALID) {
       ABORT("unexpected state");
    } /* else this is really a full collection, and mark       */
      /* bits are invalid.                              */
    scan_ptr = 0;
}

Here is the caller graph for this function:

Definition at line 578 of file mark.c.

Here is the caller graph for this function:

Definition at line 202 of file mark.c.

{
    register struct hblk *h = HBLKPTR(p);
    register hdr * hhdr = HDR(h);
    register int word_no = (word *)p - (word *)h;
    
    return(mark_bit_from_hdr(hhdr, word_no));
}

Here is the caller graph for this function:

struct GC_ms_entry* GC_mark_and_push ( GC_PTR  obj,
struct GC_ms_entry mark_stack_ptr,
struct GC_ms_entry mark_stack_limit,
GC_PTR src 
) [read]

Definition at line 1330 of file mark.c.

{
   PREFETCH(obj);
   PUSH_CONTENTS(obj, mark_stack_ptr /* modified */, mark_stack_limit, src,
               was_marked /* internally generated exit label */);
   return mark_stack_ptr;
}

Definition at line 1359 of file mark.c.

{
    register word r;
    register hdr * hhdr; 
    register int displ;
  
    GET_HDR(p, hhdr);
    if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
        if (hhdr != 0) {
          r = BASE(p);
         hhdr = HDR(r);
         displ = BYTES_TO_WORDS(HBLKDISPL(r));
       }
    } else {
        register map_entry_type map_entry;
        
        displ = HBLKDISPL(p);
        map_entry = MAP_ENTRY((hhdr -> hb_map), displ);
        if (map_entry >= MAX_OFFSET) {
          if (map_entry == OFFSET_TOO_BIG || !GC_all_interior_pointers) {
              r = BASE(p);
             displ = BYTES_TO_WORDS(HBLKDISPL(r));
             if (r == 0) hhdr = 0;
          } else {
             /* Offset invalid, but map reflects interior pointers    */
              hhdr = 0;
          }
        } else {
          displ = BYTES_TO_WORDS(displ);
          displ -= map_entry;
          r = (word)((word *)(HBLKPTR(p)) + displ);
        }
    }
    /* If hhdr != 0 then r == GC_base(p), only we did it faster. */
    /* displ is the word index within the block.         */
    if (hhdr == 0) {
#      ifdef PRINT_BLACK_LIST
         GC_add_to_black_list_stack(p, source);
#      else
         GC_add_to_black_list_stack(p);
#      endif
#      undef source  /* In case we had to define it. */
    } else {
       if (!mark_bit_from_hdr(hhdr, displ)) {
           set_mark_bit_from_hdr(hhdr, displ);
           GC_STORE_BACK_PTR(source, (ptr_t)r);
           PUSH_OBJ((word *)r, hhdr, GC_mark_stack_top,
                    GC_mark_stack_limit);
       }
    }
}

Here is the call graph for this function:

mse* GC_mark_from ( mse mark_stack_top,
mse mark_stack,
mse mark_stack_limit 
)

Definition at line 627 of file mark.c.

{
  int credit = HBLKSIZE;    /* Remaining credit for marking work      */
  register word * current_p;       /* Pointer to current candidate ptr.      */
  register word current;    /* Candidate pointer.                     */
  register word * limit;    /* (Incl) limit of current candidate      */
                            /* range                           */
  register word descr;
  register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
  register ptr_t least_ha = GC_least_plausible_heap_addr;
  DECLARE_HDR_CACHE;

# define SPLIT_RANGE_WORDS 128  /* Must be power of 2.         */

  GC_objects_are_marked = TRUE;
  INIT_HDR_CACHE;
# ifdef OS2 /* Use untweaked version to circumvent compiler problem */
  while (mark_stack_top >= mark_stack && credit >= 0) {
# else
  while ((((ptr_t)mark_stack_top - (ptr_t)mark_stack) | credit)
       >= 0) {
# endif
    current_p = mark_stack_top -> mse_start;
    descr = mark_stack_top -> mse_descr;
  retry:
    /* current_p and descr describe the current object.        */
    /* *mark_stack_top is vacant.                       */
    /* The following is 0 only for small objects described by a simple       */
    /* length descriptor.  For many applications this is the common   */
    /* case, so we try to detect it quickly.                          */
    if (descr & ((~(WORDS_TO_BYTES(SPLIT_RANGE_WORDS) - 1)) | GC_DS_TAGS)) {
      word tag = descr & GC_DS_TAGS;
      
      switch(tag) {
        case GC_DS_LENGTH:
          /* Large length.                                      */
          /* Process part of the range to avoid pushing too much on the      */
          /* stack.                                            */
         GC_ASSERT(descr < (word)GC_greatest_plausible_heap_addr
                         - (word)GC_least_plausible_heap_addr);
#        ifdef PARALLEL_MARK
#          define SHARE_BYTES 2048
           if (descr > SHARE_BYTES && GC_parallel
              && mark_stack_top < mark_stack_limit - 1) {
             int new_size = (descr/2) & ~(sizeof(word)-1);
             mark_stack_top -> mse_start = current_p;
             mark_stack_top -> mse_descr = new_size + sizeof(word);
                                   /* makes sure we handle     */
                                   /* misaligned pointers.            */
             mark_stack_top++;
             current_p = (word *) ((char *)current_p + new_size);
             descr -= new_size;
             goto retry;
           }
#        endif /* PARALLEL_MARK */
          mark_stack_top -> mse_start =
              limit = current_p + SPLIT_RANGE_WORDS-1;
          mark_stack_top -> mse_descr =
                     descr - WORDS_TO_BYTES(SPLIT_RANGE_WORDS-1);
          /* Make sure that pointers overlapping the two ranges are   */
          /* considered.                                       */
          limit = (word *)((char *)limit + sizeof(word) - ALIGNMENT);
          break;
        case GC_DS_BITMAP:
          mark_stack_top--;
          descr &= ~GC_DS_TAGS;
          credit -= WORDS_TO_BYTES(WORDSZ/2); /* guess */
          while (descr != 0) {
            if ((signed_word)descr < 0) {
              current = *current_p;
             FIXUP_POINTER(current);
             if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {
              PREFETCH((ptr_t)current);
                HC_PUSH_CONTENTS((ptr_t)current, mark_stack_top,
                           mark_stack_limit, current_p, exit1);
             }
            }
           descr <<= 1;
           ++ current_p;
          }
          continue;
        case GC_DS_PROC:
          mark_stack_top--;
          credit -= GC_PROC_BYTES;
          mark_stack_top =
              (*PROC(descr))
                         (current_p, mark_stack_top,
                         mark_stack_limit, ENV(descr));
          continue;
        case GC_DS_PER_OBJECT:
         if ((signed_word)descr >= 0) {
           /* Descriptor is in the object.       */
            descr = *(word *)((ptr_t)current_p + descr - GC_DS_PER_OBJECT);
         } else {
           /* Descriptor is in type descriptor pointed to by first    */
           /* word in object.                                         */
           ptr_t type_descr = *(ptr_t *)current_p;
           /* type_descr is either a valid pointer to the descriptor  */
           /* structure, or this object was on a free list.  If it    */
           /* it was anything but the last object on the free list,   */
           /* we will misinterpret the next object on the free list as */
           /* the type descriptor, and get a 0 GC descriptor, which   */
           /* is ideal.  Unfortunately, we need to check for the last */
           /* object case explicitly.                                 */
           if (0 == type_descr) {
              /* Rarely executed.  */
              mark_stack_top--;
              continue;
           }
            descr = *(word *)(type_descr
                           - (descr - (GC_DS_PER_OBJECT
                                     - GC_INDIR_PER_OBJ_BIAS)));
         }
         if (0 == descr) {
             /* Can happen either because we generated a 0 descriptor */
             /* or we saw a pointer to a free object.                 */
             mark_stack_top--;
             continue;
         }
          goto retry;
      }
    } else /* Small object with length descriptor */ {
      mark_stack_top--;
      limit = (word *)(((ptr_t)current_p) + (word)descr);
    }
    /* The simple case in which we're scanning a range. */
    GC_ASSERT(!((word)current_p & (ALIGNMENT-1)));
    credit -= (ptr_t)limit - (ptr_t)current_p;
    limit -= 1;
    {
#     define PREF_DIST 4

#     ifndef SMALL_CONFIG
        word deferred;

       /* Try to prefetch the next pointer to be examined asap.       */
       /* Empirically, this also seems to help slightly without       */
       /* prefetches, at least on linux/X86.  Presumably this loop    */
       /* ends up with less register pressure, and gcc thus ends up   */
       /* generating slightly better code.  Overall gcc code quality  */
       /* for this loop is still not great.                           */
       for(;;) {
         PREFETCH((ptr_t)limit - PREF_DIST*CACHE_LINE_SIZE);
         GC_ASSERT(limit >= current_p);
         deferred = *limit;
         FIXUP_POINTER(deferred);
         limit = (word *)((char *)limit - ALIGNMENT);
         if ((ptr_t)deferred >= least_ha && (ptr_t)deferred <  greatest_ha) {
           PREFETCH((ptr_t)deferred);
           break;
         }
         if (current_p > limit) goto next_object;
         /* Unroll once, so we don't do too many of the prefetches    */
         /* based on limit.                                    */
         deferred = *limit;
         FIXUP_POINTER(deferred);
         limit = (word *)((char *)limit - ALIGNMENT);
         if ((ptr_t)deferred >= least_ha && (ptr_t)deferred <  greatest_ha) {
           PREFETCH((ptr_t)deferred);
           break;
         }
         if (current_p > limit) goto next_object;
       }
#     endif

      while (current_p <= limit) {
       /* Empirically, unrolling this loop doesn't help a lot. */
       /* Since HC_PUSH_CONTENTS expands to a lot of code,     */
       /* we don't.                                     */
        current = *current_p;
       FIXUP_POINTER(current);
        PREFETCH((ptr_t)current_p + PREF_DIST*CACHE_LINE_SIZE);
        if ((ptr_t)current >= least_ha && (ptr_t)current <  greatest_ha) {
         /* Prefetch the contents of the object we just pushed.  It's */
         /* likely we will need them soon.                            */
         PREFETCH((ptr_t)current);
          HC_PUSH_CONTENTS((ptr_t)current, mark_stack_top,
                         mark_stack_limit, current_p, exit2);
        }
        current_p = (word *)((char *)current_p + ALIGNMENT);
      }

#     ifndef SMALL_CONFIG
       /* We still need to mark the entry we previously prefetched.   */
       /* We alrady know that it passes the preliminary pointer       */
       /* validity test.                                       */
        HC_PUSH_CONTENTS((ptr_t)deferred, mark_stack_top,
                       mark_stack_limit, current_p, exit4);
       next_object:;
#     endif
    }
  }
  return mark_stack_top;
}

Here is the call graph for this function:

Definition at line 603 of file mark.c.

Here is the caller graph for this function:

Definition at line 1197 of file mark.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 607 of file mark.c.

{
  GC_set_mark_bit(p);
  while (!GC_mark_some((ptr_t)0));
}

Here is the call graph for this function:

Here is the caller graph for this function:

GC_bool GC_mark_some ( ptr_t  cold_gc_frame)

Definition at line 278 of file mark.c.

{
    switch(GC_mark_state) {
       case MS_NONE:
           return(FALSE);
           
       case MS_PUSH_RESCUERS:
           if (GC_mark_stack_top
               >= GC_mark_stack_limit - INITIAL_MARK_STACK_SIZE/2) {
              /* Go ahead and mark, even though that might cause us to */
              /* see more marked dirty objects later on.  Avoid this   */
              /* in the future.                                 */
              GC_mark_stack_too_small = TRUE;
               MARK_FROM_MARK_STACK();
               return(FALSE);
           } else {
               scan_ptr = GC_push_next_marked_dirty(scan_ptr);
               if (scan_ptr == 0) {
#                 ifdef CONDPRINT
                    if (GC_print_stats) {
                     GC_printf1("Marked from %lu dirty pages\n",
                               (unsigned long)GC_n_rescuing_pages);
                    }
#                 endif
                  GC_push_roots(FALSE, cold_gc_frame);
                  GC_objects_are_marked = TRUE;
                  if (GC_mark_state != MS_INVALID) {
                      GC_mark_state = MS_ROOTS_PUSHED;
                  }
              }
           }
           return(FALSE);
       
       case MS_PUSH_UNCOLLECTABLE:
           if (GC_mark_stack_top
               >= GC_mark_stack + GC_mark_stack_size/4) {
#             ifdef PARALLEL_MARK
                /* Avoid this, since we don't parallelize the marker  */
                /* here.                                       */
                if (GC_parallel) GC_mark_stack_too_small = TRUE;
#             endif
               MARK_FROM_MARK_STACK();
               return(FALSE);
           } else {
               scan_ptr = GC_push_next_marked_uncollectable(scan_ptr);
               if (scan_ptr == 0) {
                  GC_push_roots(TRUE, cold_gc_frame);
                  GC_objects_are_marked = TRUE;
                  if (GC_mark_state != MS_INVALID) {
                      GC_mark_state = MS_ROOTS_PUSHED;
                  }
              }
           }
           return(FALSE);
       
       case MS_ROOTS_PUSHED:
#          ifdef PARALLEL_MARK
             /* In the incremental GC case, this currently doesn't    */
             /* quite do the right thing, since it runs to            */
             /* completion.  On the other hand, starting a            */
             /* parallel marker is expensive, so perhaps it is        */
             /* the right thing?                               */
             /* Eventually, incremental marking should run            */
             /* asynchronously in multiple threads, without grabbing  */
             /* the allocation lock.                                  */
               if (GC_parallel) {
                GC_do_parallel_mark();
                GC_ASSERT(GC_mark_stack_top < GC_first_nonempty);
                GC_mark_stack_top = GC_mark_stack - 1;
                 if (GC_mark_stack_too_small) {
                   alloc_mark_stack(2*GC_mark_stack_size);
                 }
                if (GC_mark_state == MS_ROOTS_PUSHED) {
                   GC_mark_state = MS_NONE;
                   return(TRUE);
                } else {
                  return(FALSE);
                 }
              }
#          endif
           if (GC_mark_stack_top >= GC_mark_stack) {
               MARK_FROM_MARK_STACK();
               return(FALSE);
           } else {
               GC_mark_state = MS_NONE;
               if (GC_mark_stack_too_small) {
                   alloc_mark_stack(2*GC_mark_stack_size);
               }
               return(TRUE);
           }
           
       case MS_INVALID:
       case MS_PARTIALLY_INVALID:
           if (!GC_objects_are_marked) {
              GC_mark_state = MS_PUSH_UNCOLLECTABLE;
              return(FALSE);
           }
           if (GC_mark_stack_top >= GC_mark_stack) {
               MARK_FROM_MARK_STACK();
               return(FALSE);
           }
           if (scan_ptr == 0 && GC_mark_state == MS_INVALID) {
              /* About to start a heap scan for marked objects. */
              /* Mark stack is empty.  OK to reallocate.         */
              if (GC_mark_stack_too_small) {
                   alloc_mark_stack(2*GC_mark_stack_size);
              }
              GC_mark_state = MS_PARTIALLY_INVALID;
           }
           scan_ptr = GC_push_next_marked(scan_ptr);
           if (scan_ptr == 0 && GC_mark_state == MS_PARTIALLY_INVALID) {
              GC_push_roots(TRUE, cold_gc_frame);
              GC_objects_are_marked = TRUE;
              if (GC_mark_state != MS_INVALID) {
                  GC_mark_state = MS_ROOTS_PUSHED;
              }
           }
           return(FALSE);
       default:
           ABORT("GC_mark_some: bad state");
           return(FALSE);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 528 of file mark.c.

{
    return(GC_mark_stack_top < GC_mark_stack);
}      

Here is the caller graph for this function:

Definition at line 31 of file mark.c.

{}

Here is the caller graph for this function:

void GC_noop1 ( word  x)

Definition at line 35 of file mark.c.

{
    static VOLATILE word sink;

    sink = x;
}

Here is the caller graph for this function:

void GC_push_all ( ptr_t  bottom,
ptr_t  top 
)

Definition at line 1209 of file mark.c.

{
    register word length;
    
    bottom = (ptr_t)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
    top = (ptr_t)(((word) top) & ~(ALIGNMENT-1));
    if (top == 0 || bottom == top) return;
    GC_mark_stack_top++;
    if (GC_mark_stack_top >= GC_mark_stack_limit) {
       ABORT("unexpected mark stack overflow");
    }
    length = top - bottom;
#   if GC_DS_TAGS > ALIGNMENT - 1
       length += GC_DS_TAGS;
       length &= ~GC_DS_TAGS;
#   endif
    GC_mark_stack_top -> mse_start = (word *)bottom;
    GC_mark_stack_top -> mse_descr = length;
}

Here is the caller graph for this function:

void GC_push_all_eager ( ptr_t  bottom,
ptr_t  top 
)

Definition at line 1464 of file mark.c.

{
    word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
    word * t = (word *)(((word) top) & ~(ALIGNMENT-1));
    register word *p;
    register word q;
    register word *lim;
    register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
    register ptr_t least_ha = GC_least_plausible_heap_addr;
#   define GC_greatest_plausible_heap_addr greatest_ha
#   define GC_least_plausible_heap_addr least_ha

    if (top == 0) return;
    /* check all pointers in range and push if they appear     */
    /* to be valid.                                     */
      lim = t - 1 /* longword */;
      for (p = b; p <= lim; p = (word *)(((char *)p) + ALIGNMENT)) {
       q = *p;
       GC_PUSH_ONE_STACK(q, p);
      }
#   undef GC_greatest_plausible_heap_addr
#   undef GC_least_plausible_heap_addr
}

Here is the caller graph for this function:

void GC_push_all_stack ( ptr_t  bottom,
ptr_t  top 
)

Definition at line 1528 of file mark.c.

{
  if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
    GC_push_all(bottom, top);
  } else {
    GC_push_all_eager(bottom, top);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void GC_push_all_stack_partially_eager ( ptr_t  bottom,
ptr_t  top,
ptr_t  cold_gc_frame 
)

Definition at line 1498 of file mark.c.

{
  if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
    /* Push the hot end of the stack eagerly, so that register values   */
    /* saved inside GC frames are marked before they disappear.              */
    /* The rest of the marking can be deferred until later.           */
    if (0 == cold_gc_frame) {
       GC_push_all_stack(bottom, top);
       return;
    }
    GC_ASSERT(bottom <= cold_gc_frame && cold_gc_frame <= top);
#   ifdef STACK_GROWS_DOWN
       GC_push_all(cold_gc_frame - sizeof(ptr_t), top);
       GC_push_all_eager(bottom, cold_gc_frame);
#   else /* STACK_GROWS_UP */
       GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t));
       GC_push_all_eager(cold_gc_frame, top);
#   endif /* STACK_GROWS_UP */
  } else {
    GC_push_all_eager(bottom, top);
  }
# ifdef TRACE_BUF
      GC_add_trace_entry("GC_push_all_stack", bottom, top);
# endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

void GC_push_conditional ( ptr_t  bottom,
ptr_t  top,
int  all 
)

Definition at line 1298 of file mark.c.

{
    if (all) {
      if (GC_dirty_maintained) {
#      ifdef PROC_VDB
           /* Pages that were never dirtied cannot contain pointers   */
           GC_push_selected(bottom, top, GC_page_was_ever_dirty, GC_push_all);
#      else
           GC_push_all(bottom, top);
#      endif
      } else {
       GC_push_all(bottom, top);
      }
    } else {
       GC_push_selected(bottom, top, GC_page_was_dirty, GC_push_all);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void GC_push_marked ( struct hblk h,
hdr hhdr 
)

Definition at line 1693 of file mark.c.

{
    register int sz = hhdr -> hb_sz;
    register int descr = hhdr -> hb_descr;
    register word * p;
    register int word_no;
    register word * lim;
    register mse * GC_mark_stack_top_reg;
    register mse * mark_stack_limit = GC_mark_stack_limit;
    
    /* Some quick shortcuts: */
       if ((0 | GC_DS_LENGTH) == descr) return;
        if (GC_block_empty(hhdr)/* nothing marked */) return;
    GC_n_rescuing_pages++;
    GC_objects_are_marked = TRUE;
    if (sz > MAXOBJSZ) {
        lim = (word *)h;
    } else {
        lim = (word *)(h + 1) - sz;
    }
    
    switch(sz) {
#   if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)   
     case 1:
       GC_push_marked1(h, hhdr);
       break;
#   endif
#   if !defined(SMALL_CONFIG) && !defined(UNALIGNED) && \
       !defined(USE_MARK_BYTES)
     case 2:
       GC_push_marked2(h, hhdr);
       break;
     case 4:
       GC_push_marked4(h, hhdr);
       break;
#   endif       
     default:
      GC_mark_stack_top_reg = GC_mark_stack_top;
      for (p = (word *)h, word_no = 0; p <= lim; p += sz, word_no += sz) {
         if (mark_bit_from_hdr(hhdr, word_no)) {
           /* Mark from fields inside the object */
             PUSH_OBJ((word *)p, hhdr, GC_mark_stack_top_reg, mark_stack_limit);
#           ifdef GATHERSTATS
              /* Subtract this object from total, since it was */
              /* added in twice.                               */
              GC_composite_in_use -= sz;
#           endif
         }
      }
      GC_mark_stack_top = GC_mark_stack_top_reg;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void GC_push_marked1 ( struct hblk h,
hdr hhdr 
)

Definition at line 1542 of file mark.c.

{
    word * mark_word_addr = &(hhdr->hb_marks[0]);
    register word *p;
    word *plim;
    register int i;
    register word q;
    register word mark_word;
    register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
    register ptr_t least_ha = GC_least_plausible_heap_addr;
    register mse * mark_stack_top = GC_mark_stack_top;
    register mse * mark_stack_limit = GC_mark_stack_limit;
#   define GC_mark_stack_top mark_stack_top
#   define GC_mark_stack_limit mark_stack_limit
#   define GC_greatest_plausible_heap_addr greatest_ha
#   define GC_least_plausible_heap_addr least_ha
    
    p = (word *)(h->hb_body);
    plim = (word *)(((word)h) + HBLKSIZE);

    /* go through all words in block */
       while( p < plim )  {
           mark_word = *mark_word_addr++;
           i = 0;
           while(mark_word != 0) {
             if (mark_word & 1) {
                 q = p[i];
                 GC_PUSH_ONE_HEAP(q, p + i);
             }
             i++;
             mark_word >>= 1;
           }
           p += WORDSZ;
       }
#   undef GC_greatest_plausible_heap_addr
#   undef GC_least_plausible_heap_addr        
#   undef GC_mark_stack_top
#   undef GC_mark_stack_limit
    GC_mark_stack_top = mark_stack_top;
}

Here is the caller graph for this function:

void GC_push_marked2 ( struct hblk h,
hdr hhdr 
)

Definition at line 1590 of file mark.c.

{
    word * mark_word_addr = &(hhdr->hb_marks[0]);
    register word *p;
    word *plim;
    register int i;
    register word q;
    register word mark_word;
    register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
    register ptr_t least_ha = GC_least_plausible_heap_addr;
    register mse * mark_stack_top = GC_mark_stack_top;
    register mse * mark_stack_limit = GC_mark_stack_limit;
#   define GC_mark_stack_top mark_stack_top
#   define GC_mark_stack_limit mark_stack_limit
#   define GC_greatest_plausible_heap_addr greatest_ha
#   define GC_least_plausible_heap_addr least_ha
    
    p = (word *)(h->hb_body);
    plim = (word *)(((word)h) + HBLKSIZE);

    /* go through all words in block */
       while( p < plim )  {
           mark_word = *mark_word_addr++;
           i = 0;
           while(mark_word != 0) {
             if (mark_word & 1) {
                 q = p[i];
                 GC_PUSH_ONE_HEAP(q, p + i);
                 q = p[i+1];
                 GC_PUSH_ONE_HEAP(q, p + i);
             }
             i += 2;
             mark_word >>= 2;
           }
           p += WORDSZ;
       }
#   undef GC_greatest_plausible_heap_addr
#   undef GC_least_plausible_heap_addr        
#   undef GC_mark_stack_top
#   undef GC_mark_stack_limit
    GC_mark_stack_top = mark_stack_top;
}

Here is the caller graph for this function:

void GC_push_marked4 ( struct hblk h,
hdr hhdr 
)

Definition at line 1639 of file mark.c.

{
    word * mark_word_addr = &(hhdr->hb_marks[0]);
    register word *p;
    word *plim;
    register int i;
    register word q;
    register word mark_word;
    register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
    register ptr_t least_ha = GC_least_plausible_heap_addr;
    register mse * mark_stack_top = GC_mark_stack_top;
    register mse * mark_stack_limit = GC_mark_stack_limit;
#   define GC_mark_stack_top mark_stack_top
#   define GC_mark_stack_limit mark_stack_limit
#   define GC_greatest_plausible_heap_addr greatest_ha
#   define GC_least_plausible_heap_addr least_ha
    
    p = (word *)(h->hb_body);
    plim = (word *)(((word)h) + HBLKSIZE);

    /* go through all words in block */
       while( p < plim )  {
           mark_word = *mark_word_addr++;
           i = 0;
           while(mark_word != 0) {
             if (mark_word & 1) {
                 q = p[i];
                 GC_PUSH_ONE_HEAP(q, p + i);
                 q = p[i+1];
                 GC_PUSH_ONE_HEAP(q, p + i + 1);
                 q = p[i+2];
                 GC_PUSH_ONE_HEAP(q, p + i + 2);
                 q = p[i+3];
                 GC_PUSH_ONE_HEAP(q, p + i + 3);
             }
             i += 4;
             mark_word >>= 4;
           }
           p += WORDSZ;
       }
#   undef GC_greatest_plausible_heap_addr
#   undef GC_least_plausible_heap_addr        
#   undef GC_mark_stack_top
#   undef GC_mark_stack_limit
    GC_mark_stack_top = mark_stack_top;
}

Here is the caller graph for this function:

Definition at line 1771 of file mark.c.

{
    register hdr * hhdr;
    
    h = GC_next_used_block(h);
    if (h == 0) return(0);
    hhdr = HDR(h);
    GC_push_marked(h, hhdr);
    return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1785 of file mark.c.

{
    register hdr * hhdr;
    
    if (!GC_dirty_maintained) { ABORT("dirty bits not set up"); }
    for (;;) {
        h = GC_next_used_block(h);
        if (h == 0) return(0);
        hhdr = HDR(h);
#      ifdef STUBBORN_ALLOC
          if (hhdr -> hb_obj_kind == STUBBORN) {
            if (GC_page_was_changed(h) && GC_block_was_dirty(h, hhdr)) {
                break;
            }
          } else {
            if (GC_block_was_dirty(h, hhdr)) break;
          }
#      else
         if (GC_block_was_dirty(h, hhdr)) break;
#      endif
        h += OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
    }
    GC_push_marked(h, hhdr);
    return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1815 of file mark.c.

{
    register hdr * hhdr = HDR(h);
    
    for (;;) {
        h = GC_next_used_block(h);
        if (h == 0) return(0);
        hhdr = HDR(h);
       if (hhdr -> hb_obj_kind == UNCOLLECTABLE) break;
        h += OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
    }
    GC_push_marked(h, hhdr);
    return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1323 of file mark.c.

{
    GC_PUSH_ONE_STACK(p, MARKED_FROM_REGISTER);
}

Here is the caller graph for this function:

void GC_push_selected ( ptr_t  bottom,
ptr_t  top,
dirty_fn  ,
void push_fn 
)

Definition at line 1241 of file mark.c.

{
    register struct hblk * h;

    bottom = (ptr_t)(((long) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
    top = (ptr_t)(((long) top) & ~(ALIGNMENT-1));

    if (top == 0 || bottom == top) return;
    h = HBLKPTR(bottom + HBLKSIZE);
    if (top <= (ptr_t) h) {
       if ((*dirty_fn)(h-1)) {
           (*push_fn)(bottom, top);
       }
       return;
    }
    if ((*dirty_fn)(h-1)) {
        (*push_fn)(bottom, (ptr_t)h);
    }
    while ((ptr_t)(h+1) <= top) {
       if ((*dirty_fn)(h)) {
           if ((word)(GC_mark_stack_top - GC_mark_stack)
              > 3 * GC_mark_stack_size / 4) {
              /* Danger of mark stack overflow */
              (*push_fn)((ptr_t)h, top);
              return;
           } else {
              (*push_fn)((ptr_t)h, (ptr_t)(h+1));
           }
       }
       h++;
    }
    if ((ptr_t)h != top) {
       if ((*dirty_fn)(h)) {
            (*push_fn)((ptr_t)h, top);
        }
    }
    if (GC_mark_stack_top >= GC_mark_stack_limit) {
        ABORT("unexpected mark stack overflow");
    }
}

Here is the caller graph for this function:

void GC_set_hdr_marks ( hdr hhdr)

Definition at line 146 of file mark.c.

{
    register int i;

    for (i = 0; i < MARK_BITS_SZ; ++i) {
#     ifdef USE_MARK_BYTES
       hhdr -> hb_marks[i] = 1;
#     else
       hhdr -> hb_marks[i] = ONES;
#     endif
    }
}

Here is the caller graph for this function:

Definition at line 182 of file mark.c.

{
    register struct hblk *h = HBLKPTR(p);
    register hdr * hhdr = HDR(h);
    register int word_no = (word *)p - (word *)h;
    
    set_mark_bit_from_hdr(hhdr, word_no);
}

Here is the caller graph for this function:

Definition at line 584 of file mark.c.

{
    GC_mark_state = MS_INVALID;
    GC_mark_stack_too_small = TRUE;
#   ifdef CONDPRINT
      if (GC_print_stats) {
       GC_printf1("Mark stack overflow; current size = %lu entries\n",
                  GC_mark_stack_size);
      }
#   endif
    return(msp - GC_MARK_STACK_DISCARDS);
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 105 of file mark.c.

Definition at line 107 of file mark.c.

Definition at line 109 of file mark.c.

Definition at line 121 of file mark.c.

Definition at line 114 of file mark.c.

Definition at line 119 of file mark.c.

Definition at line 81 of file mark.c.

Definition at line 45 of file mark.c.

Definition at line 102 of file mark.c.

Definition at line 123 of file mark.c.

struct hblk* scan_ptr [static]

Definition at line 117 of file mark.c.