Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Unity-Technologies/bdwgc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2018-05-08 20:17:48 +0300
committerIvan Maidanski <ivmai@mail.ru>2018-05-08 20:17:48 +0300
commite849b45c86b96b0e9f75d01a5410413f05a95822 (patch)
tree255adbc04c47e5718c774806cbdb7f84349f337f
parent404b6f264994f0b136a4eba3cb5d5060605a226e (diff)
Fix assertion violation and partial overlapping in remove_roots_subregion
(fix of commit 38d194a) Issue #218 (bdwgc). * mark_rts.c [USE_PROC_FOR_LIBRARIES] (GC_remove_roots_subregion): Update comment; add assertion that b and e pointers are word-aligned; handle also cases of partial overlapping with the existing roots; call GC_rebuild_root_index() only when needed; update existing root instead of removing old and adding new one (where possible); move newly static added root to precede dynamic ones (if any); process all static roots even if an intersection is already found.
-rw-r--r--mark_rts.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/mark_rts.c b/mark_rts.c
index 2997024d..0cd76966 100644
--- a/mark_rts.c
+++ b/mark_rts.c
@@ -379,15 +379,16 @@ STATIC void GC_remove_tmp_roots(void)
#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;
@@ -403,21 +404,56 @@ STATIC void GC_remove_tmp_roots(void)
}
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 */