[BACK]Return to nursery.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gc

Annotation of OpenXM_contrib/gc/nursery.c, Revision 1.1

1.1     ! maekawa     1: /*
        !             2:  * Copyright (c) 1999 by Silicon Graphics.  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: #ifdef NURSERY
        !            15: ??? This implementation is incomplete.  If you are trying to
        !            16: ??? compile this you are doing something wrong.
        !            17:
        !            18: #include "nursery.h"
        !            19:
        !            20: #define SCAN_STATICS_FOR_NURSERY
        !            21:        /* If this is not defined, the collector will not see   */
        !            22:        /* references from static data areas to the nursery.    */
        !            23:
        !            24: struct copy_obj {
        !            25:     ptr_t forward;     /* Forwarding link for copied objects.  */
        !            26:     GC_copy_descriptor descr; /* Object descriptor     */
        !            27:     word data[1];
        !            28: }
        !            29:
        !            30: ptr_t GC_nursery_start;        /* Start of nursery area.       */
        !            31:                        /* Must be NURSERY_BLOCK_SIZE   */
        !            32:                        /* aligned.                     */
        !            33: ptr_t GC_nursery_end;  /* End of nursery area.         */
        !            34: unsigned char * GC_nursery_map;
        !            35:                        /* GC_nursery_map[i] != 0 if an object  */
        !            36:                        /* starts on the ith 64-bit "word" of   */
        !            37:                        /* nursery.  This simple structure has  */
        !            38:                        /* the advantage that                   */
        !            39:                        /* allocation is cheap.  Lookup is      */
        !            40:                        /* cheap for pointers to the head of    */
        !            41:                        /* an object, which should be the       */
        !            42:                        /* usual case.                          */
        !            43: #   define NURSERY_MAP_NOT_START       0  /* Not start of object. */
        !            44: #   define NURSERY_MAP_START           1  /* Start of object.     */
        !            45: #   define NURSERY_MAP_PINNED          2  /* Start of pinned obj. */
        !            46:
        !            47: # ifdef ALIGN_DOUBLE
        !            48: #   define NURSERY_WORD_SIZE (2 * sizeof(word))
        !            49: # else
        !            50: #   define NURSERY_WORD_SIZE sizeof(word)
        !            51: # endif
        !            52:
        !            53: # define NURSERY_BLOCK_SIZE (HBLKSIZE/2)
        !            54:        /* HBLKSIZE must be a multiple of NURSERY_BLOCK_SIZE */
        !            55: # define NURSERY_SIZE (1024 * NURSERY_BLOCK_SIZE)
        !            56:
        !            57: size_t GC_nursery_size = NURSERY_SIZE;
        !            58:                        /* Must be multiple of NURSERY_BLOCK_SIZE       */
        !            59:
        !            60: size_t GC_nursery_blocks; /* Number of blocks in the nursery.  */
        !            61:
        !            62: unsigned GC_next_nursery_block; /* index of next block we will attempt         */
        !            63:                                /* allocate from during this cycle.     */
        !            64:                                /* If it is pinned, we won't actually   */
        !            65:                                /* use it.                              */
        !            66:
        !            67: unsigned short *GC_pinned;     /* Number of pinned objects in ith      */
        !            68:                                /* nursery block.                       */
        !            69:                                /* GC_pinned[i] != 0 if the ith nursery */
        !            70:                                /* block is pinned, and thus not used   */
        !            71:                                /* for allocation.                      */
        !            72:
        !            73: GC_copy_alloc_state global_alloc_state = (ptr_t)(-1);  /* will overflow. */
        !            74:
        !            75: /* Array of known rescuing pointers from the heap to the nursery.      */
        !            76:   ptr_t ** nursery_rescuers;
        !            77:   /* Pointer to one past the last slot in rescuer table        */
        !            78:   ptr_t ** nursery_rescuers_end;
        !            79:   /* Maximum number of known rescuing pointers.                        */
        !            80: # define MAX_NURSERY_RESCUERS 32*1024
        !            81:   /* Add a rescuer to the list */
        !            82: # define ADD_NURSERY_RESCUER(p) \
        !            83:     if (nursery_rescuers_end >= nursery_rescuers + MAX_NURSERY_RESCUERS) { \
        !            84:       ABORT("Nursery recuers overflow"); /* Fix later !!! */ \
        !            85:     } else { \
        !            86:       *nursery_rescuers_end++ = p; \
        !            87:     }
        !            88:   /* Remove rescuer at the given position in the table */
        !            89: # define REMOVE_RESCUER(p) \
        !            90:     *p = *--nursery_rescuers_end
        !            91:
        !            92: /* Should be called with allocator lock held.  */
        !            93: GC_nursery_init() {
        !            94:     GC_nursery_start = GET_MEM(GC_nursery_size);
        !            95:     GC_nursery_end = GC_nursery_start + GC_nursery_size;
        !            96:     GC_next_nursery_block = 0;
        !            97:     if (GC_nursery_start < GC_least_plausible_heap_addr) {
        !            98:         GC_least_plausible_heap_addr = GC_nursery_start;
        !            99:     }
        !           100:     if (GC_nursery_end > GC_greatest_plausible_heap_addr) {
        !           101:         GC_greatest_plausible_heap_addr = GC_nursery_end;
        !           102:     }
        !           103:     if (GC_nursery_start & (NURSERY_BLOCK_SIZE-1)) {
        !           104:        GC_err_printf1("Nursery area is misaligned!!");
        !           105:        /* This should be impossible, since GET_MEM returns HBLKSIZE */
        !           106:        /* aligned chunks, and that should be a multiple of          */
        !           107:        /* NURSERY_BLOCK_SIZE                                        */
        !           108:        ABORT("misaligned nursery");
        !           109:     }
        !           110:     GC_nursery_map = GET_MEM(GC_nursery_size/NURSERY_WORD_SIZE);
        !           111:     /* Map is cleared a block at a time when we allocate from the block. */
        !           112:     /* BZERO(GC_nursery_map, GC_nursery_size/NURSERY_WORD_SIZE);        */
        !           113:     GC_nursery_blocks = GC_nursery_size/NURSERY_BLOCK_SIZE;
        !           114:     GC_pinned = GC_scratch_alloc(GC_nursery_blocks * sizeof(unsigned short));
        !           115:     BZERO(GC_pinned, GC_nursery_blocks);
        !           116:     nursery_rescuers = GET_MEM(MAX_NURSERY_RESCUERS * sizeof(ptr_t *));
        !           117:     nursery_rescuers_end = nursery_rescuers;
        !           118:     if (0 == GC_nursery_start || 0 == GC_nursery_map || 0 == nursery_rescuers)
        !           119:        ABORT("Insufficient memory for nursery");
        !           120: }
        !           121:
        !           122: #define PIN_OBJ(p) \
        !           123:     if (p >= GC_nursery_start && p < GC_nursery_end) { GC_pin_obj_checked(p); }
        !           124:
        !           125: /* Pin the object at p, if it's in the nursery.        */
        !           126: void GC_pin_obj(ptr_t p) {
        !           127:     PIN_OBJ(p);
        !           128: }
        !           129:
        !           130: void (*GC_push_proc)(ptr_t) = 0;
        !           131:
        !           132: /* Pin the object at p, which is known to be in the nursery.   */
        !           133: void GC_pin_obj_checked(ptr_t p) {
        !           134:     unsigned offset = p - GC_nursery_start;
        !           135:     unsigned word_offset = BYTES_TO_WORDS(offset);
        !           136:     unsigned blockno = (current - GC_nursery_start)/NURSERY_BLOCK_SIZE;
        !           137:     while (GC_nursery_map[word_offset] == NURSERY_MAP_NOT_START) {
        !           138:        --word_offset;
        !           139:     }
        !           140:     if (GC_nursery_map[word_offset] != NURSERY_MAP_PINNED) {
        !           141:         GC_nursery_map[word_offset] = NURSERY_MAP_PINNED;
        !           142:         ++GC_pinned[blockno];
        !           143:         ??Push object at GC_nursery_start + WORDS_TO_BYTES(word_offset)
        !           144:         ??onto mark stack.
        !           145:     }
        !           146: }
        !           147:
        !           148: void GC_scan_region_for_nursery(ptr_t low, ptr_t high) {
        !           149: #   if CPP_WORDSZ/8 != ALIGNMENT
        !           150:       --> fix this
        !           151: #   endif
        !           152:     word * l = (word *)((word)low + ALIGNMENT - 1 & ~(ALIGNMENT - 1));
        !           153:     word * h = (word *)((word)high & ~(ALIGNMENT - 1));
        !           154:     word * p;
        !           155:     for (p = l; p < h; ++p) {
        !           156:        PIN_OBJ(p);
        !           157:     }
        !           158: }
        !           159:
        !           160: /* Invoke GC_scan_region_for_nursery on ranges that are not excluded. */
        !           161: void GC_scan_region_for_nursery_with_exclusions(ptr_t bottom, ptr_t top)
        !           162: {
        !           163:     struct exclusion * next;
        !           164:     ptr_t excl_start;
        !           165:
        !           166:     while (bottom < top) {
        !           167:         next = GC_next_exclusion(bottom);
        !           168:        if (0 == next || (excl_start = next -> e_start) >= top) {
        !           169:            GC_scan_region_for_nursery(bottom, top);
        !           170:            return;
        !           171:        }
        !           172:        if (excl_start > bottom)
        !           173:                GC_scan_region_for_nursery(bottom, excl_start);
        !           174:        bottom = next -> e_end;
        !           175:     }
        !           176: }
        !           177:
        !           178:
        !           179: void GC_scan_stacks_for_nursery(void) {
        !           180: #   ifdef THREADS
        !           181:        --> fix this
        !           182: #   endif
        !           183: #   ifdef STACK_GROWS_DOWN
        !           184:       ptr_t stack_low = GC_approx_sp();
        !           185:       ptr_t stack_high = GC_stackbottom;
        !           186: #   else
        !           187:       ptr_t stack_low = GC_stackbottom;
        !           188:       ptr_t stack_high = GC_approx_sp();
        !           189: #   endif
        !           190:     GC_scan_region_for_nursery(stack_low, stack_high);
        !           191: #   ifdef IA64
        !           192:       GC_scan_region_for_nursery(BACKING_STORE_BASE,
        !           193:                                 (ptr_t) GC_save_regs_ret_val);
        !           194: #   endif
        !           195: }
        !           196:
        !           197: void GC_scan_roots_for_nursery(void) {
        !           198:   /* Scan registers.   */
        !           199:     /* Direct GC_push_one to call GC_pin_obj instead of marking        */
        !           200:     /* and pushing objects.                                    */
        !           201:     /* This is a bit ugly, but we don't have to touch the      */
        !           202:     /* platform-dependent code.                                        */
        !           203:
        !           204:     void (*old_push_proc)(ptr_t) = GC_push_proc;
        !           205:     GC_push_proc = GC_pin_obj;
        !           206:     GC_push_regs();
        !           207:     GC_push_proc = old_push_proc;
        !           208:   GC_scan_stacks_for_nursery();
        !           209: # ifdef SCAN_STATICS_FOR_NURSERY
        !           210: #   if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(PCR)) \
        !           211:         && !defined(SRC_M3)
        !           212:       GC_remove_tmp_roots();
        !           213:       GC_register_dynamic_libraries();
        !           214: #   endif
        !           215:     /* Mark everything in static data areas                             */
        !           216:       for (i = 0; i < n_root_sets; i++) {
        !           217:         GC_scan_region_for_nursery_with_exclusions (
        !           218:                             GC_static_roots[i].r_start,
        !           219:                             GC_static_roots[i].r_end);
        !           220:      }
        !           221: # endif
        !           222: }
        !           223:
        !           224: /* Array of known rescuing pointers from the heap to the nursery.      */
        !           225: ptr_t ** nursery_rescuers;
        !           226:
        !           227: /* Caller holds allocation lock.       */
        !           228: void GC_collect_nursery(void) {
        !           229:     int i;
        !           230:     ptr_t scan_ptr = 0;
        !           231:     STOP_WORLD;
        !           232:     for (i = 0; i < GC_nursery_blocks; ++i) GC_pinned[i] = 0;
        !           233:     GC_scan_roots_for_nursery();
        !           234:     /* All objects referenced by roots are now pinned.                 */
        !           235:     /* Their contents are described by                                 */
        !           236:     /* mark stack entries.                                     */
        !           237:
        !           238:     /* Pin blocks corresponding to valid allocation states.    */
        !           239:     /* that probably happens automagically if the allocation   */
        !           240:     /* states are kept where we can see them.                  */
        !           241:     /* It will take work if static roots are not scanned.      */
        !           242:     /* We want to do this both for correctness and to avoid    */
        !           243:     /* promoting very young objects.                           */
        !           244:
        !           245:     /* Somehow capture dirty bits.  Update rescuers array to   */
        !           246:     /* reflect newly valid and invalid references from dirty   */
        !           247:     /* pages.  Other references should remain valid, since the */
        !           248:     /* referents should have been pinned.                      */
        !           249:
        !           250:     /* Traverse the old object heap.  Pin objects in the       */
        !           251:     /* nursery that are ambiguously referenced, copy those     */
        !           252:     /* that are unambiguously referenced.                      */
        !           253:
        !           254:     /* Traverse objects in mark stack.                         */
        !           255:     /* If referenced object is in pinned block, add contents   */
        !           256:     /* to mark stack.  If referenced object is forwarded,      */
        !           257:     /* update pointer.  Otherwise reallocate the object        in the  */
        !           258:     /* old heap, copy its contents, and then enqueue its       */
        !           259:     /* contents in the mark stack.                             */
        !           260:     START_WORLD;
        !           261: }
        !           262:
        !           263: /* Initialize an allocation state so that it can be used for   */
        !           264: /* allocation.  This implicitly reserves a small section of the        */
        !           265: /* nursery for use with this allocator.                                */
        !           266: /* Also called to replenish an allocator that has been                 */
        !           267: /* exhausted.                                                  */
        !           268: void GC_init_copy_alloc_state(GC_copy_alloc_state *)
        !           269:     unsigned next_block;
        !           270:     ptr_t block_addr;
        !           271:     LOCK();
        !           272:     next_block = GC_next_nursery_block;
        !           273:     while(is_pinned[next_block] && next_block < GC_nursery_blocks) {
        !           274:        ++next_block;
        !           275:     }
        !           276:     if (next_block < GC_nursery_blocks) {
        !           277:        block_addr = GC_nursery_start + NURSERY_BLOCK_SIZE * next_block;
        !           278:        GC_next_nursery_block = next_block + 1;
        !           279:        BZERO(GC_nursery_map + next_block *
        !           280:                                (NURSERY_BLOCK_SIZE/NURSERY_WORD_SIZE),
        !           281:              NURSERY_BLOCK_SIZE/NURSERY_WORD_SIZE);
        !           282:        *GC_copy_alloc_state = block_addr;
        !           283:        UNLOCK();
        !           284:     } else {
        !           285:        GC_collect_nursery();
        !           286:        GC_next_nursery_block = 0;
        !           287:        UNLOCK();
        !           288:        get_new_block(s);
        !           289:     }
        !           290: }
        !           291:
        !           292: GC_PTR GC_copying_malloc2(GC_copy_descriptor *d, GC_copy_alloc_state *s) {
        !           293:     size_t sz = GC_SIZE_FROM_DESCRIPTOR(d);
        !           294:     ptrdiff_t offset;
        !           295:     ptr_t result = *s;
        !           296:     ptr_t new = result + sz;
        !           297:     if (new & COPY_BLOCK_MASK <= result & COPY_BLOCK_MASK> {
        !           298:        GC_init_copy_alloc_state(s);
        !           299:        result = *s;
        !           300:        new = result + sz;
        !           301:         GC_ASSERT(new & COPY_BLOCK_MASK > result & COPY_BLOCK_MASK>
        !           302:     }
        !           303:     (struct copy_obj *)result -> descr = d;
        !           304:     (struct copy_obj *)result -> forward = 0;
        !           305:     offset = (result - GC_nursery_start)/NURSERY_WORD_SIZE;
        !           306:     GC_nursery_map[offset] = NURSERY_MAP_NOT_START;
        !           307: }
        !           308:
        !           309: GC_PTR GC_copying_malloc(GC_copy_descriptor *d) {
        !           310: }
        !           311:
        !           312: #endif /* NURSERY */

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