#endif /* !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) */
#ifdef USE_PROC_FOR_LIBRARIES
- /* If there is a static root containing [b,e) then replace this root */
- /* [r_start,r_end) with roots [r_start,b) and [e,r_end). */
- /* It is assumed that GC_remove_tmp_roots() is called before this */
- /* function is called repeatedly by GC_register_map_entries(). */
+ /* Remove given range from every static root which intersects with */
+ /* the range. It is assumed GC_remove_tmp_roots is called before */
+ /* this function is called repeatedly by GC_register_map_entries. */
GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e)
{
int i;
+ GC_bool rebuild = FALSE;
GC_ASSERT(I_HOLD_LOCK());
+ GC_ASSERT((word)b % sizeof(word) == 0 && (word)e % sizeof(word) == 0);
for (i = 0; i < n_root_sets; i++) {
ptr_t r_start, r_end;
}
r_start = GC_static_roots[i].r_start;
r_end = GC_static_roots[i].r_end;
- if (EXPECT((word)r_start <= (word)b && (word)e <= (word)r_end, FALSE)) {
+ if (!EXPECT((word)e <= (word)r_start || (word)r_end <= (word)b, TRUE)) {
# ifdef DEBUG_ADD_DEL_ROOTS
GC_log_printf("Removing %p .. %p from root section %d (%p .. %p)\n",
(void *)b, (void *)e,
i, (void *)r_start, (void *)r_end);
# endif
- GC_remove_root_at_pos(i);
- GC_rebuild_root_index();
- if ((word)r_start < (word)b)
- GC_add_roots_inner(r_start, b, FALSE);
- if ((word)e < (word)r_end)
- GC_add_roots_inner(e, r_end, FALSE);
- break;
+ if ((word)r_start < (word)b) {
+ GC_root_size -= r_end - b;
+ GC_static_roots[i].r_end = b;
+ /* No need to rebuild as hash does not use r_end value. */
+ if ((word)e < (word)r_end) {
+ int j;
+
+ if (rebuild) {
+ GC_rebuild_root_index();
+ rebuild = FALSE;
+ }
+ GC_add_roots_inner(e, r_end, FALSE); /* updates n_root_sets */
+ for (j = i + 1; j < n_root_sets; j++)
+ if (GC_static_roots[j].r_tmp)
+ break;
+ if (j < n_root_sets-1 && !GC_static_roots[n_root_sets-1].r_tmp) {
+ /* Exchange the roots to have all temporary ones at the end. */
+ ptr_t tmp_r_start = GC_static_roots[j].r_start;
+ ptr_t tmp_r_end = GC_static_roots[j].r_end;
+
+ GC_static_roots[j].r_start =
+ GC_static_roots[n_root_sets-1].r_start;
+ GC_static_roots[j].r_end = GC_static_roots[n_root_sets-1].r_end;
+ GC_static_roots[j].r_tmp = FALSE;
+ GC_static_roots[n_root_sets-1].r_start = tmp_r_start;
+ GC_static_roots[n_root_sets-1].r_end = tmp_r_end;
+ GC_static_roots[n_root_sets-1].r_tmp = TRUE;
+ rebuild = TRUE;
+ }
+ }
+ } else {
+ if ((word)e < (word)r_end) {
+ GC_root_size -= e - r_start;
+ GC_static_roots[i].r_start = e;
+ } else {
+ GC_remove_root_at_pos(i);
+ i--;
+ }
+ rebuild = TRUE;
+ }
}
}
+ if (rebuild)
+ GC_rebuild_root_index();
}
#endif /* USE_PROC_FOR_LIBRARIES */