#include "metadata/sgen-gc.h"
#include "metadata/sgen-gray.h"
#include "metadata/sgen-protocol.h"
+#include "metadata/sgen-pointer-queue.h"
#include "utils/dtrace.h"
#include "utils/mono-counters.h"
static int
tagged_object_hash (MonoObject *o)
{
- return mono_object_hash (tagged_object_get_object (o));
+ return mono_aligned_addr_hash (tagged_object_get_object (o));
}
static gboolean
MonoObject *object;
gpointer dummy;
char *copy;
+ SgenPointerQueue moved_fin_objects;
+
+ sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY);
if (no_finalize)
return;
SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object);
continue;
- } else {
+ } else if (copy != (char*)object) {
/* update pointer */
+ SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
+
+ /* register for reinsertion */
+ sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag));
+
SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object);
- SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag));
+
+ continue;
}
} SGEN_HASH_TABLE_FOREACH_END;
+
+ while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) {
+ sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL);
+ }
+
+ sgen_pointer_queue_free (&moved_fin_objects);
}
SgenHashTable *hash_table = get_finalize_entry_hash_table (generation);
MonoObject *object;
gpointer dummy;
+ SgenPointerQueue moved_fin_objects;
+
+ sgen_pointer_queue_init (&moved_fin_objects, INTERNAL_MEM_TEMPORARY);
if (no_finalize)
return;
SGEN_LOG (5, "Promoting finalization of object %p (%s) (was at %p) to major table", copy, sgen_safe_name (copy), object);
continue;
- } else {
+ } else if (copy != object) {
/* update pointer */
+ SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
+
+ /* register for reinsertion */
+ sgen_pointer_queue_add (&moved_fin_objects, tagged_object_apply (copy, tag));
+
SGEN_LOG (5, "Updating object for finalization: %p (%s) (was at %p)", copy, sgen_safe_name (copy), object);
- SGEN_HASH_TABLE_FOREACH_SET_KEY (tagged_object_apply (copy, tag));
+
+ continue;
}
}
}
} SGEN_HASH_TABLE_FOREACH_END;
+
+ while (!sgen_pointer_queue_is_empty (&moved_fin_objects)) {
+ sgen_hash_table_replace (hash_table, sgen_pointer_queue_pop (&moved_fin_objects), NULL, NULL);
+ }
+
+ sgen_pointer_queue_free (&moved_fin_objects);
}
/* LOCKING: requires that the GC lock is held */
}
#ifdef HEAVY_STATISTICS
-static long long stat_overflow_abort = 0;
-static long long stat_wait_for_processing = 0;
-static long long stat_increment_other_thread = 0;
-static long long stat_index_decremented = 0;
-static long long stat_entry_invalidated = 0;
-static long long stat_success = 0;
+static guint64 stat_overflow_abort = 0;
+static guint64 stat_wait_for_processing = 0;
+static guint64 stat_increment_other_thread = 0;
+static guint64 stat_index_decremented = 0;
+static guint64 stat_entry_invalidated = 0;
+static guint64 stat_success = 0;
#endif
static int
SgenHashTable *hash = get_dislink_hash_table (generation);
SGEN_HASH_TABLE_FOREACH (hash, link, dummy) {
char *object = DISLINK_OBJECT (link);
- if (*link && object && !((MonoObject*)object)->vtable) {
- gboolean free = TRUE;
- if (*link) {
- *link = NULL;
- binary_protocol_dislink_update (link, NULL, 0, 0);
- free = FALSE;
- /*
- * This can happen if finalizers are not ran, i.e. Environment.Exit ()
- * is called from finalizer like in finalizer-abort.cs.
- */
- SGEN_LOG (5, "Disappearing link %p not freed", link);
- }
+ if (object)
+ SGEN_ASSERT (0, ((MonoObject*)object)->vtable, "Can't have objects without vtables.");
- SGEN_HASH_TABLE_FOREACH_REMOVE (free);
+ if (*link && object && ((MonoObject*)object)->vtable->domain == domain) {
+ *link = NULL;
+ binary_protocol_dislink_update (link, NULL, 0, 0);
+ /*
+ * This can happen if finalizers are not ran, i.e. Environment.Exit ()
+ * is called from finalizer like in finalizer-abort.cs.
+ */
+ SGEN_LOG (5, "Disappearing link %p not freed", link);
+
+ /*
+ * FIXME: Why don't we free the entry here?
+ */
+ SGEN_HASH_TABLE_FOREACH_REMOVE (FALSE);
continue;
}
sgen_init_fin_weak_hash (void)
{
#ifdef HEAVY_STATISTICS
- mono_counters_register ("FinWeak Successes", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_success);
- mono_counters_register ("FinWeak Overflow aborts", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_overflow_abort);
- mono_counters_register ("FinWeak Wait for processing", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_wait_for_processing);
- mono_counters_register ("FinWeak Increment other thread", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_increment_other_thread);
- mono_counters_register ("FinWeak Index decremented", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_index_decremented);
- mono_counters_register ("FinWeak Entry invalidated", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_entry_invalidated);
+ mono_counters_register ("FinWeak Successes", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_success);
+ mono_counters_register ("FinWeak Overflow aborts", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_overflow_abort);
+ mono_counters_register ("FinWeak Wait for processing", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wait_for_processing);
+ mono_counters_register ("FinWeak Increment other thread", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_increment_other_thread);
+ mono_counters_register ("FinWeak Index decremented", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_index_decremented);
+ mono_counters_register ("FinWeak Entry invalidated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_entry_invalidated);
#endif
}