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 = table; }
static void null_weak_links_to_dead_objects (SgenBridgeProcessor *processor, int generation) { int i, j; int num_sccs = processor->num_sccs; MonoGCBridgeSCC **api_sccs = processor->api_sccs; 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); 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_if (is_bridge_object_dead, &alive_hash, GENERATION_NURSERY, FALSE); sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_NURSERY, TRUE); if (generation == GENERATION_OLD) { sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_OLD, FALSE); sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_OLD, TRUE); } sgen_hash_table_clean (&alive_hash); }
int finishing_time; DynArray srcs; int scc_index; } HashEntry; typedef struct _SCC { int index; int api_index; int num_bridge_entries; DynArray 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 MonoGCBridgeCallbacks bridge_callbacks; static int current_time; gboolean bridge_processing_in_progress = FALSE; void mono_gc_wait_for_bridge_processing (void) { if (!bridge_processing_in_progress) return; mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_BRIDGE waiting for bridge processing to finish");
return (MonoObject*)((mword)object | (mword)tag_bits); } static int tagged_object_hash (MonoObject *o) { return mono_object_hash (tagged_object_get_object (o)); } static gboolean tagged_object_equals (MonoObject *a, MonoObject *b) { return tagged_object_get_object (a) == tagged_object_get_object (b); } static SgenHashTable minor_finalizable_hash = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_FIN_TABLE, INTERNAL_MEM_FINALIZE_ENTRY, 0, (GHashFunc)tagged_object_hash, (GEqualFunc)tagged_object_equals); static SgenHashTable major_finalizable_hash = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_FIN_TABLE, INTERNAL_MEM_FINALIZE_ENTRY, 0, (GHashFunc)tagged_object_hash, (GEqualFunc)tagged_object_equals); static SgenHashTable* get_finalize_entry_hash_table (int generation) { switch (generation) { case GENERATION_NURSERY: return &minor_finalizable_hash; case GENERATION_OLD: return &major_finalizable_hash; default: g_assert_not_reached (); } }
static gboolean sgen_compare_bridge_processor_results (SgenBridgeProcessor *a, SgenBridgeProcessor *b) { int i; SgenHashTable obj_to_a_scc = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_DEBUG, INTERNAL_MEM_BRIDGE_DEBUG, sizeof (int), mono_aligned_addr_hash, NULL); SgenHashTable b_scc_to_a_scc = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_DEBUG, INTERNAL_MEM_BRIDGE_DEBUG, sizeof (int), g_direct_hash, NULL); MonoGCBridgeXRef *a_xrefs, *b_xrefs; size_t xrefs_alloc_size; // dump_processor_state (a); // dump_processor_state (b); if (a->num_sccs != b->num_sccs) g_error ("SCCS count expected %d but got %d", a->num_sccs, b->num_sccs); if (a->num_xrefs != b->num_xrefs) g_error ("SCCS count expected %d but got %d", a->num_xrefs, b->num_xrefs); /* * First we build a hash of each object in `a` to its respective SCC index within * `a`. Along the way we also assert that no object is more than one SCC. */ for (i = 0; i < a->num_sccs; ++i) { int j; MonoGCBridgeSCC *scc = a->api_sccs [i]; g_assert (scc->num_objs > 0); for (j = 0; j < scc->num_objs; ++j) { GCObject *obj = scc->objs [j]; gboolean new_entry = sgen_hash_table_replace (&obj_to_a_scc, obj, &i, NULL); g_assert (new_entry); } } /* * Now we check whether each of the objects in `b` are in `a`, and whether the SCCs * of `b` contain the same sets of objects as those of `a`. * * While we're doing this, build a hash table to map from `b` SCC indexes to `a` SCC * indexes. */ for (i = 0; i < b->num_sccs; ++i) { MonoGCBridgeSCC *scc = b->api_sccs [i]; MonoGCBridgeSCC *a_scc; int *a_scc_index_ptr; int a_scc_index; int j; gboolean new_entry; g_assert (scc->num_objs > 0); a_scc_index_ptr = (int *)sgen_hash_table_lookup (&obj_to_a_scc, scc->objs [0]); g_assert (a_scc_index_ptr); a_scc_index = *a_scc_index_ptr; //g_print ("A SCC %d -> B SCC %d\n", a_scc_index, i); a_scc = a->api_sccs [a_scc_index]; g_assert (a_scc->num_objs == scc->num_objs); for (j = 1; j < scc->num_objs; ++j) { a_scc_index_ptr = (int *)sgen_hash_table_lookup (&obj_to_a_scc, scc->objs [j]); g_assert (a_scc_index_ptr); g_assert (*a_scc_index_ptr == a_scc_index); } new_entry = sgen_hash_table_replace (&b_scc_to_a_scc, GINT_TO_POINTER (i), &a_scc_index, NULL); g_assert (new_entry); } /* * Finally, check that we have the same xrefs. We do this by making copies of both * xref arrays, and replacing the SCC indexes in the copy for `b` with the * corresponding indexes in `a`. Then we sort both arrays and assert that they're * the same. * * At the same time, check that no xref is self-referential and that there are no * duplicate ones. */ xrefs_alloc_size = a->num_xrefs * sizeof (MonoGCBridgeXRef); a_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG, TRUE); b_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG, TRUE); memcpy (a_xrefs, a->api_xrefs, xrefs_alloc_size); for (i = 0; i < b->num_xrefs; ++i) { MonoGCBridgeXRef *xref = &b->api_xrefs [i]; int *scc_index_ptr; g_assert (xref->src_scc_index != xref->dst_scc_index); scc_index_ptr = (int *)sgen_hash_table_lookup (&b_scc_to_a_scc, GINT_TO_POINTER (xref->src_scc_index)); g_assert (scc_index_ptr); b_xrefs [i].src_scc_index = *scc_index_ptr; scc_index_ptr = (int *)sgen_hash_table_lookup (&b_scc_to_a_scc, GINT_TO_POINTER (xref->dst_scc_index)); g_assert (scc_index_ptr); b_xrefs [i].dst_scc_index = *scc_index_ptr; } qsort (a_xrefs, a->num_xrefs, sizeof (MonoGCBridgeXRef), compare_xrefs); qsort (b_xrefs, a->num_xrefs, sizeof (MonoGCBridgeXRef), compare_xrefs); for (i = 0; i < a->num_xrefs; ++i) { g_assert (a_xrefs [i].src_scc_index == b_xrefs [i].src_scc_index); g_assert (a_xrefs [i].dst_scc_index == b_xrefs [i].dst_scc_index); } sgen_hash_table_clean (&obj_to_a_scc); sgen_hash_table_clean (&b_scc_to_a_scc); sgen_free_internal_dynamic (a_xrefs, xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG); sgen_free_internal_dynamic (b_xrefs, xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG); return TRUE; }
}; typedef struct { gulong num_pins [PIN_TYPE_MAX]; } PinnedClassEntry; typedef struct { gulong num_remsets; } GlobalRemsetClassEntry; static PinStatAddress *pin_stat_addresses = NULL; static size_t pinned_byte_counts [PIN_TYPE_MAX]; static ObjectList *pinned_objects = NULL; static SgenHashTable pinned_class_hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_STATISTICS, INTERNAL_MEM_STAT_PINNED_CLASS, sizeof (PinnedClassEntry), g_str_hash, g_str_equal); static SgenHashTable global_remset_class_hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_STATISTICS, INTERNAL_MEM_STAT_REMSET_CLASS, sizeof (GlobalRemsetClassEntry), g_str_hash, g_str_equal); static void pin_stats_tree_free (PinStatAddress *node) { if (!node) return; pin_stats_tree_free (node->left); pin_stats_tree_free (node->right); sgen_free_internal_dynamic (node, sizeof (PinStatAddress), INTERNAL_MEM_STATISTICS); } void sgen_pin_stats_reset (void) {