void MR_new_trail_segment(void) { MR_MemoryZones *list; MR_MemoryZone *new_zone; MR_TrailEntry *old_trail_ptr; old_trail_ptr = MR_trail_ptr; /* ** We perform explicit overflow checks so redzones just waste space. */ new_zone = MR_create_or_reuse_zone("trail_segment", MR_trail_size, 0, 0, MR_default_handler); list = MR_GC_malloc_uncollectable_attrib(sizeof(MR_MemoryZones), MR_ALLOC_SITE_RUNTIME); #if defined(MR_DEBUG_TRAIL_SEGMENTS) printf("create new trail segment: old zone: %p, old trail_ptr %p\n", MR_TRAIL_ZONE, MR_trail_ptr); #endif list->MR_zones_head = MR_TRAIL_ZONE; list->MR_zones_tail = MR_PREV_TRAIL_ZONES; MR_PREV_TRAIL_ZONES = list; MR_TRAIL_ZONE = new_zone; MR_trail_ptr = (MR_TrailEntry *) MR_TRAIL_ZONE->MR_zone_min; #if defined(MR_DEBUG_TRAIL_SEGMENTS) printf("create new trail segment: new zone: %p, new trail_ptr %p\n", MR_TRAIL_ZONE, MR_trail_ptr); #endif }
MR_Word * MR_new_detstack_segment(MR_Word *sp, int n) { MR_Word *old_sp; MR_MemoryZones *list; MR_MemoryZone *new_zone; old_sp = sp; // We perform explicit overflow checks so redzones just waste space. new_zone = MR_create_or_reuse_zone("detstack_segment", MR_detstack_size, 0, 0, MR_default_handler); list = MR_GC_malloc_uncollectable_attrib(sizeof(MR_MemoryZones), MR_ALLOC_SITE_RUNTIME); #ifdef MR_DEBUG_STACK_SEGMENTS // If you ever need to debug this again, you will probably want to // change this debugging code to include the information printed out // by MR_new_nondetstack_segment() below. MR_debug_log_message( "create new det segment: old zone: %p, old sp %p, old succip %p", MR_CONTEXT(MR_ctxt_detstack_zone), old_sp, MR_succip); #endif list->MR_zones_head = MR_CONTEXT(MR_ctxt_detstack_zone); list->MR_zones_tail = MR_CONTEXT(MR_ctxt_prev_detstack_zones); MR_CONTEXT(MR_ctxt_prev_detstack_zones) = list; MR_CONTEXT(MR_ctxt_detstack_zone) = new_zone; MR_CONTEXT(MR_ctxt_sp) = MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_min; MR_sp_word = (MR_Word) MR_CONTEXT(MR_ctxt_sp); MR_incr_sp_leaf(2); MR_stackvar(1) = (MR_Word) old_sp; MR_stackvar(2) = (MR_Word) MR_succip; // This may not be for a leaf procedure; we abuse the macro to avoid // a check for whether we have run out of the new detstack segment. // // XXX It is *theoretically* possible for a single stack frame to need // more memory than is available in the whole of the new segment. // However, if this is true, then the program is screwed anyway. // We cannot save it, though we *could* give a meaningful error message // instead of just leaving the program to crash. MR_incr_sp_leaf(n); #ifdef MR_DEBUG_STACK_SEGMENTS MR_debug_log_message( "create new det segment: new zone: %p, new sp %p new succip: %p", MR_CONTEXT(MR_ctxt_detstack_zone), MR_sp, MR_ENTRY(MR_pop_detstack_segment)); #endif return MR_sp; }
MR_Word * MR_new_nondetstack_segment(MR_Word *maxfr, int incr) { MR_Word *sentinel_maxfr; MR_Word *old_maxfr; MR_Word *old_curfr; MR_MemoryZone *new_cur_zone; MR_MemoryZones *new_prev_zones; old_maxfr = maxfr; old_curfr = MR_curfr; #ifdef MR_DEBUG_STACK_SEGMENTS printf("\nadding new nondet stack segment"); printf("\ncontext: %p", &MR_ENGINE(MR_eng_context)); printf("\nold maxfr: "); MR_printnondetstack(stdout, old_maxfr); printf("\nold curfr: "); MR_printnondetstack(stdout, old_curfr); printf("\n"); #endif new_cur_zone = MR_rewind_nondetstack_segments(maxfr); if (new_cur_zone == NULL) { // There is no old segment to reuse in the nondet stack itself, // so allocate a new one (possibly one that was freed earlier). // // Note that we perform explicit overflow checks, so redzones // would just waste space. new_cur_zone = MR_create_or_reuse_zone("nondetstack_segment", MR_nondetstack_size, 0, 0, MR_default_handler); } #ifdef MR_DEBUG_STACK_SEGMENTS printf("\nbefore creating new nondet segment:\n"); MR_print_zone(stdout, MR_CONTEXT(MR_ctxt_nondetstack_zone)); printf("\n"); #endif new_prev_zones = MR_GC_malloc_uncollectable_attrib(sizeof(MR_MemoryZones), MR_ALLOC_SITE_RUNTIME); new_prev_zones->MR_zones_head = MR_CONTEXT(MR_ctxt_nondetstack_zone); new_prev_zones->MR_zones_tail = MR_CONTEXT(MR_ctxt_prev_nondetstack_zones); MR_CONTEXT(MR_ctxt_prev_nondetstack_zones) = new_prev_zones; MR_CONTEXT(MR_ctxt_nondetstack_zone) = new_cur_zone; MR_CONTEXT(MR_ctxt_maxfr) = new_cur_zone->MR_zone_min; MR_maxfr_word = (MR_Word) MR_CONTEXT(MR_ctxt_maxfr); #ifdef MR_DEBUG_STACK_SEGMENTS printf("\nafter creating new nondet segment\n"); printf("new maxfr: "); MR_printnondetstack(stdout, MR_maxfr); printf("\nnew cur zone:\n"); MR_print_zone(stdout, MR_CONTEXT(MR_ctxt_nondetstack_zone)); printf("new prev zones:\n"); MR_print_zones(stdout, MR_CONTEXT(MR_ctxt_prev_nondetstack_zones)); printf("\n"); fflush(stdout); #endif // The stack trace tracing code needs to know the size of each nondet // stack frame, since it uses the size to classify frames as temp or // ordinary. The size is given by the difference in address between // the address of the frame and the address of the previous frame. // This difference would yield an incorrect size and hence an incorrect // frame classification if a temp frame were allowed to have a frame // on a different segment as its immediate predecessor. // // We prevent this by putting an ordinary (i.e. non-temp) frame at the // bottom of every new nondet stack segment as a sentinel. We hand-build // this frame, since it is not an "ordinary" ordinary frame. It is not // created by a call, so it has no meaningful success continuation, // and since it does not make any calls, no other frame's success // continuation can point to it either. // // We store three pieces of information in the sentinel frame. // // - The maxfr at the time the sentinel frame was created, which we store // in the prevfr slot. This is actually the address of the logically // previous frame, so we are using the slot for its intended purpose, // but the difference between the addresses of the two frames is NOT // the size of the sentinel frame. // // - The curfr at the time the sentinel frame was created, which we store // in the succfr slot. This is NOT actually the frame of the success // continuation; we can store it there because this frame HAS no // meaningful success continuation, so the slot is not needed for its // intended purpose. // // - The address of the MR_MemoryZone structure of the zone containing // the sentinel frame, which we store in framevar 1. This is used by // the code of MR_pop_nondetstack_segment. sentinel_maxfr = MR_maxfr + (MR_NONDET_FIXED_SIZE + 1); MR_prevfr_slot_word(sentinel_maxfr) = (MR_Word) old_maxfr; MR_succfr_slot_word(sentinel_maxfr) = (MR_Word) old_curfr; MR_succip_slot_word(sentinel_maxfr) = (MR_Word) MR_ENTRY(MR_do_not_reached); MR_redofr_slot_word(sentinel_maxfr) = (MR_Word) sentinel_maxfr; MR_redoip_slot_word(sentinel_maxfr) = (MR_Word) MR_ENTRY(MR_pop_nondetstack_segment); MR_based_framevar(sentinel_maxfr, 1) = (MR_Word) new_cur_zone; #ifdef MR_DEBUG_STACK_SEGMENTS printf("creating sentinel frame:\n"); printf("sentinel_maxfr: "); MR_printnondetstack(stdout, sentinel_maxfr); printf("\nsentinel frame's prevfr slot: "); MR_printnondetstack(stdout, MR_prevfr_slot(sentinel_maxfr)); printf("\nsentinel frame's succfr slot: "); MR_printnondetstack(stdout, MR_succfr_slot(sentinel_maxfr)); printf("\nsentinel frame's redofr slot: "); MR_printnondetstack(stdout, MR_redofr_slot(sentinel_maxfr)); printf("\n"); #endif // Reserve space for the new nondet stack frame on top of the // sentinel frame. MR_maxfr_word = (MR_Word) (sentinel_maxfr + incr); #ifdef MR_DEBUG_STACK_SEGMENTS printf("after creating sentinel frame and reserving %d words:\n", incr); printf("new maxfr: "); MR_printnondetstack(stdout, MR_maxfr); printf("\n"); fflush(stdout); #endif return MR_maxfr; }