diff options
author | Mirco Bauer <meebey@meebey.net> | 2013-03-01 05:57:24 +0100 |
---|---|---|
committer | Mirco Bauer <meebey@meebey.net> | 2013-03-01 05:57:24 +0100 |
commit | 422ee0e1d56ae748ac12a51c1d5e9f050587c017 (patch) | |
tree | 75b6de740428982dd3f47303eadebacc2e8f080b /libgc | |
parent | 81be09480c3549b42ca79a6085529267c677de03 (diff) | |
download | mono-422ee0e1d56ae748ac12a51c1d5e9f050587c017.tar.gz |
Imported Upstream version 3.0.6+dfsgupstream/3.0.6+dfsg
Diffstat (limited to 'libgc')
-rwxr-xr-x | libgc/configure | 76 | ||||
-rw-r--r-- | libgc/configure.in | 16 | ||||
-rw-r--r-- | libgc/darwin_stop_world.c | 4 | ||||
-rw-r--r-- | libgc/finalize.c | 231 | ||||
-rw-r--r-- | libgc/include/gc.h | 8 | ||||
-rw-r--r-- | libgc/include/private/gc_locks.h | 8 | ||||
-rw-r--r-- | libgc/include/private/gcconfig.h | 5 | ||||
-rw-r--r-- | libgc/pthread_support.c | 2 |
8 files changed, 258 insertions, 92 deletions
diff --git a/libgc/configure b/libgc/configure index 884af0cf6c..92b8af475c 100755 --- a/libgc/configure +++ b/libgc/configure @@ -5076,6 +5076,42 @@ else fi +# Check if the GCC builtin __sync_bool_compare_and_swap is available. +# It is preferred in gc_locks.h for PPC as GCC 4.4 has a problem with the inline assembly there. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_bool_compare_and_swap" >&5 +$as_echo_n "checking for __sync_bool_compare_and_swap... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +volatile unsigned int foo = 0; +int main(int argc, char** argv) { + unsigned int r1 = __sync_bool_compare_and_swap(&foo, 0, 1); + return 0; +} + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +$as_echo "#define HAS___SYNC_BOOL_COMPARE_AND_SWAP 1" >>confdefs.h + + +else + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xlc" >&5 $as_echo_n "checking for xlc... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5953,13 +5989,13 @@ if ${lt_cv_nm_interface+:} false; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5956: $ac_compile\"" >&5) + (eval echo "\"\$as_me:5992: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5959: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:5995: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5962: output\"" >&5) + (eval echo "\"\$as_me:5998: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -7164,7 +7200,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 7167 "configure"' > conftest.$ac_ext + echo '#line 7203 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -9186,11 +9222,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9189: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9225: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9193: \$? = $ac_status" >&5 + echo "$as_me:9229: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9525,11 +9561,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9528: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9564: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9532: \$? = $ac_status" >&5 + echo "$as_me:9568: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9630,11 +9666,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9633: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9669: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9637: \$? = $ac_status" >&5 + echo "$as_me:9673: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9685,11 +9721,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9688: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9724: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9692: \$? = $ac_status" >&5 + echo "$as_me:9728: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -12053,7 +12089,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12056 "configure" +#line 12092 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12149,7 +12185,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12152 "configure" +#line 12188 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14105,11 +14141,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14108: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14144: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14112: \$? = $ac_status" >&5 + echo "$as_me:14148: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -14204,11 +14240,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14207: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14243: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14211: \$? = $ac_status" >&5 + echo "$as_me:14247: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14256,11 +14292,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14259: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14295: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14263: \$? = $ac_status" >&5 + echo "$as_me:14299: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized diff --git a/libgc/configure.in b/libgc/configure.in index be6f6d4259..837e2cb9f1 100644 --- a/libgc/configure.in +++ b/libgc/configure.in @@ -217,6 +217,22 @@ case "$host" in esac AM_CONDITIONAL(POWERPC_DARWIN,test x$powerpc_darwin = xtrue) +# Check if the GCC builtin __sync_bool_compare_and_swap is available. +# It is preferred in gc_locks.h for PPC as GCC 4.4 has a problem with the inline assembly there. +AC_MSG_CHECKING(for __sync_bool_compare_and_swap) +AC_TRY_COMPILE([],[ +volatile unsigned int foo = 0; +int main(int argc, char** argv) { + unsigned int r1 = __sync_bool_compare_and_swap(&foo, 0, 1); + return 0; +} +], [ +AC_MSG_RESULT(yes) +AC_DEFINE(HAS___SYNC_BOOL_COMPARE_AND_SWAP) +], [ +AC_MSG_RESULT(no) +]) + AC_MSG_CHECKING(for xlc) AC_TRY_COMPILE([],[ #ifndef __xlC__ diff --git a/libgc/darwin_stop_world.c b/libgc/darwin_stop_world.c index a1051f5ac4..a53cda354a 100644 --- a/libgc/darwin_stop_world.c +++ b/libgc/darwin_stop_world.c @@ -115,7 +115,7 @@ void GC_push_all_stacks() { if(r != KERN_SUCCESS) continue; #if defined(I386) -#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 +#if defined (TARGET_IOS) || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) lo = state.__esp; @@ -391,7 +391,7 @@ void GC_push_all_stacks() { (natural_t *)&info, &outCount); if(r != KERN_SUCCESS) continue; -#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 +#if defined (TARGET_IOS) || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) lo = (void*)info.__esp; hi = (ptr_t)FindTopOfStack(info.__esp); diff --git a/libgc/finalize.c b/libgc/finalize.c index 893f825976..c5068c0a0d 100644 --- a/libgc/finalize.c +++ b/libgc/finalize.c @@ -46,7 +46,7 @@ struct hash_chain_entry { unsigned GC_finalization_failures = 0; /* Number of finalization requests that failed for lack of memory. */ -static struct disappearing_link { +struct disappearing_link { struct hash_chain_entry prolog; # define dl_hidden_link prolog.hidden_key /* Field to be cleared. */ @@ -54,15 +54,23 @@ static struct disappearing_link { # define dl_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y) word dl_hidden_obj; /* Pointer to object base */ -} **dl_head = 0; +}; + +struct dl_hashtbl_s { + struct disappearing_link **head; + signed_word log_size; + word entries; +}; + +/* Forward decls. */ +static int GC_register_disappearing_link_inner(struct dl_hashtbl_s *dl_hashtbl, GC_PTR * link, GC_PTR obj); +static int GC_unregister_disappearing_link_inner(struct dl_hashtbl_s *dl_hashtbl, GC_PTR * link); -static signed_word log_dl_table_size = -1; - /* Binary log of */ - /* current size of array pointed to by dl_head. */ - /* -1 ==> size is 0. */ +static struct dl_hashtbl_s GC_dl_hashtbl = { + /* head */ NULL, /* log_size */ -1, /* entries */ 0 }; + +static struct dl_hashtbl_s GC_ll_hashtbl = { NULL, -1, 0 }; -word GC_dl_entries = 0; /* Number of entries currently in disappearing */ - /* link table. */ static struct finalizable_object { struct hash_chain_entry prolog; @@ -87,7 +95,10 @@ word GC_fo_entries = 0; void GC_push_finalizer_structures GC_PROTO((void)) { - GC_push_all((ptr_t)(&dl_head), (ptr_t)(&dl_head) + sizeof(word)); + GC_push_all((ptr_t)(&GC_ll_hashtbl.head), + (ptr_t)(&GC_ll_hashtbl.head) + sizeof(word)); + GC_push_all((ptr_t)(&GC_dl_hashtbl.head), + (ptr_t)(&GC_dl_hashtbl.head) + sizeof(word)); GC_push_all((ptr_t)(&fo_head), (ptr_t)(&fo_head) + sizeof(word)); GC_push_all((ptr_t)(&GC_finalize_now), (ptr_t)(&GC_finalize_now) + sizeof(word)); @@ -158,7 +169,19 @@ signed_word * log_size_ptr; GC_PTR * link; GC_PTR obj; # endif +{ + return GC_register_disappearing_link_inner(&GC_dl_hashtbl, link, obj); +} +# if defined(__STDC__) || defined(__cplusplus) + static int GC_register_disappearing_link_inner(struct dl_hashtbl_s *dl_hashtbl, GC_PTR * link, + GC_PTR obj) +# else + static int GC_register_disappearing_link_inner(dl_hashtbl, link, obj) + struct dl_hashtbl_s *dl_hashtbl + GC_PTR * link; + GC_PTR obj; +# endif { struct disappearing_link *curr_dl; int index; @@ -171,26 +194,26 @@ signed_word * log_size_ptr; DISABLE_SIGNALS(); LOCK(); # endif - if (log_dl_table_size == -1 - || GC_dl_entries > ((word)1 << log_dl_table_size)) { + if (dl_hashtbl -> log_size == -1 + || dl_hashtbl -> entries > ((word)1 << dl_hashtbl -> log_size)) { # ifndef THREADS DISABLE_SIGNALS(); # endif - GC_grow_table((struct hash_chain_entry ***)(&dl_head), - &log_dl_table_size); + GC_grow_table((struct hash_chain_entry ***)(&dl_hashtbl -> head), + &dl_hashtbl -> log_size); # ifdef CONDPRINT if (GC_print_stats) { GC_printf1("Grew dl table to %lu entries\n", - (unsigned long)(1 << log_dl_table_size)); + (unsigned long)(1 << dl_hashtbl -> log_size)); } # endif # ifndef THREADS ENABLE_SIGNALS(); # endif } - index = HASH2(link, log_dl_table_size); - curr_dl = dl_head[index]; - for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = dl_next(curr_dl)) { + index = HASH2(link, dl_hashtbl -> log_size); + curr_dl = dl_hashtbl -> head[index]; + for (curr_dl = dl_hashtbl -> head[index]; curr_dl != 0; curr_dl = dl_next(curr_dl)) { if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) { curr_dl -> dl_hidden_obj = HIDE_POINTER(obj); # ifdef THREADS @@ -221,9 +244,9 @@ signed_word * log_size_ptr; } new_dl -> dl_hidden_obj = HIDE_POINTER(obj); new_dl -> dl_hidden_link = HIDE_POINTER(link); - dl_set_next(new_dl, dl_head[index]); - dl_head[index] = new_dl; - GC_dl_entries++; + dl_set_next(new_dl, dl_hashtbl -> head[index]); + dl_hashtbl -> head[index] = new_dl; + dl_hashtbl -> entries++; # ifdef THREADS UNLOCK(); ENABLE_SIGNALS(); @@ -238,23 +261,34 @@ signed_word * log_size_ptr; GC_PTR * link; # endif { + return GC_unregister_disappearing_link_inner(&GC_dl_hashtbl, link); +} + +# if defined(__STDC__) || defined(__cplusplus) + static int GC_unregister_disappearing_link_inner(struct dl_hashtbl_s *dl_hashtbl, GC_PTR * link) +# else + static int GC_unregister_disappearing_link_inner(dl_hashtbl, link) + struct dl_hashtbl_s *dl_hashtbl; + GC_PTR * link; +# endif +{ struct disappearing_link *curr_dl, *prev_dl; int index; DCL_LOCK_STATE; DISABLE_SIGNALS(); LOCK(); - index = HASH2(link, log_dl_table_size); + index = HASH2(link, dl_hashtbl->log_size); if (((unsigned long)link & (ALIGNMENT-1))) goto out; - prev_dl = 0; curr_dl = dl_head[index]; + prev_dl = 0; curr_dl = dl_hashtbl -> head[index]; while (curr_dl != 0) { if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) { if (prev_dl == 0) { - dl_head[index] = dl_next(curr_dl); + dl_hashtbl -> head[index] = dl_next(curr_dl); } else { dl_set_next(prev_dl, dl_next(curr_dl)); } - GC_dl_entries--; + dl_hashtbl -> entries--; UNLOCK(); ENABLE_SIGNALS(); # ifdef DBG_HDRS_ALL @@ -273,6 +307,28 @@ out: return(0); } + +# if defined(__STDC__) || defined(__cplusplus) + int GC_register_long_link(GC_PTR * link, GC_PTR obj) +# else + int GC_register_long_link(link, obj) + GC_PTR * link; + GC_PTR obj; +# endif +{ + return GC_register_disappearing_link_inner(&GC_ll_hashtbl, link, obj); +} + +# if defined(__STDC__) || defined(__cplusplus) + int GC_unregister_long_link(GC_PTR * link) +# else + int GC_unregister_long_link(link) + GC_PTR * link; +# endif +{ + return GC_unregister_disappearing_link_inner(&GC_ll_hashtbl, link); +} + /* Possible finalization_marker procedures. Note that mark stack */ /* overflow is handled by the caller, and is not a disaster. */ GC_API void GC_normal_finalize_mark_proc(p) @@ -512,23 +568,37 @@ finalization_mark_proc * mp; } #ifndef NO_DEBUGGING + +static void GC_dump_finalization_links(struct dl_hashtbl_s *dl_hashtbl) +{ + struct disappearing_link *curr_dl; + ptr_t real_ptr, real_link; + size_t dl_size = dl_hashtbl->log_size == -1 ? 0 : + 1 << dl_hashtbl->log_size; + int i; + + for (i = 0; i < dl_size; i++) { + for (curr_dl = dl_hashtbl -> head[i]; curr_dl != 0; + curr_dl = dl_next(curr_dl)) { + real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj); + real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link); + GC_printf2("Object: %lx, link: %lx\n", real_ptr, real_link); + } + } +} + void GC_dump_finalization() { - struct disappearing_link * curr_dl; struct finalizable_object * curr_fo; - ptr_t real_ptr, real_link; - int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size); + ptr_t real_ptr; int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size); int i; - GC_printf0("Disappearing links:\n"); - for (i = 0; i < dl_size; i++) { - for (curr_dl = dl_head[i]; curr_dl != 0; curr_dl = dl_next(curr_dl)) { - real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj); - real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link); - GC_printf2("Object: 0x%lx, Link:0x%lx\n", real_ptr, real_link); - } - } + GC_printf0("Disappearing (short) links:\n"); + GC_dump_finalization_links(&GC_dl_hashtbl); + GC_printf0("Disappearing long links:\n"); + GC_dump_finalization_links(&GC_ll_hashtbl); + GC_printf0("Finalizers:\n"); for (i = 0; i < fo_size; i++) { for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) { @@ -539,20 +609,15 @@ void GC_dump_finalization() } #endif -/* Called with world stopped. Cause disappearing links to disappear, */ -/* and invoke finalizers. */ -void GC_finalize() +static void GC_make_disappearing_links_disappear(struct dl_hashtbl_s *dl_hashtbl) { struct disappearing_link * curr_dl, * prev_dl, * next_dl; - struct finalizable_object * curr_fo, * prev_fo, * next_fo; ptr_t real_ptr, real_link; register int i; - int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size); - int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size); - - /* Make disappearing links disappear */ + int dl_size = (dl_hashtbl -> log_size == -1 ) ? 0 : (1 << dl_hashtbl -> log_size); + for (i = 0; i < dl_size; i++) { - curr_dl = dl_head[i]; + curr_dl = dl_hashtbl -> head[i]; prev_dl = 0; while (curr_dl != 0) { real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj); @@ -561,12 +626,12 @@ void GC_finalize() *(word *)real_link = 0; next_dl = dl_next(curr_dl); if (prev_dl == 0) { - dl_head[i] = next_dl; + dl_hashtbl -> head[i] = next_dl; } else { dl_set_next(prev_dl, next_dl); } GC_clear_mark_bit((ptr_t)curr_dl); - GC_dl_entries--; + dl_hashtbl -> entries--; curr_dl = next_dl; } else { prev_dl = curr_dl; @@ -574,6 +639,50 @@ void GC_finalize() } } } +} + +static void GC_remove_dangling_disappearing_links(struct dl_hashtbl_s *dl_hashtbl) +{ + struct disappearing_link * curr_dl, * prev_dl, * next_dl; + ptr_t real_ptr, real_link; + register int i; + int dl_size = (dl_hashtbl -> log_size == -1 ) ? 0 : (1 << dl_hashtbl -> log_size); + + for (i = 0; i < dl_size; i++) { + curr_dl = dl_hashtbl -> head[i]; + prev_dl = 0; + while (curr_dl != 0) { + real_link = GC_base((ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link)); + if (real_link != 0 && !GC_is_marked(real_link)) { + next_dl = dl_next(curr_dl); + if (prev_dl == 0) { + dl_hashtbl -> head[i] = next_dl; + } else { + dl_set_next(prev_dl, next_dl); + } + GC_clear_mark_bit((ptr_t)curr_dl); + dl_hashtbl -> entries--; + curr_dl = next_dl; + } else { + prev_dl = curr_dl; + curr_dl = dl_next(curr_dl); + } + } + } +} + +/* Called with world stopped. Cause disappearing links to disappear, */ +/* and invoke finalizers. */ +void GC_finalize() +{ + struct finalizable_object * curr_fo, * prev_fo, * next_fo; + ptr_t real_ptr; + register int i; + int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size); + + /* Make non-tracking disappearing links disappear */ + GC_make_disappearing_links_disappear(&GC_dl_hashtbl); + /* Mark all objects reachable via chains of 1 or more pointers */ /* from finalizable objects. */ GC_ASSERT(GC_mark_state == MS_NONE); @@ -644,27 +753,11 @@ void GC_finalize() } /* Remove dangling disappearing links. */ - for (i = 0; i < dl_size; i++) { - curr_dl = dl_head[i]; - prev_dl = 0; - while (curr_dl != 0) { - real_link = GC_base((ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link)); - if (real_link != 0 && !GC_is_marked(real_link)) { - next_dl = dl_next(curr_dl); - if (prev_dl == 0) { - dl_head[i] = next_dl; - } else { - dl_set_next(prev_dl, next_dl); - } - GC_clear_mark_bit((ptr_t)curr_dl); - GC_dl_entries--; - curr_dl = next_dl; - } else { - prev_dl = curr_dl; - curr_dl = dl_next(curr_dl); - } - } - } + GC_remove_dangling_disappearing_links(&GC_dl_hashtbl); + + /* Make long links disappear and remove dangling ones. */ + GC_make_disappearing_links_disappear(&GC_ll_hashtbl); + GC_remove_dangling_disappearing_links(&GC_ll_hashtbl); } #ifndef JAVA_FINALIZATION_NOT_NEEDED @@ -889,8 +982,8 @@ void GC_print_finalization_stats() struct finalizable_object *fo = GC_finalize_now; size_t ready = 0; - GC_printf2("%lu finalization table entries; %lu disappearing links\n", - GC_fo_entries, GC_dl_entries); + GC_printf3("%lu finalization table entries; %lu/%lu short/long disappearing links alive\n", + GC_fo_entries, (unsigned long)GC_dl_hashtbl.entries, (unsigned long)GC_ll_hashtbl.entries); for (; 0 != fo; fo = fo_next(fo)) ++ready; GC_printf1("%lu objects are eligible for immediate finalization\n", ready); } diff --git a/libgc/include/gc.h b/libgc/include/gc.h index 7e5fd2ed84..123d6cce08 100644 --- a/libgc/include/gc.h +++ b/libgc/include/gc.h @@ -61,6 +61,7 @@ /* Win64 isn't really supported yet, but this is the first step. And */ /* it might cause error messages to show up in more plausible places. */ /* This needs basetsd.h, which is included by windows.h. */ + #include <stdint.h> typedef unsigned __int64 GC_word; typedef __int64 GC_signed_word; #endif @@ -600,6 +601,8 @@ GC_API GC_PTR GC_debug_realloc_replacement # define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p) # define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \ GC_general_register_disappearing_link(link, GC_base(obj)) +# define GC_REGISTER_LONG_LINK(link, obj) \ + GC_register_long_link(link, GC_base(obj)) # define GC_REGISTER_DISPLACEMENT(n) GC_debug_register_displacement(n) # else # define GC_MALLOC(sz) GC_malloc(sz) @@ -622,6 +625,8 @@ GC_API GC_PTR GC_debug_realloc_replacement # define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p) # define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \ GC_general_register_disappearing_link(link, obj) +# define GC_REGISTER_LONG_LINK(link, obj) \ + GC_register_long_link(link, obj) # define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n) # endif /* The following are included because they are often convenient, and */ @@ -761,6 +766,9 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */)); /* Undoes a registration by either of the above two */ /* routines. */ +GC_API int GC_register_long_link GC_PROTO((GC_PTR * /* link */, GC_PTR obj)); +GC_API int GC_unregister_long_link GC_PROTO((GC_PTR * /* link */)); + /* Returns !=0 if GC_invoke_finalizers has something to do. */ GC_API int GC_should_invoke_finalizers GC_PROTO((void)); diff --git a/libgc/include/private/gc_locks.h b/libgc/include/private/gc_locks.h index a45553aa7c..8705d07a1b 100644 --- a/libgc/include/private/gc_locks.h +++ b/libgc/include/private/gc_locks.h @@ -475,6 +475,9 @@ inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, GC_word old, GC_word new_val) { +# if HAS___SYNC_BOOL_COMPARE_AND_SWAP + return __sync_bool_compare_and_swap(addr, old, new_val); +# else unsigned long result, dummy; __asm__ __volatile__( "1:\tldarx %0,0,%5\n" @@ -491,12 +494,16 @@ : "r" (new_val), "r" (old), "2"(addr) : "cr0","memory"); return (GC_bool) result; +# endif } # else /* Returns TRUE if the comparison succeeded. */ inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, GC_word old, GC_word new_val) { +# if HAS___SYNC_BOOL_COMPARE_AND_SWAP + return __sync_bool_compare_and_swap(addr, old, new_val); +# else int result, dummy; __asm__ __volatile__( "1:\tlwarx %0,0,%5\n" @@ -513,6 +520,7 @@ : "r" (new_val), "r" (old), "2"(addr) : "cr0","memory"); return (GC_bool) result; +# endif } # endif # endif /* !GENERIC_COMPARE_AND_SWAP */ diff --git a/libgc/include/private/gcconfig.h b/libgc/include/private/gcconfig.h index da15e905c5..ec53e3a95e 100644 --- a/libgc/include/private/gcconfig.h +++ b/libgc/include/private/gcconfig.h @@ -312,6 +312,7 @@ # define mach_type_known # endif # ifdef DARWIN +# include "TargetConditionals.h" # if defined(__ppc__) || defined(__ppc64__) # define POWERPC # define mach_type_known @@ -320,7 +321,9 @@ # define mach_type_known # define DARWIN_DONT_PARSE_STACK # define OS_TYPE "DARWIN" -# define DYNAMIC_LOADING +# if TARGET_IPHONE_SIMULATOR == 0 +# define DYNAMIC_LOADING +# endif /* XXX: see get_end(3), get_etext() and get_end() should not be used. These aren't used when dyld support is enabled (it is by default) */ # define DATASTART ((ptr_t) get_etext()) diff --git a/libgc/pthread_support.c b/libgc/pthread_support.c index bc31c9733a..ccafb3b116 100644 --- a/libgc/pthread_support.c +++ b/libgc/pthread_support.c @@ -66,6 +66,7 @@ --> Macro replaced by USE_COMPILER_TLS # endif +#ifndef USE_COMPILER_TLS # if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \ defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \ defined(GC_NETBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC) || \ @@ -73,6 +74,7 @@ defined(GC_OPENBSD_THREADS) # define USE_PTHREAD_SPECIFIC # endif +#endif # if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE) # define _POSIX4A_DRAFT10_SOURCE 1 |