summaryrefslogtreecommitdiff
path: root/mark_rts.c
diff options
context:
space:
mode:
authorivmai <ivmai>2009-09-10 19:38:06 +0200
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 19:06:46 +0200
commit7d41ef96b2a1cf0ebd342de528204647d78c28dc (patch)
treeeb8b1e27b9408ead35af0445d5abdb96fb811ee6 /mark_rts.c
parent644cf3c2f83bd7f6b052d76a2a38fda5a8b6bb8a (diff)
2009-09-10 Ivan Maidanski <ivmai@mail.ru>
(diff113) * include/gc.h (GC_has_static_roots_func): New typedef (user filter callback). * include/gc.h (GC_register_has_static_roots_callback): Use GC_has_static_roots_func type. * dyn_load.c (GC_has_static_roots, GC_register_has_static_roots_callback): Ditto. * dyn_load.c (GC_has_static_roots, GC_register_has_static_roots_callback): Define on all platforms. * dyn_load.c (GC_register_dynlib_callback, GC_register_dynamic_libraries, GC_init_dyld): Replace K&R-style functions definition with the ANSI C one. * dyn_load.c (GC_register_dynlib_callback): Use new local variable "callback" (initialized from GC_has_static_roots) to minimize data races. * dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr, GC_cond_add_roots): Define as STATIC. * mark_rts.c (GC_remove_roots_inner): Ditto. * dyn_load.c (GC_dyld_image_add): Don't call GC_add_roots() for sections smaller than pointer size (just to avoid acquiring the lock unnecessarily). * dyn_load.c (GC_dyld_name_for_hdr): Define unconditionally (not only for DARWIN_DEBUG). * dyn_load.c (GC_dyld_image_add): Replace GC_add_roots() call with LOCK + GC_add_roots_inner() + UNLOCK. * dyn_load.c (GC_dyld_image_add): Call GC_has_static_roots() user callback (if set) holding the lock; if it returns 0 then don't call GC_add_roots_inner() for that region. * dyn_load.c (GC_register_has_static_roots_callback): Put "callback" value to GC_has_static_roots on all platforms. * dyn_load.c (GC_has_static_roots): Update the comments. * include/gc.h (GC_exclude_static_roots, GC_add_roots, GC_remove_roots, GC_register_has_static_roots_callback): Ditto. * include/private/gc_priv.h (struct roots): Ditto. * include/private/gc_priv.h (GC_remove_roots_inner): Move prototype to mark_rts.c and declare it as STATIC. * include/private/gc_priv.h (GC_exclude_static_roots_inner): New prototype. * dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr): Use GC_exclude_static_roots_inner() instead of GC_exclude_static_roots. * misc.c (GC_init_inner): Ditto. * mark_rts.c (GC_exclude_static_roots_inner): New function (move all the code from GC_exclude_static_roots(); add the comment. * mark_rts.c (GC_add_roots_inner, GC_exclude_static_roots_inner): add alignment assertion for the lower bound; add assertion for the lower bound to be less than the upper one. * mark_rts.c (GC_add_roots_inner, GC_exclude_static_roots): Adjust the upper bound (round down to be of a pointer-aligned value); return in case of an empty range. * mark_rts.c (GC_exclude_static_roots): Acquire the lock and call GC_exclude_static_roots_inner(). * mark_rts.c (GC_remove_roots): Quickly check the bounds and return in case of a do-nothing case (before acquiring the lock).
Diffstat (limited to 'mark_rts.c')
-rw-r--r--mark_rts.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/mark_rts.c b/mark_rts.c
index 3554627..830110f 100644
--- a/mark_rts.c
+++ b/mark_rts.c
@@ -158,6 +158,12 @@ GC_API void GC_CALL GC_add_roots(void *b, void *e)
void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp)
{
struct roots * old;
+
+ /* Adjust and check range boundaries for safety */
+ GC_ASSERT((word)b % sizeof(word) == 0);
+ e = (ptr_t)((word)e & ~(sizeof(word) - 1));
+ GC_ASSERT(b <= e);
+ if (b == e) return; /* nothing to do? */
# if defined(MSWIN32) || defined(MSWINCE)
/* Spend the time to ensure that there are no overlapping */
@@ -299,9 +305,16 @@ STATIC void GC_remove_tmp_roots(void)
#endif
#if !defined(MSWIN32) && !defined(MSWINCE)
+STATIC void GC_remove_roots_inner(ptr_t b, ptr_t e);
+
GC_API void GC_CALL GC_remove_roots(void *b, void *e)
{
DCL_LOCK_STATE;
+
+ /* Quick check whether has nothing to do */
+ if ((((word)b + (sizeof(word) - 1)) & ~(sizeof(word) - 1)) >=
+ ((word)e & ~(sizeof(word) - 1)))
+ return;
LOCK();
GC_remove_roots_inner((ptr_t)b, (ptr_t)e);
@@ -309,7 +322,7 @@ GC_API void GC_CALL GC_remove_roots(void *b, void *e)
}
/* Should only be called when the lock is held */
-void GC_remove_roots_inner(ptr_t b, ptr_t e)
+STATIC void GC_remove_roots_inner(ptr_t b, ptr_t e)
{
int i;
for (i = 0; i < n_root_sets; ) {
@@ -396,11 +409,16 @@ STATIC struct exclusion * GC_next_exclusion(ptr_t start_addr)
return GC_excl_table + low;
}
-GC_API void GC_CALL GC_exclude_static_roots(void *start, void *finish)
+/* Should only be called when the lock is held. The range boundaries */
+/* should be properly aligned and valid. */
+void GC_exclude_static_roots_inner(void *start, void *finish)
{
struct exclusion * next;
size_t next_index, i;
+ GC_ASSERT((word)start % sizeof(word) == 0);
+ GC_ASSERT(start < finish);
+
if (0 == GC_excl_table_entries) {
next = 0;
} else {
@@ -429,6 +447,20 @@ GC_API void GC_CALL GC_exclude_static_roots(void *start, void *finish)
++GC_excl_table_entries;
}
+GC_API void GC_CALL GC_exclude_static_roots(void *b, void *e)
+{
+ DCL_LOCK_STATE;
+
+ /* Adjust the upper boundary for safety (round down) */
+ e = (void *)((word)e & ~(sizeof(word) - 1));
+
+ if (b == e) return; /* nothing to exclude? */
+
+ LOCK();
+ GC_exclude_static_roots_inner(b, e);
+ UNLOCK();
+}
+
/* Invoke push_conditional on ranges that are not excluded. */
/*ARGSUSED*/
STATIC void GC_push_conditional_with_exclusions(ptr_t bottom, ptr_t top,