DynIntArray xrefs; /* these are incoming, not outgoing */
} SCC;
-static SgenHashTable hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntry), mono_aligned_addr_hash, NULL);
+static SgenHashTable hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_OLD_BRIDGE_HASH_TABLE, INTERNAL_MEM_OLD_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntry), mono_aligned_addr_hash, NULL);
static int current_time;
static gboolean bridge_accounting_enabled = FALSE;
+static SgenBridgeProcessor *bridge_processor;
/* Core functions */
/* public */
static void
enable_accounting (void)
{
+ SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL);
bridge_accounting_enabled = TRUE;
- hash_table = (SgenHashTable)SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL);
+ hash_table = table;
}
static MonoGCBridgeObjectKind
obj_entry = dyn_array_ptr_pop (&dfs_stack);
if (obj_entry) {
+ mword desc;
src = dyn_array_ptr_pop (&dfs_stack);
obj = obj_entry->obj;
start = (char*)obj;
+ desc = sgen_obj_get_descriptor (start);
if (src) {
//g_print ("link %s -> %s\n", sgen_safe_name (src->obj), sgen_safe_name (obj));
DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries)
-static unsigned long step_1, step_2, step_3, step_4, step_5, step_6, step_7, step_8;
+static unsigned long step_1, step_2, step_3, step_4, step_5, step_6;
static int fist_pass_links, second_pass_links, sccs_links;
static int max_sccs_links = 0;
if (!dyn_array_ptr_size (®istered_bridges))
return;
- /*
- * bridge_processing_in_progress must be set with the world
- * stopped. If not there would be race conditions.
- */
- bridge_processing_in_progress = TRUE;
-
SGEN_TV_GETTIME (btv);
/* first DFS pass */
step_2 = SGEN_TV_ELAPSED (btv, atv);
}
-static mono_bool
-is_bridge_object_alive (MonoObject *obj, void *data)
-{
- SgenHashTable *table = data;
- unsigned char *value = sgen_hash_table_lookup (table, obj);
- if (!value)
- return TRUE;
- return *value;
-}
+static int num_registered_bridges, hash_table_size;
static void
-processing_finish (int generation)
+processing_build_callback_data (int generation)
{
int i, j;
int num_sccs, num_xrefs;
int max_entries, max_xrefs;
- int hash_table_size, sccs_size;
+ int sccs_size;
MonoObject *obj;
HashEntry *entry;
- int num_registered_bridges;
HashEntry **all_entries;
MonoGCBridgeSCC **api_sccs;
MonoGCBridgeXRef *api_xrefs;
- SgenHashTable alive_hash = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE, INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE_ENTRY, 1, mono_aligned_addr_hash, NULL);
SGEN_TV_DECLARE (atv);
SGEN_TV_DECLARE (btv);
+ g_assert (bridge_processor->num_sccs == 0 && bridge_processor->num_xrefs == 0);
+ g_assert (!bridge_processor->api_sccs && !bridge_processor->api_xrefs);
+
if (!dyn_array_ptr_size (®istered_bridges))
return;
//g_print ("%d sccs containing bridges - %d max bridge objects - %d max xrefs\n", j, max_entries, max_xrefs);
- /* callback */
-
- bridge_callbacks.cross_references (num_sccs, api_sccs, num_xrefs, api_xrefs);
-
- /* Release for finalization those objects we no longer care. */
- SGEN_TV_GETTIME (btv);
- step_7 = SGEN_TV_ELAPSED (atv, btv);
-
- for (i = 0; i < num_sccs; ++i) {
- unsigned char alive = api_sccs [i]->is_alive ? 1 : 0;
- for (j = 0; j < api_sccs [i]->num_objs; ++j) {
- /* Build hash table for nulling weak links. */
- sgen_hash_table_replace (&alive_hash, api_sccs [i]->objs [j], &alive, NULL);
-
- /* Release for finalization those objects we no longer care. */
- if (!api_sccs [i]->is_alive)
- sgen_mark_bridge_object (api_sccs [i]->objs [j]);
- }
- }
-
- /* Null weak links to dead objects. */
- sgen_null_links_with_predicate (GENERATION_NURSERY, is_bridge_object_alive, &alive_hash);
- if (generation == GENERATION_OLD)
- sgen_null_links_with_predicate (GENERATION_OLD, is_bridge_object_alive, &alive_hash);
+ bridge_processor->num_sccs = num_sccs;
+ bridge_processor->api_sccs = api_sccs;
+ bridge_processor->num_xrefs = num_xrefs;
+ bridge_processor->api_xrefs = api_xrefs;
+}
- sgen_hash_table_clean (&alive_hash);
+static void
+processing_after_callback (int generation)
+{
+ int i, j;
+ int num_sccs = bridge_processor->num_sccs;
+ MonoGCBridgeSCC **api_sccs = bridge_processor->api_sccs;
if (bridge_accounting_enabled) {
for (i = 0; i < num_sccs; ++i) {
}
}
- /* free callback data */
-
- for (i = 0; i < num_sccs; ++i) {
- sgen_free_internal_dynamic (api_sccs [i],
- sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * api_sccs [i]->num_objs,
- INTERNAL_MEM_BRIDGE_DATA);
- }
- sgen_free_internal_dynamic (api_sccs, sizeof (MonoGCBridgeSCC*) * num_sccs, INTERNAL_MEM_BRIDGE_DATA);
-
- sgen_free_internal_dynamic (api_xrefs, sizeof (MonoGCBridgeXRef) * num_xrefs, INTERNAL_MEM_BRIDGE_DATA);
-
- SGEN_TV_GETTIME (atv);
- step_8 = SGEN_TV_ELAPSED (btv, atv);
-
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_BRIDGE num-objects %d num_hash_entries %d sccs size %d init %.2fms df1 %.2fms sort %.2fms dfs2 %.2fms setup-cb %.2fms free-data %.2fms user-cb %.2fms clenanup %.2fms links %d/%d/%d/%d dfs passes %d/%d",
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_OLD_BRIDGE num-objects %d num_hash_entries %d sccs size %d init %.2fms df1 %.2fms sort %.2fms dfs2 %.2fms setup-cb %.2fms free-data %.2fms links %d/%d/%d/%d dfs passes %d/%d",
num_registered_bridges, hash_table_size, dyn_array_scc_size (&sccs),
step_1 / 10000.0f,
step_2 / 10000.0f,
step_4 / 10000.0f,
step_5 / 10000.0f,
step_6 / 10000.0f,
- step_7 / 10000.0f,
- step_8 / 10000.f,
fist_pass_links, second_pass_links, sccs_links, max_sccs_links,
dfs1_passes, dfs2_passes);
step_1 = 0; /* We must cleanup since this value is used as an accumulator. */
fist_pass_links = second_pass_links = sccs_links = max_sccs_links = 0;
dfs1_passes = dfs2_passes = 0;
-
- bridge_processing_in_progress = FALSE;
}
static void
{
collector->reset_data = reset_data;
collector->processing_stw_step = processing_stw_step;
- collector->processing_finish = processing_finish;
+ collector->processing_build_callback_data = processing_build_callback_data;
+ collector->processing_after_callback = processing_after_callback;
collector->class_kind = class_kind;
collector->register_finalized_object = register_finalized_object;
collector->describe_pointer = describe_pointer;
collector->enable_accounting = enable_accounting;
+
+ bridge_processor = collector;
}
#endif