X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fsgen-new-bridge.c;h=9d2d2064c16e9993c6dcf6b204c5fb2d0d0b2fbe;hb=3fc2fee18d61305b6b63b61f47c059dc2d5f058a;hp=51b00e96695475d26176387342f33ba37ae13695;hpb=72c15bb6f222184aeeda3c5d4093d698905d29e1;p=mono.git diff --git a/mono/metadata/sgen-new-bridge.c b/mono/metadata/sgen-new-bridge.c index 51b00e96695..a1eb82a714f 100644 --- a/mono/metadata/sgen-new-bridge.c +++ b/mono/metadata/sgen-new-bridge.c @@ -3,38 +3,10 @@ * * Copyright 2011 Novell, Inc (http://www.novell.com) * Copyright 2011 Xamarin Inc (http://www.xamarin.com) - * - * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED - * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. - * - * Permission is hereby granted to use or copy this program - * for any purpose, provided the above notices are retained on all copies. - * Permission to modify the code and to distribute modified code is granted, - * provided the above notices are retained, and a notice that the code was - * modified is included with the above copyright notice. - * - * * Copyright 2001-2003 Ximian, Inc * Copyright 2003-2010 Novell, Inc. * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include "config.h" @@ -44,14 +16,13 @@ #include #include -#include "sgen-gc.h" -#include "sgen-bridge.h" -#include "sgen-hash-table.h" -#include "sgen-qsort.h" +#include "sgen/sgen-gc.h" +#include "sgen-bridge-internals.h" +#include "sgen/sgen-hash-table.h" +#include "sgen/sgen-qsort.h" +#include "sgen/sgen-client.h" #include "tabledefs.h" -#include "utils/mono-logger-internal.h" -#include "utils/mono-time.h" -#include "utils/mono-compiler.h" +#include "utils/mono-logger-internals.h" //#define NEW_XREFS #ifdef NEW_XREFS @@ -94,9 +65,11 @@ typedef struct { /* + * Bridge data for a single managed object + * * FIXME: Optimizations: * - * Don't allocate a scrs array for just one source. Most objects have + * Don't allocate a srcs array for just one source. Most objects have * just one source, so use the srcs pointer itself. */ typedef struct _HashEntry { @@ -109,10 +82,12 @@ typedef struct _HashEntry { struct _HashEntry *forwarded_to; } dfs1; struct { + // Index in sccs array of SCC this object was folded into int scc_index; } dfs2; } v; + // "Source" managed objects pointing at this destination DynPtrArray srcs; } HashEntry; @@ -121,12 +96,19 @@ typedef struct { double weight; } HashEntryWithAccounting; +// The graph of managed objects/HashEntries is reduced to a graph of strongly connected components typedef struct _SCC { int index; int api_index; + + // How many bridged objects does this SCC hold references to? int num_bridge_entries; + gboolean flag; + /* + * Index in global sccs array of SCCs holding pointers to this SCC + * * New and old xrefs are typically mutually exclusive. Only when TEST_NEW_XREFS is * enabled we do both, and compare the results. This should only be done for * debugging, obviously. @@ -139,6 +121,7 @@ typedef struct _SCC { #endif } SCC; +// Maps managed objects to corresponding HashEntry stricts 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 guint32 current_time; @@ -200,7 +183,7 @@ dyn_array_ensure_capacity (DynArray *da, int capacity, int elem_size) while (capacity > da->capacity) da->capacity *= 2; - new_data = sgen_alloc_internal_dynamic (elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA, TRUE); + new_data = (char *)sgen_alloc_internal_dynamic (elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA, TRUE); memcpy (new_data, da->data, elem_size * da->size); if (old_capacity > 0) sgen_free_internal_dynamic (da->data, elem_size * old_capacity, INTERNAL_MEM_BRIDGE_DATA); @@ -277,7 +260,7 @@ dyn_array_int_empty (DynIntArray *da) static void dyn_array_int_add (DynIntArray *da, int x) { - int *p = dyn_array_add (&da->array, sizeof (int)); + int *p = (int *)dyn_array_add (&da->array, sizeof (int)); *p = x; } @@ -375,13 +358,13 @@ dyn_array_ptr_add (DynPtrArray *da, void *ptr) void *ptr0 = da->array.data; void **p0; dyn_array_init (&da->array); - p0 = dyn_array_add (&da->array, sizeof (void*)); + p0 = (void **)dyn_array_add (&da->array, sizeof (void*)); *p0 = ptr0; - p = dyn_array_add (&da->array, sizeof (void*)); + p = (void **)dyn_array_add (&da->array, sizeof (void*)); } else #endif { - p = dyn_array_add (&da->array, sizeof (void*)); + p = (void **)dyn_array_add (&da->array, sizeof (void*)); } *p = ptr; } @@ -432,7 +415,7 @@ dyn_array_scc_size (DynSCCArray *da) static SCC* dyn_array_scc_add (DynSCCArray *da) { - return dyn_array_add (&da->array, sizeof (SCC)); + return (SCC *)dyn_array_add (&da->array, sizeof (SCC)); } static SCC* @@ -466,28 +449,28 @@ enable_accounting (void) } static MonoGCBridgeObjectKind -class_kind (MonoClass *class) +class_kind (MonoClass *klass) { - MonoGCBridgeObjectKind res = bridge_callbacks.bridge_class_kind (class); + MonoGCBridgeObjectKind res = bridge_callbacks.bridge_class_kind (klass); /* If it's a bridge, nothing we can do about it. */ if (res == GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS || res == GC_BRIDGE_OPAQUE_BRIDGE_CLASS) return res; /* Non bridge classes with no pointers will never point to a bridge, so we can savely ignore them. */ - if (!class->has_references) { - SGEN_LOG (6, "class %s is opaque\n", class->name); + if (!klass->has_references) { + SGEN_LOG (6, "class %s is opaque\n", klass->name); return GC_BRIDGE_OPAQUE_CLASS; } /* Some arrays can be ignored */ - if (class->rank == 1) { - MonoClass *elem_class = class->element_class; + if (klass->rank == 1) { + MonoClass *elem_class = klass->element_class; /* FIXME the bridge check can be quite expensive, cache it at the class level. */ /* An array of a sealed type that is not a bridge will never get to a bridge */ if ((elem_class->flags & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) { - SGEN_LOG (6, "class %s is opaque\n", class->name); + SGEN_LOG (6, "class %s is opaque\n", klass->name); return GC_BRIDGE_OPAQUE_CLASS; } } @@ -498,7 +481,7 @@ class_kind (MonoClass *class) static HashEntry* get_hash_entry (MonoObject *obj, gboolean *existing) { - HashEntry *entry = sgen_hash_table_lookup (&hash_table, obj); + HashEntry *entry = (HashEntry *)sgen_hash_table_lookup (&hash_table, obj); HashEntry new_entry; if (entry) { @@ -516,7 +499,7 @@ get_hash_entry (MonoObject *obj, gboolean *existing) sgen_hash_table_replace (&hash_table, obj, &new_entry, NULL); - return sgen_hash_table_lookup (&hash_table, obj); + return (HashEntry *)sgen_hash_table_lookup (&hash_table, obj); } static void @@ -528,12 +511,12 @@ add_source (HashEntry *entry, HashEntry *src) static void free_data (void) { - MonoObject *obj; + MonoObject *obj G_GNUC_UNUSED; HashEntry *entry; int total_srcs = 0; int max_srcs = 0; - SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) { + SGEN_HASH_TABLE_FOREACH (&hash_table, MonoObject *, obj, HashEntry *, entry) { int entry_size = dyn_array_ptr_size (&entry->srcs); total_srcs += entry_size; if (entry_size > max_srcs) @@ -626,7 +609,7 @@ static int dfs1_passes, dfs2_passes; #undef HANDLE_PTR #define HANDLE_PTR(ptr,obj) do { \ - MonoObject *dst = (MonoObject*)*(ptr); \ + GCObject *dst = (GCObject*)*(ptr); \ if (dst && object_needs_expansion (&dst)) { \ ++num_links; \ dyn_array_ptr_push (&dfs_stack, obj_entry); \ @@ -648,10 +631,10 @@ dfs1 (HashEntry *obj_entry) char *start; ++dfs1_passes; - obj_entry = dyn_array_ptr_pop (&dfs_stack); + obj_entry = (HashEntry *)dyn_array_ptr_pop (&dfs_stack); if (obj_entry) { /* obj_entry needs to be expanded */ - src = dyn_array_ptr_pop (&dfs_stack); + src = (HashEntry *)dyn_array_ptr_pop (&dfs_stack); if (src) g_assert (!src->v.dfs1.forwarded_to); @@ -665,7 +648,7 @@ dfs1 (HashEntry *obj_entry) if (!obj_entry->v.dfs1.is_visited) { int num_links = 0; - mword desc = sgen_obj_get_descriptor (start); + mword desc = sgen_obj_get_descriptor_safe (obj); obj_entry->v.dfs1.is_visited = 1; @@ -673,7 +656,7 @@ dfs1 (HashEntry *obj_entry) dyn_array_ptr_push (&dfs_stack, obj_entry); dyn_array_ptr_push (&dfs_stack, NULL); -#include "sgen-scan-object.h" +#include "sgen/sgen-scan-object.h" /* * We can remove non-bridge objects with a single outgoing @@ -687,8 +670,8 @@ dfs1 (HashEntry *obj_entry) */ #ifdef OPTIMIZATION_FORWARD if (!obj_entry->is_bridge && num_links == 1) { - HashEntry *dst_entry = dyn_array_ptr_pop (&dfs_stack); - HashEntry *obj_entry_again = dyn_array_ptr_pop (&dfs_stack); + HashEntry *dst_entry = (HashEntry *)dyn_array_ptr_pop (&dfs_stack); + HashEntry *obj_entry_again = (HashEntry *)dyn_array_ptr_pop (&dfs_stack); g_assert (obj_entry_again == obj_entry); g_assert (!dst_entry->v.dfs1.forwarded_to); if (obj_entry != dst_entry) { @@ -710,7 +693,7 @@ dfs1 (HashEntry *obj_entry) } else { /* obj_entry needs to be finished */ - obj_entry = dyn_array_ptr_pop (&dfs_stack); + obj_entry = (HashEntry *)dyn_array_ptr_pop (&dfs_stack); //g_print ("finish %s\n", sgen_safe_name (obj_entry->obj)); register_finishing_time (obj_entry, ++current_time); @@ -839,7 +822,7 @@ dfs2 (HashEntry *entry) dyn_array_ptr_push (&dfs_stack, entry); do { - entry = dyn_array_ptr_pop (&dfs_stack); + entry = (HashEntry *)dyn_array_ptr_pop (&dfs_stack); ++dfs2_passes; if (entry->v.dfs2.scc_index >= 0) { @@ -911,7 +894,7 @@ dump_graph (void) MonoObject *obj; HashEntry *entry; size_t prefix_len = strlen (dump_prefix); - char *filename = alloca(prefix_len + 64); + char *filename = (char *)alloca (prefix_len + 64); FILE *file; int edge_id = 0; @@ -932,18 +915,18 @@ dump_graph (void) "\n"); fprintf (file, "\n"); - SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) { - MonoVTable *vt = (MonoVTable*) SGEN_LOAD_VTABLE (obj); + SGEN_HASH_TABLE_FOREACH (&hash_table, MonoObject *, obj, HashEntry *, entry) { + MonoVTable *vt = SGEN_LOAD_VTABLE (obj); fprintf (file, "\n", obj, vt->klass->name_space, vt->klass->name, entry->is_bridge ? "true" : "false"); } SGEN_HASH_TABLE_FOREACH_END; fprintf (file, "\n"); fprintf (file, "\n"); - SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) { + SGEN_HASH_TABLE_FOREACH (&hash_table, MonoObject *, obj, HashEntry *, entry) { int i; for (i = 0; i < dyn_array_ptr_size (&entry->srcs); ++i) { - HashEntry *src = dyn_array_ptr_get (&entry->srcs, i); + HashEntry *src = (HashEntry *)dyn_array_ptr_get (&entry->srcs, i); fprintf (file, "\n", edge_id++, sgen_hash_table_key_for_value_pointer (src), obj); } } SGEN_HASH_TABLE_FOREACH_END; @@ -969,12 +952,12 @@ compare_hash_entries (const HashEntry *e1, const HashEntry *e2) DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries) -static unsigned long step_1, step_2, step_3, step_4, step_5, step_6; +static gint64 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; static void -register_finalized_object (MonoObject *obj) +register_finalized_object (GCObject *obj) { g_assert (sgen_need_bridge_processing ()); dyn_array_ptr_push (®istered_bridges, obj); @@ -991,7 +974,7 @@ processing_stw_step (void) { int i; int bridge_count; - MonoObject *obj; + MonoObject *obj G_GNUC_UNUSED; HashEntry *entry; SGEN_TV_DECLARE (atv); SGEN_TV_DECLARE (btv); @@ -1018,13 +1001,13 @@ processing_stw_step (void) */ 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)); + register_bridge_object ((MonoObject *)dyn_array_ptr_get (®istered_bridges, i)); for (i = 0; i < bridge_count; ++i) - dfs1 (get_hash_entry (dyn_array_ptr_get (®istered_bridges, i), NULL)); + dfs1 (get_hash_entry ((MonoObject *)dyn_array_ptr_get (®istered_bridges, i), NULL)); /* Remove all forwarded objects. */ - SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) { + SGEN_HASH_TABLE_FOREACH (&hash_table, MonoObject *, obj, HashEntry *, entry) { if (entry->v.dfs1.forwarded_to) { g_assert (dyn_array_ptr_size (&entry->srcs) == 0); SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE); @@ -1047,8 +1030,7 @@ processing_build_callback_data (int generation) int i, j; int num_sccs, num_xrefs; int max_entries, max_xrefs; - int sccs_size; - MonoObject *obj; + MonoObject *obj G_GNUC_UNUSED; HashEntry *entry; HashEntry **all_entries; MonoGCBridgeSCC **api_sccs; @@ -1068,10 +1050,10 @@ processing_build_callback_data (int generation) /* alloc and fill array of all entries */ - all_entries = sgen_alloc_internal_dynamic (sizeof (HashEntry*) * hash_table.num_entries, INTERNAL_MEM_BRIDGE_DATA, TRUE); + all_entries = (HashEntry **)sgen_alloc_internal_dynamic (sizeof (HashEntry*) * hash_table.num_entries, INTERNAL_MEM_BRIDGE_DATA, TRUE); j = 0; - SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) { + SGEN_HASH_TABLE_FOREACH (&hash_table, MonoObject *, obj, HashEntry *, entry) { g_assert (entry->v.dfs1.finishing_time > 0); all_entries [j++] = entry; fist_pass_links += dyn_array_ptr_size (&entry->srcs); @@ -1082,7 +1064,7 @@ processing_build_callback_data (int generation) /* sort array according to decreasing finishing time */ qsort_hash_entries (all_entries, hash_table.num_entries); - SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) { + SGEN_HASH_TABLE_FOREACH (&hash_table, MonoObject *, obj, HashEntry *, entry) { entry->v.dfs2.scc_index = -1; } SGEN_HASH_TABLE_FOREACH_END; @@ -1203,14 +1185,12 @@ processing_build_callback_data (int generation) HashEntryWithAccounting *entry = (HashEntryWithAccounting*)all_entries [i]; if (entry->entry.is_bridge) { MonoObject *obj = sgen_hash_table_key_for_value_pointer (entry); - MonoClass *klass = ((MonoVTable*)SGEN_LOAD_VTABLE (obj))->klass; + MonoClass *klass = SGEN_LOAD_VTABLE (obj)->klass; mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "OBJECT %s::%s (%p) weight %f", klass->name_space, klass->name, obj, entry->weight); } } } - sccs_size = dyn_array_scc_size (&sccs); - for (i = 0; i < hash_table.num_entries; ++i) { HashEntry *entry = all_entries [i]; second_pass_links += dyn_array_ptr_size (&entry->srcs); @@ -1235,7 +1215,7 @@ processing_build_callback_data (int generation) max_sccs_links = MAX (max_sccs_links, dyn_array_int_size (&scc->XREFS)); } - api_sccs = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_sccs, INTERNAL_MEM_BRIDGE_DATA, TRUE); + api_sccs = (MonoGCBridgeSCC **)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_sccs, INTERNAL_MEM_BRIDGE_DATA, TRUE); num_xrefs = 0; j = 0; for (i = 0; i < dyn_array_scc_size (&sccs); ++i) { @@ -1243,7 +1223,7 @@ processing_build_callback_data (int generation) if (!scc->num_bridge_entries) continue; - api_sccs [j] = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * scc->num_bridge_entries, INTERNAL_MEM_BRIDGE_DATA, TRUE); + api_sccs [j] = (MonoGCBridgeSCC *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * scc->num_bridge_entries, INTERNAL_MEM_BRIDGE_DATA, TRUE); api_sccs [j]->is_alive = FALSE; api_sccs [j]->num_objs = scc->num_bridge_entries; scc->num_bridge_entries = 0; @@ -1252,14 +1232,14 @@ processing_build_callback_data (int generation) num_xrefs += dyn_array_int_size (&scc->XREFS); } - SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) { + SGEN_HASH_TABLE_FOREACH (&hash_table, MonoObject *, obj, HashEntry *, entry) { if (entry->is_bridge) { SCC *scc = dyn_array_scc_get_ptr (&sccs, entry->v.dfs2.scc_index); api_sccs [scc->api_index]->objs [scc->num_bridge_entries++] = sgen_hash_table_key_for_value_pointer (entry); } } SGEN_HASH_TABLE_FOREACH_END; - api_xrefs = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * num_xrefs, INTERNAL_MEM_BRIDGE_DATA, TRUE); + api_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * num_xrefs, INTERNAL_MEM_BRIDGE_DATA, TRUE); j = 0; for (i = 0; i < dyn_array_scc_size (&sccs); ++i) { int k; @@ -1328,12 +1308,14 @@ processing_after_callback (int generation) if (bridge_accounting_enabled) { for (i = 0; i < num_sccs; ++i) { - for (j = 0; j < api_sccs [i]->num_objs; ++j) + for (j = 0; j < api_sccs [i]->num_objs; ++j) { + GCVTable vtable = SGEN_LOAD_VTABLE (api_sccs [i]->objs [j]); mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "OBJECT %s (%p) SCC [%d] %s", - sgen_safe_name (api_sccs [i]->objs [j]), api_sccs [i]->objs [j], + sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable), api_sccs [i]->objs [j], i, api_sccs [i]->is_alive ? "ALIVE" : "DEAD"); + } } } @@ -1354,7 +1336,7 @@ processing_after_callback (int generation) } static void -describe_pointer (MonoObject *obj) +describe_pointer (GCObject *obj) { HashEntry *entry; int i; @@ -1366,7 +1348,7 @@ describe_pointer (MonoObject *obj) } } - entry = sgen_hash_table_lookup (&hash_table, obj); + entry = (HashEntry *)sgen_hash_table_lookup (&hash_table, obj); if (!entry) return;