* Copyright 2011 Novell, Inc (http://www.novell.com)
* Copyright 2014 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"
#include <stdlib.h>
-#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 "tabledefs.h"
-#include "utils/mono-logger-internal.h"
-#include "utils/mono-time.h"
-#include "utils/mono-compiler.h"
-
+#include "utils/mono-logger-internals.h"
typedef struct {
int 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);
if (da->data) {
memcpy (new_data, da->data, elem_size * da->size);
sgen_free_internal_dynamic (da->data, elem_size * old_capacity, INTERNAL_MEM_BRIDGE_DATA);
static void
dyn_array_ptr_add (DynPtrArray *da, void *ptr)
{
- void **p = dyn_array_add (&da->array, sizeof (void*));
+ void **p = (void **)dyn_array_add (&da->array, sizeof (void*));
*p = ptr;
}
}
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;
}
}
typedef struct {
- MonoObject *obj; //XXX this can be eliminated.
+ GCObject *obj; //XXX this can be eliminated.
mword lock_word;
ColorData *color;
static ObjectBucket*
new_object_bucket (void)
{
- ObjectBucket *res = sgen_alloc_internal (INTERNAL_MEM_TARJAN_OBJ_BUCKET);
+ ObjectBucket *res = (ObjectBucket *)sgen_alloc_internal (INTERNAL_MEM_TARJAN_OBJ_BUCKET);
res->next_data = &res->data [0];
return res;
}
static ColorBucket*
new_color_bucket (void)
{
- ColorBucket *res = sgen_alloc_internal (INTERNAL_MEM_TARJAN_OBJ_BUCKET);
+ ColorBucket *res = (ColorBucket *)sgen_alloc_internal (INTERNAL_MEM_TARJAN_OBJ_BUCKET);
res->next_data = &res->data [0];
return res;
}
static ScanData*
-create_data (MonoObject *obj)
+create_data (GCObject *obj)
{
mword *o = (mword*)obj;
ScanData *res = alloc_object_data ();
}
static ScanData*
-find_data (MonoObject *obj)
+find_data (GCObject *obj)
{
ScanData *a = NULL;
mword *o = (mword*)obj;
}
}
-static MonoObject*
-bridge_object_forward (MonoObject *obj)
+static GCObject*
+bridge_object_forward (GCObject *obj)
{
- MonoObject *fwd;
+ GCObject *fwd;
mword *o = (mword*)obj;
if ((o [0] & SGEN_VTABLE_BITS_MASK) == SGEN_VTABLE_BITS_MASK)
return obj;
#ifdef DUMP_GRAPH
static const char*
-safe_name_bridge (MonoObject *obj)
+safe_name_bridge (GCObject *obj)
{
- MonoVTable *vt = (MonoVTable*)SGEN_LOAD_VTABLE (obj);
+ GCVTable vt = SGEN_LOAD_VTABLE (obj);
return vt->klass->name;
}
static ScanData*
-find_or_create_data (MonoObject *obj)
+find_or_create_data (GCObject *obj)
{
ScanData *entry = find_data (obj);
if (!entry)
static void
-register_bridge_object (MonoObject *obj)
+register_bridge_object (GCObject *obj)
{
create_data (obj)->is_bridge = TRUE;
}
static gboolean
-is_opaque_object (MonoObject *obj)
+is_opaque_object (GCObject *obj)
{
- MonoVTable *vt = (MonoVTable*)SGEN_LOAD_VTABLE (obj);
+ MonoVTable *vt = SGEN_LOAD_VTABLE (obj);
if ((vt->gc_bits & SGEN_GC_BIT_BRIDGE_OPAQUE_OBJECT) == SGEN_GC_BIT_BRIDGE_OPAQUE_OBJECT) {
SGEN_LOG (6, "ignoring %s\n", vt->klass->name);
++ignored_objects;
}
static void
-push_object (MonoObject *obj)
+push_object (GCObject *obj)
{
ScanData *data;
obj = bridge_object_forward (obj);
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
- MonoObject *dst = (MonoObject*)*(ptr); \
+ GCObject *dst = (GCObject*)*(ptr); \
if (dst) push_object (dst); \
} while (0)
static void
push_all (ScanData *data)
{
- MonoObject *obj = data->obj;
+ GCObject *obj = data->obj;
char *start = (char*)obj;
- mword desc = sgen_obj_get_descriptor (start);
+ mword desc = sgen_obj_get_descriptor_safe (obj);
#if DUMP_GRAPH
printf ("**scanning %p %s\n", obj, safe_name_bridge (obj));
#endif
- #include "sgen-scan-object.h"
+ #include "sgen/sgen-scan-object.h"
}
static void
-compute_low_index (ScanData *data, MonoObject *obj)
+compute_low_index (ScanData *data, GCObject *obj)
{
ScanData *other;
ColorData *cd;
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
- MonoObject *dst = (MonoObject*)*(ptr); \
+ GCObject *dst = (GCObject*)*(ptr); \
if (dst) compute_low_index (data, dst); \
} while (0)
static void
compute_low (ScanData *data)
{
- MonoObject *obj = data->obj;
+ GCObject *obj = data->obj;
char *start = (char*)obj;
- mword desc = sgen_obj_get_descriptor (start);
+ mword desc = sgen_obj_get_descriptor_safe (obj);
- #include "sgen-scan-object.h"
+ #include "sgen/sgen-scan-object.h"
}
static ColorData*
if (size == 0)
color = NULL;
else if (size == 1) {
- color = dyn_array_ptr_get (&color_merge_array, 0);
+ color = (ColorData *)dyn_array_ptr_get (&color_merge_array, 0);
} else
color = new_color (FALSE);
ColorData *color_data = NULL;
for (i = dyn_array_ptr_size (&loop_stack) - 1; i >= 0; --i) {
- ScanData *other = dyn_array_ptr_get (&loop_stack, i);
+ ScanData *other = (ScanData *)dyn_array_ptr_get (&loop_stack, i);
found_bridge |= other->is_bridge;
if (found_bridge || other == data)
break;
}
while (dyn_array_ptr_size (&loop_stack) > 0) {
- ScanData *other = dyn_array_ptr_pop (&loop_stack);
+ ScanData *other = (ScanData *)dyn_array_ptr_pop (&loop_stack);
#if DUMP_GRAPH
printf ("\tmember %s (%p) index %d low-index %d color %p state %d\n", safe_name_bridge (other->obj), other->obj, other->index, other->low_index, other->color, other->state);
g_assert (found);
for (i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i) {
- ColorData *cd = dyn_array_ptr_get (&color_merge_array, i);
+ ColorData *cd = (ColorData *)dyn_array_ptr_get (&color_merge_array, i);
g_assert (cd->visited);
cd->visited = FALSE;
}
dyn_array_ptr_set_size (&color_merge_array, 0);
while (dyn_array_ptr_size (&scan_stack) > 0) {
- ScanData *data = dyn_array_ptr_pop (&scan_stack);
+ ScanData *data = (ScanData *)dyn_array_ptr_pop (&scan_stack);
/**
* Ignore finished objects on stack, they happen due to loops. For example:
}
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);
if (dyn_array_ptr_size (&cd->bridges)) {
printf (" bridges: ");
for (j = 0; j < dyn_array_ptr_size (&cd->bridges); ++j) {
- MonoObject *obj = dyn_array_ptr_get (&cd->bridges, j);
+ GCObject *obj = dyn_array_ptr_get (&cd->bridges, j);
ScanData *data = find_or_create_data (obj);
printf ("%d ", data->index);
}
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 ((GCObject *)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));
+ ScanData *sd = find_data ((GCObject *)dyn_array_ptr_get (®istered_bridges, i));
if (sd->state == INITIAL) {
dyn_array_ptr_push (&scan_stack, sd);
dfs ();
{
int i;
for (i = 0; i < dyn_array_ptr_size (&color->other_colors); ++i) {
- ColorData *src = dyn_array_ptr_get (&color->other_colors, i);
+ ColorData *src = (ColorData *)dyn_array_ptr_get (&color->other_colors, i);
if (src->visited)
continue;
src->visited = TRUE;
{
int i;
for (i = 0; i < dyn_array_ptr_size (&color->other_colors); ++i) {
- ColorData *src = dyn_array_ptr_get (&color->other_colors, i);
+ ColorData *src = (ColorData *)dyn_array_ptr_get (&color->other_colors, i);
if (!src->visited)
continue;
src->visited = FALSE;
#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_sccs = (MonoGCBridgeSCC **)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) {
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] = (MonoGCBridgeSCC *)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_sccs [api_index]->objs [j] = (MonoObject *)dyn_array_ptr_get (&cd->bridges, j);
api_index++;
}
}
dump_color_table (" after xref pass", TRUE);
#endif
- api_xrefs = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE);
+ api_xrefs = (MonoGCBridgeXRef *)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;
continue;
for (j = 0; j < dyn_array_ptr_size (&src->other_colors); ++j) {
- ColorData *dest = dyn_array_ptr_get (&src->other_colors, j);
+ ColorData *dest = (ColorData *)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;
}
static void
-describe_pointer (MonoObject *obj)
+describe_pointer (GCObject *obj)
{
// HashEntry *entry;
int i;