-/*
- * sgen-debug.c: Collector debugging
+/**
+ * \file
+ * Collector debugging
*
* Author:
* Paolo Molaro (lupus@ximian.com)
* Copyright 2011 Xamarin, Inc.
* Copyright (C) 2012 Xamarin Inc
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include "config.h"
if (object_is_pinned (ptr))
printf ("Object is pinned.\n");
- if ((forwarded = object_is_forwarded (ptr))) {
+ if ((forwarded = (char *)object_is_forwarded (ptr))) {
printf ("Object is forwarded to %p:\n", forwarded);
ptr = forwarded;
goto restart;
*/
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
- if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
- if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \
- GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
- SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \
- binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
- if (!object_is_pinned (*(ptr))) \
- missing_remsets = TRUE; \
- } \
- } \
+ if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
+ if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \
+ GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
+ gboolean is_pinned = object_is_pinned (*(ptr)); \
+ SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets%s.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt), is_pinned ? ", but object is pinned" : ""); \
+ binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), is_pinned); \
+ if (!is_pinned) \
+ missing_remsets = TRUE; \
+ } \
+ } \
} while (0)
/*
* Assumes the world is stopped.
*/
void
-sgen_check_consistency (void)
+sgen_check_remset_consistency (void)
{
// Need to add more checks
SGEN_LOG (1, "Heap consistency check done.");
+ if (missing_remsets)
+ binary_protocol_flush_buffers (TRUE);
if (!binary_protocol_is_enabled ())
g_assert (!missing_remsets);
}
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((GCObject*)*(ptr))) { \
- if (!sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
+ if (!cards || !sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
SGEN_LOG (0, "major->major reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \
binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
else
cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_reference (start);
- SGEN_ASSERT (0, cards, "we must have mod union for marked major objects");
-
#include "sgen-scan-object.h"
}
{
missing_remsets = FALSE;
- major_collector.iterate_objects (ITERATE_OBJECTS_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
+ major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_mod_union_callback, (void*)TRUE);
setup_valid_nursery_objects (void)
{
if (!valid_nursery_objects)
- valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging data");
+ valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (sgen_nursery_max_size, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging data", MONO_MEM_ACCOUNT_SGEN_DEBUGGING);
valid_nursery_object_count = 0;
- sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE);
+ sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE, FALSE);
}
static gboolean
FIXME Flag missing remsets due to pinning as non fatal
*/
#undef HANDLE_PTR
-#define HANDLE_PTR(ptr,obj) do { \
- if (*(char**)ptr) { \
+#define HANDLE_PTR(ptr,obj) do { \
+ if (*(char**)ptr) { \
if (!is_valid_object_pointer (*(char**)ptr)) { \
- bad_pointer_spew ((char*)obj, (char**)ptr); \
- } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \
- if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr)) && (!allow_missing_pinned || !SGEN_OBJECT_IS_PINNED (*(ptr)))) \
- missing_remset_spew ((char*)obj, (char**)ptr); \
- } \
- } \
+ bad_pointer_spew ((char*)obj, (char**)ptr); \
+ } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \
+ if (!allow_missing_pinned && !SGEN_OBJECT_IS_PINNED (*(ptr)) && !sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) \
+ missing_remset_spew ((char*)obj, (char**)ptr); \
+ } \
+ } \
} while (0)
static void
{
char *start = (char*)obj;
gboolean allow_missing_pinned = (gboolean) (size_t) data;
- SgenDescriptor desc = sgen_obj_get_descriptor (obj);
+ SgenDescriptor desc = sgen_obj_get_descriptor_safe (obj);
#include "sgen-scan-object.h"
}
setup_valid_nursery_objects ();
broken_heap = FALSE;
- sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE);
+ sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE, TRUE);
major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
sgen_los_iterate_objects (verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
find_pinning_ref_from_thread (char *obj, size_t size)
{
#ifndef SGEN_WITHOUT_MONO
- int j;
- SgenThreadInfo *info;
char *endobj = obj + size;
FOREACH_THREAD (info) {
+ mword *ctxstart, *ctxcurrent, *ctxend;
char **start = (char**)info->client_info.stack_start;
if (info->client_info.skip || info->client_info.gc_disabled)
continue;
- while (start < (char**)info->client_info.stack_end) {
+ while (start < (char**)info->client_info.info.stack_end) {
if (*start >= obj && *start < endobj)
- SGEN_LOG (0, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p", obj, info, (gpointer)mono_thread_info_get_tid (info), start, info->client_info.stack_start, info->client_info.stack_end);
+ SGEN_LOG (0, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p", obj, info, (gpointer)mono_thread_info_get_tid (info), start, info->client_info.stack_start, info->client_info.info.stack_end);
start++;
}
- for (j = 0; j < ARCH_NUM_REGS; ++j) {
-#ifdef USE_MONO_CTX
- mword w = ((mword*)&info->client_info.ctx) [j];
-#else
- mword w = (mword)&info->client_info.regs [j];
-#endif
+ for (ctxstart = ctxcurrent = (mword*) &info->client_info.ctx, ctxend = (mword*) (&info->client_info.ctx + 1); ctxcurrent < ctxend; ctxcurrent ++) {
+ mword w = *ctxcurrent;
if (w >= (mword)obj && w < (mword)obj + size)
- SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, j, info, (gpointer)mono_thread_info_get_tid (info));
- } END_FOREACH_THREAD
- }
+ SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, (int) (ctxcurrent - ctxstart), info, (gpointer)mono_thread_info_get_tid (info));
+ }
+ } FOREACH_THREAD_END
#endif
}
RootRecord *root;
char *endobj = obj + size;
- SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_NORMAL], start, root) {
+ SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_NORMAL], char **, start, RootRecord *, root) {
/* if desc is non-null it has precise info */
if (!root->root_desc) {
while (start < (char**)root->end_root) {
{
sgen_clear_nursery_fragments ();
sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
- (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE);
+ (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE, TRUE);
}
static void
is_array_fill);
}
if (nursery_canaries_enabled () && !is_array_fill) {
- CHECK_CANARY_FOR_OBJECT ((GCObject*)cur);
+ CHECK_CANARY_FOR_OBJECT ((GCObject*)cur, TRUE);
CANARIFY_SIZE (size);
}
cur += size;
RootRecord *root;
check_key = key;
- SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) {
+ SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], void **, start_root, RootRecord *, root) {
SgenDescriptor desc = root->root_desc;
check_root = root;
desc >>= ROOT_DESC_TYPE_SHIFT;
while (desc) {
if (desc & 1)
- check_root_obj_specific_ref (root, key, *start_root);
+ check_root_obj_specific_ref (root, key, (GCObject *)*start_root);
desc >>= 1;
start_root++;
}
return;
case ROOT_DESC_COMPLEX: {
- gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc);
+ gsize *bitmap_data = (gsize *)sgen_get_complex_descriptor_bitmap (desc);
int bwords = (int) ((*bitmap_data) - 1);
void **start_run = start_root;
bitmap_data++;
void **objptr = start_run;
while (bmap) {
if (bmap & 1)
- check_root_obj_specific_ref (root, key, *objptr);
+ check_root_obj_specific_ref (root, key, (GCObject *)*objptr);
bmap >>= 1;
++objptr;
}
}
break;
}
+ case ROOT_DESC_VECTOR: {
+ void **p;
+
+ for (p = start_root; p < (void**)root->end_root; p++) {
+ if (*p)
+ check_root_obj_specific_ref (root, key, (GCObject *)*p);
+ }
+ break;
+ }
case ROOT_DESC_USER: {
SgenUserRootMarkFunc marker = sgen_get_user_descriptor_func (desc);
marker (start_root, check_root_obj_specific_ref_from_marker, NULL);
scan_object_for_specific_ref_precise = precise;
sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
- (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE);
+ (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE, FALSE);
major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key);
scan_roots_for_specific_ref (key, ROOT_TYPE_NORMAL);
scan_roots_for_specific_ref (key, ROOT_TYPE_WBARRIER);
- SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_PINNED], ptr, root) {
+ SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_PINNED], void **, ptr, RootRecord *, root) {
while (ptr < (void**)root->end_root) {
- check_root_obj_specific_ref (root, *ptr, key);
+ check_root_obj_specific_ref (root, (GCObject *)*ptr, key);
++ptr;
}
} SGEN_HASH_TABLE_FOREACH_END;
void **start_root;
RootRecord *root;
check_domain = domain;
- SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) {
+ SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], void **, start_root, RootRecord *, root) {
SgenDescriptor desc = root->root_desc;
/* The MonoDomain struct is allowed to hold
desc >>= ROOT_DESC_TYPE_SHIFT;
while (desc) {
if ((desc & 1) && *start_root)
- check_obj_not_in_domain (*start_root);
+ check_obj_not_in_domain ((MonoObject **)*start_root);
desc >>= 1;
start_root++;
}
break;
case ROOT_DESC_COMPLEX: {
- gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc);
+ gsize *bitmap_data = (gsize *)sgen_get_complex_descriptor_bitmap (desc);
int bwords = (int)((*bitmap_data) - 1);
void **start_run = start_root;
bitmap_data++;
void **objptr = start_run;
while (bmap) {
if ((bmap & 1) && *objptr)
- check_obj_not_in_domain (*objptr);
+ check_obj_not_in_domain ((MonoObject **)*objptr);
bmap >>= 1;
++objptr;
}
}
break;
}
+ case ROOT_DESC_VECTOR: {
+ void **p;
+
+ for (p = start_root; p < (void**)root->end_root; p++) {
+ if (*p)
+ check_obj_not_in_domain ((MonoObject **)*p);
+ }
+ break;
+ }
case ROOT_DESC_USER: {
SgenUserRootMarkFunc marker = sgen_get_user_descriptor_func (desc);
marker (start_root, check_obj_not_in_domain_callback, NULL);
offset == G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server))
return TRUE;
#endif
- /* Thread.cached_culture_info */
- if (!strcmp (ref->vtable->klass->name_space, "System.Globalization") &&
- !strcmp (ref->vtable->klass->name, "CultureInfo") &&
- !strcmp(o->vtable->klass->name_space, "System") &&
- !strcmp(o->vtable->klass->name, "Object[]"))
- return TRUE;
/*
* at System.IO.MemoryStream.InternalConstructor (byte[],int,int,bool,bool) [0x0004d] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.IO/MemoryStream.cs:121
* at System.IO.MemoryStream..ctor (byte[]) [0x00017] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.IO/MemoryStream.cs:81
{
MonoObject *ref = *ptr;
size_t offset = (char*)(ptr) - (char*)obj;
- MonoClass *class;
+ MonoClass *klass;
MonoClassField *field;
char *str;
return;
field = NULL;
- for (class = obj->vtable->klass; class; class = class->parent) {
+ for (klass = obj->vtable->klass; klass; klass = klass->parent) {
int i;
- for (i = 0; i < class->field.count; ++i) {
- if (class->fields[i].offset == offset) {
- field = &class->fields[i];
+ int fcount = mono_class_get_field_count (klass);
+ for (i = 0; i < fcount; ++i) {
+ if (klass->fields[i].offset == offset) {
+ field = &klass->fields[i];
break;
}
}
break;
}
- if (ref->vtable->klass == mono_defaults.string_class)
- str = mono_string_to_utf8 ((MonoString*)ref);
- else
+ if (ref->vtable->klass == mono_defaults.string_class) {
+ MonoError error;
+ str = mono_string_to_utf8_checked ((MonoString*)ref, &error);
+ mono_error_cleanup (&error);
+ } else
str = NULL;
g_print ("xdomain reference in %p (%s.%s) at offset %d (%s) to %p (%s.%s) (%s) - pointed to by:\n",
obj, obj->vtable->klass->name_space, obj->vtable->klass->name,
LOSObject *bigobj;
sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
- (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE);
+ (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE, TRUE);
major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL);
sgen_dump_section (GCMemSection *section, const char *type)
{
char *start = section->data;
- char *end = section->data + section->size;
+ char *end = section->end_data;
char *occ_start = NULL;
- fprintf (heap_dump_file, "<section type=\"%s\" size=\"%lu\">\n", type, (unsigned long)section->size);
+ fprintf (heap_dump_file, "<section type=\"%s\" size=\"%lu\">\n", type, (unsigned long)(section->end_data - section->data));
while (start < end) {
guint size;
start += sizeof (void*); /* should be ALLOC_ALIGN, really */
continue;
}
- g_assert (start < section->next_data);
if (!occ_start)
occ_start = start;
#ifndef SGEN_WITHOUT_MONO
static char class_name [1024];
- MonoClass *class = mono_object_class (obj);
+ MonoClass *klass = mono_object_class (obj);
int i, j;
/*
* in strings, so we just ignore them;
*/
i = j = 0;
- while (class->name [i] && j < sizeof (class_name) - 1) {
- if (!strchr ("<>\"", class->name [i]))
- class_name [j++] = class->name [i];
+ while (klass->name [i] && j < sizeof (class_name) - 1) {
+ if (!strchr ("<>\"", klass->name [i]))
+ class_name [j++] = klass->name [i];
++i;
}
g_assert (j < sizeof (class_name));
class_name [j] = 0;
fprintf (heap_dump_file, "<object class=\"%s.%s\" size=\"%zd\"",
- class->name_space, class_name,
+ klass->name_space, class_name,
safe_object_get_size (obj));
if (dump_location) {
const char *location;
fprintf (heap_dump_file, "<pinned-objects>\n");
pinned_objects = sgen_pin_stats_get_object_list ();
for (i = 0; i < pinned_objects->next_slot; ++i)
- dump_object (pinned_objects->data [i], TRUE);
+ dump_object ((GCObject *)pinned_objects->data [i], TRUE);
fprintf (heap_dump_file, "</pinned-objects>\n");
sgen_dump_section (nursery_section, "nursery");
static void
find_object_for_ptr_callback (GCObject *obj, size_t size, void *user_data)
{
- char *ptr = user_data;
+ char *ptr = (char *)user_data;
if (ptr >= (char*)obj && ptr < (char*)obj + size) {
g_assert (!found_obj);
if (ptr >= nursery_section->data && ptr < nursery_section->end_data) {
found_obj = NULL;
sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
- find_object_for_ptr_callback, ptr, TRUE);
+ find_object_for_ptr_callback, ptr, TRUE, FALSE);
if (found_obj)
return found_obj;
}