[BACK]Return to gc_mark.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gc

Annotation of OpenXM_contrib/gc/gc_mark.h, Revision 1.1.1.3

1.1       maekawa     1: /*
                      2:  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
                      3:  *
                      4:  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
                      5:  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
                      6:  *
                      7:  * Permission is hereby granted to use or copy this program
                      8:  * for any purpose,  provided the above notices are retained on all copies.
                      9:  * Permission to modify the code and to distribute modified code is granted,
                     10:  * provided the above notices are retained, and a notice that the code was
                     11:  * modified is included with the above copyright notice.
                     12:  *
                     13:  */
                     14: /* Boehm, November 7, 1994 4:56 pm PST */
                     15:
                     16: /*
                     17:  * Declarations of mark stack.  Needed by marker and client supplied mark
                     18:  * routines.  To be included after gc_priv.h.
                     19:  */
                     20: #ifndef GC_MARK_H
                     21: # define GC_MARK_H
                     22:
1.1.1.3 ! maekawa    23: # ifdef KEEP_BACK_PTRS
        !            24: #   include "dbg_mlc.h"
        !            25: # endif
        !            26:
1.1       maekawa    27: /* A client supplied mark procedure.  Returns new mark stack pointer.  */
                     28: /* Primary effect should be to push new entries on the mark stack.     */
                     29: /* Mark stack pointer values are passed and returned explicitly.       */
                     30: /* Global variables decribing mark stack are not necessarily valid.    */
                     31: /* (This usually saves a few cycles by keeping things in registers.)   */
                     32: /* Assumed to scan about PROC_BYTES on average.  If it needs to do     */
                     33: /* much more work than that, it should do it in smaller pieces by      */
                     34: /* pushing itself back on the mark stack.                              */
                     35: /* Note that it should always do some work (defined as marking some    */
                     36: /* objects) before pushing more than one entry on the mark stack.      */
                     37: /* This is required to ensure termination in the event of mark stack   */
                     38: /* overflows.                                                          */
                     39: /* This procedure is always called with at least one empty entry on the */
                     40: /* mark stack.                                                         */
                     41: /* Currently we require that mark procedures look for pointers in a    */
                     42: /* subset of the places the conservative marker would.  It must be safe        */
                     43: /* to invoke the normal mark procedure instead.                                */
                     44: # define PROC_BYTES 100
                     45: /* The real declarations of the following are in gc_priv.h, so that    */
                     46: /* we can avoid scanning the following table.                          */
                     47: /*
1.1.1.3 ! maekawa    48: typedef struct ms_entry * (*mark_proc)(   word * addr,
        !            49:                                          struct ms_entry *mark_stack_ptr,
        !            50:                                          struct ms_entry *mark_stack_limit,
        !            51:                                          word env   );
1.1       maekawa    52:
                     53: # define LOG_MAX_MARK_PROCS 6
                     54: # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS)
                     55: extern mark_proc GC_mark_procs[MAX_MARK_PROCS];
                     56: */
                     57:
                     58: extern word GC_n_mark_procs;
                     59:
1.1.1.3 ! maekawa    60: /* In a few cases it's necessary to assign statically known indices to */
        !            61: /* certain mark procs.  Thus we reserve a few for well known clients.  */
        !            62: /* (This is necessary if mark descriptors are compiler generated.)     */
        !            63: #define GC_RESERVED_MARK_PROCS 8
        !            64: #   define GCJ_RESERVED_MARK_PROC_INDEX 0
        !            65:
1.1       maekawa    66: /* Object descriptors on mark stack or in objects.  Low order two      */
                     67: /* bits are tags distinguishing among the following 4 possibilities    */
                     68: /* for the high order 30 bits.                                         */
                     69: #define DS_TAG_BITS 2
                     70: #define DS_TAGS   ((1 << DS_TAG_BITS) - 1)
                     71: #define DS_LENGTH 0    /* The entire word is a length in bytes that    */
                     72:                        /* must be a multiple of 4.                     */
                     73: #define DS_BITMAP 1    /* 30 bits are a bitmap describing pointer      */
                     74:                        /* fields.  The msb is 1 iff the first word     */
                     75:                        /* is a pointer.                                */
                     76:                        /* (This unconventional ordering sometimes      */
                     77:                        /* makes the marker slightly faster.)           */
                     78:                        /* Zeroes indicate definite nonpointers.  Ones  */
                     79:                        /* indicate possible pointers.                  */
                     80:                        /* Only usable if pointers are word aligned.    */
                     81: #   define BITMAP_BITS (WORDSZ - DS_TAG_BITS)
                     82: #define DS_PROC   2
                     83:                        /* The objects referenced by this object can be */
                     84:                        /* pushed on the mark stack by invoking         */
                     85:                        /* PROC(descr).  ENV(descr) is passed as the    */
                     86:                        /* last argument.                               */
                     87: #   define PROC(descr) \
                     88:                (GC_mark_procs[((descr) >> DS_TAG_BITS) & (MAX_MARK_PROCS-1)])
                     89: #   define ENV(descr) \
                     90:                ((descr) >> (DS_TAG_BITS + LOG_MAX_MARK_PROCS))
                     91: #   define MAX_ENV \
                     92:              (((word)1 << (WORDSZ - DS_TAG_BITS - LOG_MAX_MARK_PROCS)) - 1)
                     93: #   define MAKE_PROC(proc_index, env) \
                     94:            (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS) \
                     95:            | DS_PROC)
                     96: #define DS_PER_OBJECT 3        /* The real descriptor is at the                */
                     97:                        /* byte displacement from the beginning of the  */
                     98:                        /* object given by descr & ~DS_TAGS             */
1.1.1.3 ! maekawa    99:                        /* If the descriptor is negative, the real      */
        !           100:                        /* descriptor is at (*<object_start>) -         */
        !           101:                        /* (descr & ~DS_TAGS) - INDIR_PER_OBJ_BIAS      */
        !           102:                        /* The latter alternative can be used if each   */
        !           103:                        /* object contains a type descriptor in the     */
        !           104:                        /* first word.                                  */
        !           105: #define INDIR_PER_OBJ_BIAS 0x10
1.1       maekawa   106:
                    107: typedef struct ms_entry {
                    108:     word * mse_start;   /* First word of object */
                    109:     word mse_descr;    /* Descriptor; low order two bits are tags,     */
                    110:                        /* identifying the upper 30 bits as one of the  */
                    111:                        /* following:                                   */
                    112: } mse;
                    113:
                    114: extern word GC_mark_stack_size;
                    115:
                    116: extern mse * GC_mark_stack_top;
                    117:
                    118: extern mse * GC_mark_stack;
                    119:
1.1.1.3 ! maekawa   120: ptr_t GC_find_start();
1.1       maekawa   121:
                    122: mse * GC_signal_mark_stack_overflow();
                    123:
                    124: # ifdef GATHERSTATS
                    125: #   define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz)
                    126: #   define ADD_TO_COMPOSITE(sz) GC_composite_in_use += (sz)
                    127: # else
                    128: #   define ADD_TO_ATOMIC(sz)
                    129: #   define ADD_TO_COMPOSITE(sz)
                    130: # endif
                    131:
                    132: /* Push the object obj with corresponding heap block header hhdr onto  */
                    133: /* the mark stack.                                                     */
                    134: # define PUSH_OBJ(obj, hhdr, mark_stack_top, mark_stack_limit) \
                    135: { \
                    136:     register word _descr = (hhdr) -> hb_descr; \
                    137:         \
                    138:     if (_descr == 0) { \
                    139:        ADD_TO_ATOMIC((hhdr) -> hb_sz); \
                    140:     } else { \
                    141:         ADD_TO_COMPOSITE((hhdr) -> hb_sz); \
                    142:         mark_stack_top++; \
                    143:         if (mark_stack_top >= mark_stack_limit) { \
                    144:           mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top); \
                    145:         } \
                    146:         mark_stack_top -> mse_start = (obj); \
                    147:         mark_stack_top -> mse_descr = _descr; \
                    148:     } \
                    149: }
                    150:
                    151: #ifdef PRINT_BLACK_LIST
                    152: #   define GC_FIND_START(current, hhdr, source) \
                    153:        GC_find_start(current, hhdr, source)
                    154: #else
                    155: #   define GC_FIND_START(current, hhdr, source) \
                    156:        GC_find_start(current, hhdr)
                    157: #endif
                    158:
                    159: /* Push the contents of current onto the mark stack if it is a valid   */
                    160: /* ptr to a currently unmarked object.  Mark it.                       */
                    161: /* If we assumed a standard-conforming compiler, we could probably     */
                    162: /* generate the exit_label transparently.                              */
                    163: # define PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, \
                    164:                       source, exit_label) \
                    165: { \
1.1.1.3 ! maekawa   166:     hdr * my_hhdr; \
        !           167:     ptr_t my_current = current; \
        !           168:  \
        !           169:     GET_HDR(my_current, my_hhdr); \
        !           170:     if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \
        !           171:          my_current = GC_FIND_START(my_current, my_hhdr, (word)source); \
        !           172:          if (my_current == 0) goto exit_label; \
        !           173:          my_hhdr = GC_find_header(my_current); \
1.1       maekawa   174:     } \
1.1.1.3 ! maekawa   175:     PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
        !           176:                  source, exit_label, my_hhdr); \
        !           177: exit_label: ; \
        !           178: }
        !           179:
        !           180: /* As above, but use header cache for header lookup.   */
        !           181: # define HC_PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, \
        !           182:                       source, exit_label) \
        !           183: { \
        !           184:     hdr * my_hhdr; \
        !           185:     ptr_t my_current = current; \
        !           186:  \
        !           187:     HC_GET_HDR(my_current, my_hhdr, source); \
        !           188:     PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
        !           189:                  source, exit_label, my_hhdr); \
        !           190: exit_label: ; \
        !           191: }
        !           192:
        !           193: /* As above, but deal with two pointers in interleaved fashion.        */
        !           194: # define HC_PUSH_CONTENTS2(current1, current2, mark_stack_top, \
        !           195:                           mark_stack_limit, \
        !           196:                           source1, source2, exit_label1, exit_label2) \
        !           197: { \
        !           198:     hdr * hhdr1; \
        !           199:     ptr_t my_current1 = current1; \
        !           200:     hdr * hhdr2; \
        !           201:     ptr_t my_current2 = current2; \
        !           202:  \
        !           203:     HC_GET_HDR2(my_current1, hhdr1, source1, my_current2, hhdr2, source2); \
        !           204:     PUSH_CONTENTS_HDR(my_current1, mark_stack_top, mark_stack_limit, \
        !           205:                  source1, exit_label1, hhdr1); \
        !           206: exit_label1: ; \
        !           207:     if (0 != hhdr2) { \
        !           208:       PUSH_CONTENTS_HDR(my_current2, mark_stack_top, mark_stack_limit, \
        !           209:                  source2, exit_label2, hhdr2); \
        !           210:     } \
        !           211: exit_label2: ; \
        !           212: }
        !           213:
        !           214: # define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \
        !           215:                           source, exit_label, hhdr) \
        !           216: { \
        !           217:     int displ;  /* Displacement in block; first bytes, then words */ \
        !           218:     map_entry_type map_entry; \
        !           219:     \
1.1       maekawa   220:     displ = HBLKDISPL(current); \
                    221:     map_entry = MAP_ENTRY((hhdr -> hb_map), displ); \
                    222:     if (map_entry == OBJ_INVALID) { \
                    223:         GC_ADD_TO_BLACK_LIST_NORMAL(current, source); goto exit_label; \
                    224:     } \
                    225:     displ = BYTES_TO_WORDS(displ); \
                    226:     displ -= map_entry; \
                    227:        \
                    228:     { \
                    229:         register word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(displ); \
                    230:         register word mark_word = *mark_word_addr; \
                    231:         register word mark_bit = (word)1 << modWORDSZ(displ); \
                    232:           \
                    233:         if (mark_word & mark_bit) { \
                    234:              /* Mark bit is already set */ \
                    235:              goto exit_label; \
                    236:         } \
1.1.1.2   maekawa   237:         GC_STORE_BACK_PTR((ptr_t)source, (ptr_t)HBLKPTR(current) \
                    238:                                      + WORDS_TO_BYTES(displ)); \
1.1       maekawa   239:         *mark_word_addr = mark_word | mark_bit; \
                    240:     } \
                    241:     PUSH_OBJ(((word *)(HBLKPTR(current)) + displ), hhdr, \
                    242:             mark_stack_top, mark_stack_limit) \
                    243: }
                    244:
1.1.1.3 ! maekawa   245: #if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
1.1       maekawa   246: #   define PUSH_ONE_CHECKED(p, ip, source) \
                    247:        GC_push_one_checked(p, ip, (ptr_t)(source))
                    248: #else
                    249: #   define PUSH_ONE_CHECKED(p, ip, source) \
                    250:        GC_push_one_checked(p, ip)
                    251: #endif
                    252:
                    253: /*
                    254:  * Push a single value onto mark stack. Mark from the object pointed to by p.
                    255:  * P is considered valid even if it is an interior pointer.
                    256:  * Previously marked objects are not pushed.  Hence we make progress even
                    257:  * if the mark stack overflows.
                    258:  */
                    259: # define GC_PUSH_ONE_STACK(p, source) \
                    260:     if ((ptr_t)(p) >= GC_least_plausible_heap_addr     \
                    261:         && (ptr_t)(p) < GC_greatest_plausible_heap_addr) {     \
                    262:         PUSH_ONE_CHECKED(p, TRUE, source);     \
                    263:     }
                    264:
                    265: /*
                    266:  * As above, but interior pointer recognition as for
                    267:  * normal for heap pointers.
                    268:  */
                    269: # ifdef ALL_INTERIOR_POINTERS
                    270: #   define AIP TRUE
                    271: # else
                    272: #   define AIP FALSE
                    273: # endif
                    274: # define GC_PUSH_ONE_HEAP(p,source) \
                    275:     if ((ptr_t)(p) >= GC_least_plausible_heap_addr     \
                    276:         && (ptr_t)(p) < GC_greatest_plausible_heap_addr) {     \
                    277:         PUSH_ONE_CHECKED(p,AIP,source);        \
                    278:     }
                    279:
                    280: /*
                    281:  * Mark from one finalizable object using the specified
                    282:  * mark proc. May not mark the object pointed to by
                    283:  * real_ptr. That is the job of the caller, if appropriate
                    284:  */
                    285: # define GC_MARK_FO(real_ptr, mark_proc) \
                    286: { \
                    287:     (*(mark_proc))(real_ptr); \
                    288:     while (!GC_mark_stack_empty()) GC_mark_from_mark_stack(); \
                    289:     if (GC_mark_state != MS_NONE) { \
                    290:         GC_set_mark_bit(real_ptr); \
                    291:         while (!GC_mark_some((ptr_t)0)); \
                    292:     } \
                    293: }
                    294:
                    295: extern GC_bool GC_mark_stack_too_small;
                    296:                                /* We need a larger mark stack.  May be */
                    297:                                /* set by client supplied mark routines.*/
                    298:
                    299: typedef int mark_state_t;      /* Current state of marking, as follows:*/
                    300:                                /* Used to remember where we are during */
                    301:                                /* concurrent marking.                  */
                    302:
                    303:                                /* We say something is dirty if it was  */
                    304:                                /* written since the last time we       */
                    305:                                /* retrieved dirty bits.  We say it's   */
                    306:                                /* grungy if it was marked dirty in the */
                    307:                                /* last set of bits we retrieved.       */
                    308:
                    309:                                /* Invariant I: all roots and marked    */
                    310:                                /* objects p are either dirty, or point */
                    311:                                /* to objects q that are either marked  */
                    312:                                /* or a pointer to q appears in a range */
                    313:                                /* on the mark stack.                   */
                    314:
                    315: # define MS_NONE 0             /* No marking in progress. I holds.     */
                    316:                                /* Mark stack is empty.                 */
                    317:
                    318: # define MS_PUSH_RESCUERS 1    /* Rescuing objects are currently       */
                    319:                                /* being pushed.  I holds, except       */
                    320:                                /* that grungy roots may point to       */
                    321:                                /* unmarked objects, as may marked      */
                    322:                                /* grungy objects above scan_ptr.       */
                    323:
                    324: # define MS_PUSH_UNCOLLECTABLE 2
                    325:                                /* I holds, except that marked          */
                    326:                                /* uncollectable objects above scan_ptr */
                    327:                                /* may point to unmarked objects.       */
                    328:                                /* Roots may point to unmarked objects  */
                    329:
                    330: # define MS_ROOTS_PUSHED 3     /* I holds, mark stack may be nonempty  */
                    331:
                    332: # define MS_PARTIALLY_INVALID 4        /* I may not hold, e.g. because of M.S. */
                    333:                                /* overflow.  However marked heap       */
                    334:                                /* objects below scan_ptr point to      */
                    335:                                /* marked or stacked objects.           */
                    336:
                    337: # define MS_INVALID 5          /* I may not hold.                      */
                    338:
                    339: extern mark_state_t GC_mark_state;
                    340:
                    341: #endif  /* GC_MARK_H */
                    342:

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