static void processing_after_callback (int generation) { gint64 curtime; int bridge_count = dyn_array_ptr_size (®istered_bridges); int object_count = object_data_count; int color_count = color_data_count; int scc_count = num_colors_with_bridges; SGEN_TV_GETTIME (curtime); /* cleanup */ cleanup (); cleanup_time = step_timer (&curtime); mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_TAR_BRIDGE bridges %d objects %d colors %d ignored %d sccs %d xref %d cache %d/%d setup %.2fms tarjan %.2fms scc-setup %.2fms gather-xref %.2fms xref-setup %.2fms cleanup %.2fms", bridge_count, object_count, color_count, ignored_objects, scc_count, xref_count, cache_hits, cache_misses, setup_time / 10000.0f, tarjan_time / 10000.0f, scc_setup_time / 10000.0f, gather_xref_time / 10000.0f, xref_setup_time / 10000.0f, cleanup_time / 10000.0f); cache_hits = cache_misses = 0; ignored_objects = 0; bridge_processing_in_progress = FALSE; }
static gint64 step_timer (gint64 *timer) { gint64 curtime, diff; SGEN_TV_GETTIME (curtime); diff = SGEN_TV_ELAPSED (*timer, curtime); *timer = curtime; return diff; }
static void processing_stw_step (void) { int i; int bridge_count; gint64 curtime; if (!dyn_array_ptr_size (®istered_bridges)) return; #if defined (DUMP_GRAPH) printf ("-----------------\n"); #endif /* * 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 (curtime); object_alloc_init (); color_alloc_init (); bridge_count = dyn_array_ptr_size (®istered_bridges); for (i = 0; i < bridge_count ; ++i) register_bridge_object (dyn_array_ptr_get (®istered_bridges, i)); setup_time = step_timer (&curtime); for (i = 0; i < bridge_count; ++i) { ScanData *sd = find_data (dyn_array_ptr_get (®istered_bridges, i)); if (sd->state == INITIAL) { dyn_array_ptr_push (&scan_stack, sd); dfs (); } else { g_assert (sd->state == FINISHED_OFF_STACK); } } tarjan_time = step_timer (&curtime); #if defined (DUMP_GRAPH) printf ("----summary----\n"); printf ("bridges:\n"); for (i = 0; i < bridge_count; ++i) { ScanData *sd = find_data (dyn_array_ptr_get (®istered_bridges, i)); printf ("\t%s (%p) index %d color %p\n", safe_name_bridge (sd->obj), sd->obj, sd->index, sd->color); } dump_color_table (" after tarjan", FALSE); #endif clear_after_processing (); }
void sgen_bridge_processing_finish (int generation) { unsigned long step_8; SGEN_TV_DECLARE (atv); SGEN_TV_DECLARE (btv); bridge_processor.processing_build_callback_data (generation); if (compare_bridge_processors ()) compare_to_bridge_processor.processing_build_callback_data (generation); if (bridge_processor.num_sccs == 0) { g_assert (bridge_processor.num_xrefs == 0); goto after_callback; } bridge_callbacks.cross_references (bridge_processor.num_sccs, bridge_processor.api_sccs, bridge_processor.num_xrefs, bridge_processor.api_xrefs); if (compare_bridge_processors ()) sgen_compare_bridge_processor_results (&bridge_processor, &compare_to_bridge_processor); SGEN_TV_GETTIME (btv); null_weak_links_to_dead_objects (&bridge_processor, generation); free_callback_data (&bridge_processor); if (compare_bridge_processors ()) free_callback_data (&compare_to_bridge_processor); SGEN_TV_GETTIME (atv); step_8 = SGEN_TV_ELAPSED (btv, atv); after_callback: bridge_processor.processing_after_callback (generation); if (compare_bridge_processors ()) compare_to_bridge_processor.processing_after_callback (generation); bridge_processing_in_progress = FALSE; }
static void ms_wait_for_sweep_done (void) { SGEN_TV_DECLARE (atv); SGEN_TV_DECLARE (btv); int result; if (!concurrent_sweep) return; if (!ms_sweep_in_progress) return; SGEN_TV_GETTIME (atv); while ((result = MONO_SEM_WAIT (&ms_sweep_done_semaphore)) != 0) { if (errno != EINTR) g_error ("MONO_SEM_WAIT"); } SGEN_TV_GETTIME (btv); stat_time_wait_for_sweep += SGEN_TV_ELAPSED_MS (atv, btv); g_assert (ms_sweep_in_progress); ms_sweep_in_progress = FALSE; }
static void processing_build_callback_data (int generation) { int j, api_index; MonoGCBridgeSCC **api_sccs; MonoGCBridgeXRef *api_xrefs; gint64 curtime; ColorBucket *cur; 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; SGEN_TV_GETTIME (curtime); /*create API objects */ #if defined (DUMP_GRAPH) printf ("***** API *****\n"); printf ("number of SCCs %d\n", num_colors_with_bridges); #endif /* This is a straightforward translation from colors to the bridge callback format. */ api_sccs = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_colors_with_bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE); api_index = xref_count = 0; for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *cd; for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { int bridges = dyn_array_ptr_size (&cd->bridges); if (!bridges) continue; api_sccs [api_index] = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE); api_sccs [api_index]->is_alive = FALSE; api_sccs [api_index]->num_objs = bridges; cd->api_index = api_index; for (j = 0; j < bridges; ++j) api_sccs [api_index]->objs [j] = dyn_array_ptr_get (&cd->bridges, j); api_index++; } } scc_setup_time = step_timer (&curtime); for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *cd; for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { int bridges = dyn_array_ptr_size (&cd->bridges); if (!bridges) continue; dyn_array_ptr_set_size (&color_merge_array, 0); gather_xrefs (cd); reset_xrefs (cd); dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array); xref_count += dyn_array_ptr_size (&cd->other_colors); } } gather_xref_time = step_timer (&curtime); #if defined (DUMP_GRAPH) printf ("TOTAL XREFS %d\n", xref_count); dump_color_table (" after xref pass", TRUE); #endif api_xrefs = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE); api_index = 0; for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *src; for (src = &cur->data [0]; src < cur->next_data; ++src) { int bridges = dyn_array_ptr_size (&src->bridges); if (!bridges) continue; for (j = 0; j < dyn_array_ptr_size (&src->other_colors); ++j) { ColorData *dest = dyn_array_ptr_get (&src->other_colors, j); g_assert (dyn_array_ptr_size (&dest->bridges)); /* We flattened the color graph, so this must never happen. */ api_xrefs [api_index].src_scc_index = src->api_index; api_xrefs [api_index].dst_scc_index = dest->api_index; ++api_index; } } } g_assert (xref_count == api_index); xref_setup_time = step_timer (&curtime); #if defined (DUMP_GRAPH) printf ("---xrefs:\n"); for (i = 0; i < xref_count; ++i) printf ("\t%d -> %d\n", api_xrefs [i].src_scc_index, api_xrefs [i].dst_scc_index); #endif //FIXME move half of the cleanup to before the bridge callback? bridge_processor->num_sccs = num_colors_with_bridges; bridge_processor->api_sccs = api_sccs; bridge_processor->num_xrefs = xref_count; bridge_processor->api_xrefs = api_xrefs; }