[BACK]Return to gc_mark.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc5.3

Annotation of OpenXM_contrib2/asir2000/gc5.3/gc_mark.h, Revision 1.1

1.1     ! noro        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:
        !            23: # ifdef KEEP_BACK_PTRS
        !            24: #   include "dbg_mlc.h"
        !            25: # endif
        !            26:
        !            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: /*
        !            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   );
        !            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:
        !            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:
        !            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             */
        !            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
        !           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:
        !           120: ptr_t GC_find_start();
        !           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: { \
        !           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); \
        !           174:     } \
        !           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:     \
        !           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:         } \
        !           237:         GC_STORE_BACK_PTR((ptr_t)source, (ptr_t)HBLKPTR(current) \
        !           238:                                      + WORDS_TO_BYTES(displ)); \
        !           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:
        !           245: #if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
        !           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>