[BACK]Return to mark.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Diff for /OpenXM_contrib2/asir2000/gc/mark.c between version 1.6 and 1.7

version 1.6, 2002/07/24 08:00:10 version 1.7, 2003/06/24 05:11:33
Line 19 
Line 19 
 # include <stdio.h>  # include <stdio.h>
 # include "private/gc_pmark.h"  # include "private/gc_pmark.h"
   
   #if defined(MSWIN32) && defined(__GNUC__)
   # include <excpt.h>
   #endif
   
 /* We put this here to minimize the risk of inlining. */  /* We put this here to minimize the risk of inlining. */
 /*VARARGS*/  /*VARARGS*/
 #ifdef __WATCOMC__  #ifdef __WATCOMC__
Line 261  static void alloc_mark_stack();
Line 265  static void alloc_mark_stack();
 /* remains valid until all marking is complete.         */  /* remains valid until all marking is complete.         */
 /* A zero value indicates that it's OK to miss some     */  /* A zero value indicates that it's OK to miss some     */
 /* register values.                                     */  /* register values.                                     */
 GC_bool GC_mark_some(cold_gc_frame)  /* We hold the allocation lock.  In the case of         */
 ptr_t cold_gc_frame;  /* incremental collection, the world may not be stopped.*/
   #ifdef MSWIN32
     /* For win32, this is called after we establish a structured  */
     /* exception handler, in case Windows unmaps one of our root  */
     /* segments.  See below.  In either case, we acquire the      */
     /* allocator lock long before we get here.                    */
     GC_bool GC_mark_some_inner(cold_gc_frame)
     ptr_t cold_gc_frame;
   #else
     GC_bool GC_mark_some(cold_gc_frame)
     ptr_t cold_gc_frame;
   #endif
 {  {
 #if defined(MSWIN32) && !defined(__GNUC__)  
   /* Windows 98 appears to asynchronously create and remove writable    */  
   /* memory mappings, for reasons we haven't yet understood.  Since     */  
   /* we look for writable regions to determine the root set, we may     */  
   /* try to mark from an address range that disappeared since we        */  
   /* started the collection.  Thus we have to recover from faults here. */  
   /* This code does not appear to be necessary for Windows 95/NT/2000.  */  
   /* Note that this code should never generate an incremental GC write  */  
   /* fault.                                                             */  
   __try {  
 #endif /* defined(MSWIN32) && !defined(__GNUC__) */  
     switch(GC_mark_state) {      switch(GC_mark_state) {
         case MS_NONE:          case MS_NONE:
             return(FALSE);              return(FALSE);
Line 395  ptr_t cold_gc_frame;
Line 399  ptr_t cold_gc_frame;
             ABORT("GC_mark_some: bad state");              ABORT("GC_mark_some: bad state");
             return(FALSE);              return(FALSE);
     }      }
 #if defined(MSWIN32) && !defined(__GNUC__)  }
   } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?  
             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {  
 #   ifdef CONDPRINT  #ifdef MSWIN32
       if (GC_print_stats) {  
         GC_printf0("Caught ACCESS_VIOLATION in marker. "  # ifdef __GNUC__
                    "Memory mapping disappeared.\n");  
       typedef struct {
         EXCEPTION_REGISTRATION ex_reg;
         void *alt_path;
       } ext_ex_regn;
   
   
       static EXCEPTION_DISPOSITION mark_ex_handler(
           struct _EXCEPTION_RECORD *ex_rec,
           void *est_frame,
           struct _CONTEXT *context,
           void *disp_ctxt)
       {
           if (ex_rec->ExceptionCode == STATUS_ACCESS_VIOLATION) {
             ext_ex_regn *xer = (ext_ex_regn *)est_frame;
   
             /* Unwind from the inner function assuming the standard */
             /* function prologue.                                   */
             /* Assumes code has not been compiled with              */
             /* -fomit-frame-pointer.                                */
             context->Esp = context->Ebp;
             context->Ebp = *((DWORD *)context->Esp);
             context->Esp = context->Esp - 8;
   
             /* Resume execution at the "real" handler within the    */
             /* wrapper function.                                    */
             context->Eip = (DWORD )(xer->alt_path);
   
             return ExceptionContinueExecution;
   
           } else {
               return ExceptionContinueSearch;
           }
       }
   # endif /* __GNUC__ */
   
   
     GC_bool GC_mark_some(cold_gc_frame)
     ptr_t cold_gc_frame;
     {
         GC_bool ret_val;
   
   #   ifndef __GNUC__
         /* Windows 98 appears to asynchronously create and remove  */
         /* writable memory mappings, for reasons we haven't yet    */
         /* understood.  Since we look for writable regions to      */
         /* determine the root set, we may try to mark from an      */
         /* address range that disappeared since we started the     */
         /* collection.  Thus we have to recover from faults here.  */
         /* This code does not appear to be necessary for Windows   */
         /* 95/NT/2000. Note that this code should never generate   */
         /* an incremental GC write fault.                          */
   
         __try {
   
   #   else /* __GNUC__ */
   
         /* Manually install an exception handler since GCC does    */
         /* not yet support Structured Exception Handling (SEH) on  */
         /* Win32.                                                  */
   
         ext_ex_regn er;
   
         er.alt_path = &&handle_ex;
         er.ex_reg.handler = mark_ex_handler;
         asm volatile ("movl %%fs:0, %0" : "=r" (er.ex_reg.prev));
         asm volatile ("movl %0, %%fs:0" : : "r" (&er));
   
   #   endif /* __GNUC__ */
   
             ret_val = GC_mark_some_inner(cold_gc_frame);
   
   #   ifndef __GNUC__
   
         } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                   EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
   
   #   else /* __GNUC__ */
   
             /* Prevent GCC from considering the following code unreachable */
             /* and thus eliminating it.                                    */
             if (er.alt_path != 0)
                 goto rm_handler;
   
   handle_ex:
             /* Execution resumes from here on an access violation. */
   
   #   endif /* __GNUC__ */
   
   #         ifdef CONDPRINT
               if (GC_print_stats) {
                 GC_printf0("Caught ACCESS_VIOLATION in marker. "
                            "Memory mapping disappeared.\n");
               }
   #         endif /* CONDPRINT */
   
             /* We have bad roots on the stack.  Discard mark stack.  */
             /* Rescan from marked objects.  Redetermine roots.     */
             GC_invalidate_mark_state();
             scan_ptr = 0;
   
             ret_val = FALSE;
   
   #   ifndef __GNUC__
   
       }        }
 #   endif /* CONDPRINT */  
     /* We have bad roots on the stack.  Discard mark stack.     */  #   else /* __GNUC__ */
     /* Rescan from marked objects.  Redetermine roots.          */  
     GC_invalidate_mark_state();  rm_handler:
     scan_ptr = 0;        /* Uninstall the exception handler */
     return FALSE;        asm volatile ("mov %0, %%fs:0" : : "r" (er.ex_reg.prev));
   
   #   endif /* __GNUC__ */
   
         return ret_val;
   }    }
 #endif /* defined(MSWIN32) && !defined(__GNUC__) */  #endif /* MSWIN32 */
 }  
   
   
 GC_bool GC_mark_stack_empty()  GC_bool GC_mark_stack_empty()
Line 539  mse * mark_stack_limit;
Line 650  mse * mark_stack_limit;
           /* Large length.                                              */            /* Large length.                                              */
           /* Process part of the range to avoid pushing too much on the */            /* Process part of the range to avoid pushing too much on the */
           /* stack.                                                     */            /* stack.                                                     */
           GC_ASSERT(descr < GC_greatest_plausible_heap_addr            GC_ASSERT(descr < (word)GC_greatest_plausible_heap_addr
                             - GC_least_plausible_heap_addr);                              - (word)GC_least_plausible_heap_addr);
 #         ifdef PARALLEL_MARK  #         ifdef PARALLEL_MARK
 #           define SHARE_BYTES 2048  #           define SHARE_BYTES 2048
             if (descr > SHARE_BYTES && GC_parallel              if (descr > SHARE_BYTES && GC_parallel
Line 571  mse * mark_stack_limit;
Line 682  mse * mark_stack_limit;
           while (descr != 0) {            while (descr != 0) {
             if ((signed_word)descr < 0) {              if ((signed_word)descr < 0) {
               current = *current_p;                current = *current_p;
                 FIXUP_POINTER(current);
               if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {                if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {
                 PREFETCH(current);                  PREFETCH(current);
                 HC_PUSH_CONTENTS((ptr_t)current, mark_stack_top,                  HC_PUSH_CONTENTS((ptr_t)current, mark_stack_top,
Line 645  mse * mark_stack_limit;
Line 757  mse * mark_stack_limit;
           PREFETCH((ptr_t)limit - PREF_DIST*CACHE_LINE_SIZE);            PREFETCH((ptr_t)limit - PREF_DIST*CACHE_LINE_SIZE);
           GC_ASSERT(limit >= current_p);            GC_ASSERT(limit >= current_p);
           deferred = *limit;            deferred = *limit;
             FIXUP_POINTER(deferred);
           limit = (word *)((char *)limit - ALIGNMENT);            limit = (word *)((char *)limit - ALIGNMENT);
           if ((ptr_t)deferred >= least_ha && (ptr_t)deferred <  greatest_ha) {            if ((ptr_t)deferred >= least_ha && (ptr_t)deferred <  greatest_ha) {
             PREFETCH(deferred);              PREFETCH(deferred);
Line 654  mse * mark_stack_limit;
Line 767  mse * mark_stack_limit;
           /* Unroll once, so we don't do too many of the prefetches     */            /* Unroll once, so we don't do too many of the prefetches     */
           /* based on limit.                                            */            /* based on limit.                                            */
           deferred = *limit;            deferred = *limit;
             FIXUP_POINTER(deferred);
           limit = (word *)((char *)limit - ALIGNMENT);            limit = (word *)((char *)limit - ALIGNMENT);
           if ((ptr_t)deferred >= least_ha && (ptr_t)deferred <  greatest_ha) {            if ((ptr_t)deferred >= least_ha && (ptr_t)deferred <  greatest_ha) {
             PREFETCH(deferred);              PREFETCH(deferred);
Line 668  mse * mark_stack_limit;
Line 782  mse * mark_stack_limit;
         /* Since HC_PUSH_CONTENTS expands to a lot of code,     */          /* Since HC_PUSH_CONTENTS expands to a lot of code,     */
         /* we don't.                                            */          /* we don't.                                            */
         current = *current_p;          current = *current_p;
           FIXUP_POINTER(current);
         PREFETCH((ptr_t)current_p + PREF_DIST*CACHE_LINE_SIZE);          PREFETCH((ptr_t)current_p + PREF_DIST*CACHE_LINE_SIZE);
         if ((ptr_t)current >= least_ha && (ptr_t)current <  greatest_ha) {          if ((ptr_t)current >= least_ha && (ptr_t)current <  greatest_ha) {
           /* Prefetch the contents of the object we just pushed.  It's  */            /* Prefetch the contents of the object we just pushed.  It's  */
Line 719  mse * GC_steal_mark_stack(mse * low, mse * high, mse *
Line 834  mse * GC_steal_mark_stack(mse * low, mse * high, mse *
     mse *top = local - 1;      mse *top = local - 1;
     unsigned i = 0;      unsigned i = 0;
   
       /* Make sure that prior writes to the mark stack are visible. */
       /* On some architectures, the fact that the reads are         */
       /* volatile should suffice.                                   */
   #   if !defined(IA64) && !defined(HP_PA) && !defined(I386)
         GC_memory_barrier();
   #   endif
     GC_ASSERT(high >= low-1 && high - low + 1 <= GC_mark_stack_size);      GC_ASSERT(high >= low-1 && high - low + 1 <= GC_mark_stack_size);
     for (p = low; p <= high && i <= max; ++p) {      for (p = low; p <= high && i <= max; ++p) {
         word descr = *(volatile word *) &(p -> mse_descr);          word descr = *(volatile word *) &(p -> mse_descr);
           /* In the IA64 memory model, the following volatile store is    */
           /* ordered after this read of descr.  Thus a thread must read   */
           /* the original nonzero value.  HP_PA appears to be similar,    */
           /* and if I'm reading the P4 spec correctly, X86 is probably    */
           /* also OK.  In some other cases we need a barrier.             */
   #       if !defined(IA64) && !defined(HP_PA) && !defined(I386)
             GC_memory_barrier();
   #       endif
         if (descr != 0) {          if (descr != 0) {
             *(volatile word *) &(p -> mse_descr) = 0;              *(volatile word *) &(p -> mse_descr) = 0;
               /* More than one thread may get this entry, but that's only */
               /* a minor performance problem.                             */
             ++top;              ++top;
             top -> mse_descr = descr;              top -> mse_descr = descr;
             top -> mse_start = p -> mse_start;              top -> mse_start = p -> mse_start;
             GC_ASSERT(  top -> mse_descr & GC_DS_TAGS != GC_DS_LENGTH ||              GC_ASSERT(  top -> mse_descr & GC_DS_TAGS != GC_DS_LENGTH ||
                         top -> mse_descr < GC_greatest_plausible_heap_addr                          top -> mse_descr < GC_greatest_plausible_heap_addr
                                            - GC_least_plausible_heap_addr);                                             - GC_least_plausible_heap_addr);
             /* There is no synchronization here.  We assume that at     */  
             /* least one thread will see the original descriptor.       */  
             /* Otherwise we need a barrier.                             */  
             /* More than one thread may get this entry, but that's only */  
             /* a minor performance problem.                             */  
             /* If this is a big object, count it as                     */              /* If this is a big object, count it as                     */
             /* size/256 + 1 objects.                                    */              /* size/256 + 1 objects.                                    */
             ++i;              ++i;
Line 771  void GC_return_mark_stack(mse * low, mse * high)
Line 897  void GC_return_mark_stack(mse * low, mse * high)
       BCOPY(low, my_start, stack_size * sizeof(mse));        BCOPY(low, my_start, stack_size * sizeof(mse));
       GC_ASSERT(GC_mark_stack_top = my_top);        GC_ASSERT(GC_mark_stack_top = my_top);
 #     if !defined(IA64) && !defined(HP_PA)  #     if !defined(IA64) && !defined(HP_PA)
         GC_memory_write_barrier();          GC_memory_barrier();
 #     endif  #     endif
         /* On IA64, the volatile write acts as a release barrier. */          /* On IA64, the volatile write acts as a release barrier. */
       GC_mark_stack_top = my_top + stack_size;        GC_mark_stack_top = my_top + stack_size;
Line 1335  ptr_t top;
Line 1461  ptr_t top;
 #   define GC_least_plausible_heap_addr least_ha  #   define GC_least_plausible_heap_addr least_ha
   
     if (top == 0) return;      if (top == 0) return;
     /* check all pointers in range and put in push if they appear */      /* check all pointers in range and push if they appear      */
     /* to be valid.                                               */      /* to be valid.                                             */
       lim = t - 1 /* longword */;        lim = t - 1 /* longword */;
       for (p = b; p <= lim; p = (word *)(((char *)p) + ALIGNMENT)) {        for (p = b; p <= lim; p = (word *)(((char *)p) + ALIGNMENT)) {
         q = *p;          q = *p;
Line 1359  ptr_t bottom;
Line 1485  ptr_t bottom;
 ptr_t top;  ptr_t top;
 ptr_t cold_gc_frame;  ptr_t cold_gc_frame;
 {  {
   if (GC_all_interior_pointers) {    if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
 #   define EAGER_BYTES 1024  #   define EAGER_BYTES 1024
     /* Push the hot end of the stack eagerly, so that register values   */      /* Push the hot end of the stack eagerly, so that register values   */
     /* saved inside GC frames are marked before they disappear.         */      /* saved inside GC frames are marked before they disappear.         */
Line 1368  ptr_t cold_gc_frame;
Line 1494  ptr_t cold_gc_frame;
         GC_push_all_stack(bottom, top);          GC_push_all_stack(bottom, top);
         return;          return;
     }      }
       GC_ASSERT(bottom <= cold_gc_frame && cold_gc_frame <= top);
 #   ifdef STACK_GROWS_DOWN  #   ifdef STACK_GROWS_DOWN
         GC_push_all(cold_gc_frame - sizeof(ptr_t), top);          GC_push_all(cold_gc_frame - sizeof(ptr_t), top);
         GC_push_all_eager(bottom, cold_gc_frame);          GC_push_all_eager(bottom, cold_gc_frame);
Line 1388  void GC_push_all_stack(bottom, top)
Line 1515  void GC_push_all_stack(bottom, top)
 ptr_t bottom;  ptr_t bottom;
 ptr_t top;  ptr_t top;
 {  {
   if (GC_all_interior_pointers) {    if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
     GC_push_all(bottom, top);      GC_push_all(bottom, top);
   } else {    } else {
     GC_push_all_eager(bottom, top);      GC_push_all_eager(bottom, top);

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>