/* * A version of GC_push_all that treats all interior pointers as valid * and scans part of the area immediately, to make sure that saved * register values are not lost. * Cold_gc_frame delimits the stack section that must be scanned * eagerly. A zero value indicates that no eager scanning is needed. * We don't need to worry about the MANUAL_VDB case here, since this * is only called in the single-threaded case. We assume that we * cannot collect between an assignment and the corresponding * GC_dirty() call. */ STATIC void GC_push_all_stack_partially_eager(ptr_t bottom, ptr_t top, ptr_t cold_gc_frame) { #ifndef NEED_FIXUP_POINTER if (GC_all_interior_pointers) { /* Push the hot end of the stack eagerly, so that register values */ /* saved inside GC frames are marked before they disappear. */ /* The rest of the marking can be deferred until later. */ if (0 == cold_gc_frame) { GC_push_all_stack(bottom, top); return; } GC_ASSERT((word)bottom <= (word)cold_gc_frame && (word)cold_gc_frame <= (word)top); # ifdef STACK_GROWS_DOWN GC_push_all(cold_gc_frame - sizeof(ptr_t), top); GC_push_all_eager(bottom, cold_gc_frame); # else /* STACK_GROWS_UP */ GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t)); GC_push_all_eager(cold_gc_frame, top); # endif /* STACK_GROWS_UP */ } else #endif /* else */ { GC_push_all_eager(bottom, top); } # ifdef TRACE_BUF GC_add_trace_entry("GC_push_all_stack", (word)bottom, (word)top); # endif }
/*ARGSUSED*/ STATIC void GC_push_current_stack(ptr_t cold_gc_frame, void * context) { # if defined(THREADS) if (0 == cold_gc_frame) return; # ifdef STACK_GROWS_DOWN GC_push_all_eager(GC_approx_sp(), cold_gc_frame); /* For IA64, the register stack backing store is handled */ /* in the thread-specific code. */ # else GC_push_all_eager(cold_gc_frame, GC_approx_sp()); # endif # else GC_push_all_stack_part_eager_sections(GC_approx_sp(), GC_stackbottom, cold_gc_frame, GC_traced_stack_sect); # ifdef IA64 /* We also need to push the register stack backing store. */ /* This should really be done in the same way as the */ /* regular stack. For now we fudge it a bit. */ /* Note that the backing store grows up, so we can't use */ /* GC_push_all_stack_partially_eager. */ { ptr_t bsp = GC_save_regs_ret_val; ptr_t cold_gc_bs_pointer = bsp - 2048; if (GC_all_interior_pointers && cold_gc_bs_pointer > BACKING_STORE_BASE) { /* Adjust cold_gc_bs_pointer if below our innermost */ /* "traced stack section" in backing store. */ if (GC_traced_stack_sect != NULL && cold_gc_bs_pointer < GC_traced_stack_sect->backing_store_end) cold_gc_bs_pointer = GC_traced_stack_sect->backing_store_end; GC_push_all_register_sections(BACKING_STORE_BASE, cold_gc_bs_pointer, FALSE, GC_traced_stack_sect); GC_push_all_eager(cold_gc_bs_pointer, bsp); } else { GC_push_all_register_sections(BACKING_STORE_BASE, bsp, TRUE /* eager */, GC_traced_stack_sect); } /* All values should be sufficiently aligned that we */ /* don't have to worry about the boundary. */ } # endif # endif /* !THREADS */ }
/* Similar to GC_push_all_stack_sections() but for IA-64 registers store. */ GC_INNER void GC_push_all_register_sections(ptr_t bs_lo, ptr_t bs_hi, int eager, struct GC_traced_stack_sect_s *traced_stack_sect) { while (traced_stack_sect != NULL) { ptr_t frame_bs_lo = traced_stack_sect -> backing_store_end; GC_ASSERT((word)frame_bs_lo <= (word)bs_hi); if (eager) { GC_push_all_eager(frame_bs_lo, bs_hi); } else { GC_push_all_stack(frame_bs_lo, bs_hi); } bs_hi = traced_stack_sect -> saved_backing_store_ptr; traced_stack_sect = traced_stack_sect -> prev; } GC_ASSERT((word)bs_lo <= (word)bs_hi); if (eager) { GC_push_all_eager(bs_lo, bs_hi); } else { GC_push_all_stack(bs_lo, bs_hi); } }