summaryrefslogtreecommitdiff
path: root/libgc
diff options
context:
space:
mode:
authorMirco Bauer <meebey@meebey.net>2013-03-01 05:57:24 +0100
committerMirco Bauer <meebey@meebey.net>2013-03-01 05:57:24 +0100
commit422ee0e1d56ae748ac12a51c1d5e9f050587c017 (patch)
tree75b6de740428982dd3f47303eadebacc2e8f080b /libgc
parent81be09480c3549b42ca79a6085529267c677de03 (diff)
downloadmono-422ee0e1d56ae748ac12a51c1d5e9f050587c017.tar.gz
Imported Upstream version 3.0.6+dfsgupstream/3.0.6+dfsg
Diffstat (limited to 'libgc')
-rwxr-xr-xlibgc/configure76
-rw-r--r--libgc/configure.in16
-rw-r--r--libgc/darwin_stop_world.c4
-rw-r--r--libgc/finalize.c231
-rw-r--r--libgc/include/gc.h8
-rw-r--r--libgc/include/private/gc_locks.h8
-rw-r--r--libgc/include/private/gcconfig.h5
-rw-r--r--libgc/pthread_support.c2
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