2 * sgen-debug.c: Collector debugging
5 * Paolo Molaro (lupus@ximian.com)
6 * Rodrigo Kumpera (kumpera@gmail.com)
8 * Copyright 2005-2011 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
10 * Copyright 2011 Xamarin, Inc.
11 * Copyright (C) 2012 Xamarin Inc
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License 2.0 as published by the Free Software Foundation;
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License 2.0 along with this library; if not, write to the Free
24 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include "metadata/sgen-gc.h"
31 #include "metadata/sgen-cardtable.h"
32 #include "metadata/sgen-protocol.h"
33 #include "metadata/sgen-memory-governor.h"
34 #include "metadata/sgen-pinning.h"
35 #include "metadata/threadpool-internals.h"
37 #define LOAD_VTABLE SGEN_LOAD_VTABLE
39 #define object_is_forwarded SGEN_OBJECT_IS_FORWARDED
40 #define object_is_pinned SGEN_OBJECT_IS_PINNED
41 #define safe_object_get_size sgen_safe_object_get_size
43 void describe_ptr (char *ptr);
44 void check_object (char *start);
47 * ######################################################################
48 * ######## Collector debugging
49 * ######################################################################
52 const char*descriptor_types [] = {
63 static char* describe_nursery_ptr (char *ptr, gboolean need_setup);
66 describe_pointer (char *ptr, gboolean need_setup)
76 if (sgen_ptr_in_nursery (ptr)) {
77 start = describe_nursery_ptr (ptr, need_setup);
81 vtable = (MonoVTable*)LOAD_VTABLE (ptr);
83 if (sgen_ptr_is_in_los (ptr, &start)) {
85 printf ("Pointer is the start of object %p in LOS space.\n", start);
87 printf ("Pointer is at offset 0x%x of object %p in LOS space.\n", (int)(ptr - start), start);
89 mono_sgen_los_describe_pointer (ptr);
90 vtable = (MonoVTable*)LOAD_VTABLE (ptr);
91 } else if (major_collector.ptr_is_in_non_pinned_space (ptr, &start)) {
93 printf ("Pointer is the start of object %p in oldspace.\n", start);
95 printf ("Pointer is at offset 0x%x of object %p in oldspace.\n", (int)(ptr - start), start);
97 printf ("Pointer inside oldspace.\n");
100 vtable = major_collector.describe_pointer (ptr);
101 } else if (major_collector.obj_is_from_pinned_alloc (ptr)) {
102 // FIXME: Handle pointers to the inside of objects
103 printf ("Pointer is inside a pinned chunk.\n");
104 vtable = (MonoVTable*)LOAD_VTABLE (ptr);
106 printf ("Pointer unknown.\n");
111 if (object_is_pinned (ptr))
112 printf ("Object is pinned.\n");
114 if ((forwarded = object_is_forwarded (ptr))) {
115 printf ("Object is forwarded to %p:\n", forwarded);
120 printf ("VTable: %p\n", vtable);
121 if (vtable == NULL) {
122 printf ("VTable is invalid (empty).\n");
125 if (sgen_ptr_in_nursery (vtable)) {
126 printf ("VTable is invalid (points inside nursery).\n");
129 printf ("Class: %s\n", vtable->klass->name);
131 desc = ((GCVTable*)vtable)->desc;
132 printf ("Descriptor: %lx\n", (long)desc);
135 printf ("Descriptor type: %d (%s)\n", type, descriptor_types [type]);
137 size = sgen_safe_object_get_size ((MonoObject*)ptr);
138 printf ("Size: %d\n", (int)size);
141 sgen_bridge_describe_pointer ((MonoObject*)ptr);
145 describe_ptr (char *ptr)
147 describe_pointer (ptr, TRUE);
150 static gboolean missing_remsets;
153 * We let a missing remset slide if the target object is pinned,
154 * because the store might have happened but the remset not yet added,
155 * but in that case the target must be pinned. We might theoretically
156 * miss some missing remsets this way, but it's very unlikely.
159 #define HANDLE_PTR(ptr,obj) do { \
160 if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
161 if (!sgen_get_remset ()->find_address ((char*)(ptr))) { \
162 SGEN_LOG (0, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), ((MonoObject*)(obj))->vtable->klass->name_space, ((MonoObject*)(obj))->vtable->klass->name); \
163 binary_protocol_missing_remset ((obj), (gpointer)LOAD_VTABLE ((obj)), (char*)(ptr) - (char*)(obj), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
164 if (!object_is_pinned (*(ptr))) \
165 missing_remsets = TRUE; \
171 * Check that each object reference which points into the nursery can
172 * be found in the remembered sets.
175 check_consistency_callback (char *start, size_t size, void *dummy)
177 GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
178 SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name);
180 #include "sgen-scan-object.h"
184 * Perform consistency check of the heap.
186 * Assumes the world is stopped.
189 sgen_check_consistency (void)
191 // Need to add more checks
193 missing_remsets = FALSE;
195 SGEN_LOG (1, "Begin heap consistency check...");
197 // Check that oldspace->newspace pointers are registered with the collector
198 major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)check_consistency_callback, NULL);
200 sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_consistency_callback, NULL);
202 SGEN_LOG (1, "Heap consistency check done.");
204 if (!binary_protocol_is_enabled ())
205 g_assert (!missing_remsets);
209 is_major_or_los_object_marked (char *obj)
211 if (sgen_safe_object_get_size ((MonoObject*)obj) > SGEN_MAX_SMALL_OBJ_SIZE) {
212 return sgen_los_object_is_pinned (obj);
214 return sgen_get_major_collector ()->is_object_live (obj);
219 #define HANDLE_PTR(ptr,obj) do { \
220 if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((char*)*(ptr))) { \
221 if (!sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
222 SGEN_LOG (0, "major->major reference %p at offset %td in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), ((MonoObject*)(obj))->vtable->klass->name_space, ((MonoObject*)(obj))->vtable->klass->name); \
223 binary_protocol_missing_remset ((obj), (gpointer)LOAD_VTABLE ((obj)), (char*)(ptr) - (char*)(obj), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
224 missing_remsets = TRUE; \
230 check_mod_union_callback (char *start, size_t size, void *dummy)
232 gboolean in_los = (gboolean) (size_t) dummy;
233 GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
235 SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name);
237 if (!is_major_or_los_object_marked (start))
241 cards = sgen_los_header_for_object (start)->cardtable_mod_union;
243 cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_object (start);
245 SGEN_ASSERT (0, cards, "we must have mod union for marked major objects");
247 #include "sgen-scan-object.h"
251 sgen_check_mod_union_consistency (void)
253 missing_remsets = FALSE;
255 major_collector.iterate_objects (ITERATE_OBJECTS_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
257 sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_mod_union_callback, (void*)TRUE);
259 if (!binary_protocol_is_enabled ())
260 g_assert (!missing_remsets);
264 #define HANDLE_PTR(ptr,obj) do { \
265 if (*(ptr) && !LOAD_VTABLE (*(ptr))) \
266 g_error ("Could not load vtable for obj %p slot %d (size %d)", obj, (char*)ptr - (char*)obj, safe_object_get_size ((MonoObject*)obj)); \
270 check_major_refs_callback (char *start, size_t size, void *dummy)
272 #include "sgen-scan-object.h"
276 sgen_check_major_refs (void)
278 major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)check_major_refs_callback, NULL);
279 sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_major_refs_callback, NULL);
282 /* Check that the reference is valid */
284 #define HANDLE_PTR(ptr,obj) do { \
286 g_assert (sgen_safe_name (*(ptr)) != NULL); \
293 * Perform consistency check on an object. Currently we only check that the
294 * reference fields are valid.
297 check_object (char *start)
302 #include "sgen-scan-object.h"
306 static char **valid_nursery_objects;
307 static int valid_nursery_object_count;
308 static gboolean broken_heap;
311 setup_mono_sgen_scan_area_with_callback (char *object, size_t size, void *data)
313 valid_nursery_objects [valid_nursery_object_count++] = object;
317 setup_valid_nursery_objects (void)
319 if (!valid_nursery_objects)
320 valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging data");
321 valid_nursery_object_count = 0;
322 sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE);
326 find_object_in_nursery_dump (char *object)
328 int first = 0, last = valid_nursery_object_count;
329 while (first < last) {
330 int middle = first + ((last - first) >> 1);
331 if (object == valid_nursery_objects [middle])
334 if (object < valid_nursery_objects [middle])
339 g_assert (first == last);
344 describe_nursery_ptr (char *ptr, gboolean need_setup)
349 setup_valid_nursery_objects ();
351 for (i = 0; i < valid_nursery_object_count; ++i) {
352 if (valid_nursery_objects [i] >= ptr)
356 if (i >= valid_nursery_object_count || valid_nursery_objects [i] + safe_object_get_size ((MonoObject *)valid_nursery_objects [i]) < ptr) {
357 SGEN_LOG (0, "nursery-ptr (unalloc'd-memory)\n");
360 char *obj = valid_nursery_objects [i];
362 SGEN_LOG (0, "nursery-ptr\n");
364 SGEN_LOG (0, "nursery-ptr (interior-ptr offset %td)\n", ptr - obj);
370 is_valid_object_pointer (char *object)
372 if (sgen_ptr_in_nursery (object))
373 return find_object_in_nursery_dump (object);
375 if (sgen_los_is_valid_object (object))
378 if (major_collector.is_valid_object (object))
384 bad_pointer_spew (char *obj, char **slot)
387 MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
389 SGEN_LOG (0, "Invalid object pointer %p at offset %td in object %p (%s.%s):", ptr,
391 obj, vtable->klass->name_space, vtable->klass->name);
392 describe_pointer (ptr, FALSE);
397 missing_remset_spew (char *obj, char **slot)
400 MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
402 SGEN_LOG (0, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.",
403 ptr, (char*)slot - obj, obj,
404 vtable->klass->name_space, vtable->klass->name);
410 FIXME Flag missing remsets due to pinning as non fatal
413 #define HANDLE_PTR(ptr,obj) do { \
414 if (*(char**)ptr) { \
415 if (!is_valid_object_pointer (*(char**)ptr)) { \
416 bad_pointer_spew ((char*)obj, (char**)ptr); \
417 } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \
418 if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup ((char*)*(ptr)) && (!allow_missing_pinned || !SGEN_OBJECT_IS_PINNED ((char*)*(ptr)))) \
419 missing_remset_spew ((char*)obj, (char**)ptr); \
425 verify_object_pointers_callback (char *start, size_t size, void *data)
427 gboolean allow_missing_pinned = (gboolean) (size_t) data;
429 #include "sgen-scan-object.h"
434 -This heap checker is racy regarding inlined write barriers and other JIT tricks that
435 depend on OP_DUMMY_USE.
438 sgen_check_whole_heap (gboolean allow_missing_pinned)
440 setup_valid_nursery_objects ();
443 sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE);
444 major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
445 sgen_los_iterate_objects (verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
447 g_assert (!broken_heap);
451 ptr_in_heap (char *object)
453 if (sgen_ptr_in_nursery (object))
456 if (sgen_los_is_valid_object (object))
459 if (major_collector.is_valid_object (object))
466 * Do consistency checks on the object reference OBJ. Assert on failure.
469 sgen_check_objref (char *obj)
471 g_assert (ptr_in_heap (obj));
475 find_pinning_ref_from_thread (char *obj, size_t size)
478 SgenThreadInfo *info;
479 char *endobj = obj + size;
481 FOREACH_THREAD (info) {
482 char **start = (char**)info->stack_start;
485 while (start < (char**)info->stack_end) {
486 if (*start >= obj && *start < endobj) {
487 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->stack_start, info->stack_end);
492 for (j = 0; j < ARCH_NUM_REGS; ++j) {
494 mword w = ((mword*)&info->ctx) [j];
496 mword w = (mword)&info->regs [j];
499 if (w >= (mword)obj && w < (mword)obj + size)
500 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));
506 * Debugging function: find in the conservative roots where @obj is being pinned.
508 static G_GNUC_UNUSED void
509 find_pinning_reference (char *obj, size_t size)
513 char *endobj = obj + size;
515 SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_NORMAL], start, root) {
516 /* if desc is non-null it has precise info */
517 if (!root->root_desc) {
518 while (start < (char**)root->end_root) {
519 if (*start >= obj && *start < endobj) {
520 SGEN_LOG (0, "Object %p referenced in pinned roots %p-%p\n", obj, start, root->end_root);
525 } SGEN_HASH_TABLE_FOREACH_END;
527 find_pinning_ref_from_thread (obj, size);
531 #define HANDLE_PTR(ptr,obj) do { \
532 char* __target = *(char**)ptr; \
534 g_assert (is_valid_object_pointer (__target)); \
535 if (sgen_ptr_in_nursery (__target)) { \
536 g_assert (SGEN_OBJECT_IS_PINNED (__target)); \
537 } else if (sgen_los_is_valid_object (__target)) { \
538 g_assert (sgen_los_object_is_pinned (__target)); \
539 } else if (major_collector.is_valid_object (__target)) { \
540 g_assert (major_collector.is_object_live (__target)); \
542 g_assert_not_reached (); \
548 check_marked_callback (char *start, size_t size, void *dummy)
550 gboolean is_los = (gboolean) (size_t) dummy;
553 if (!sgen_los_object_is_pinned (start))
556 if (!major_collector.is_object_live (start))
560 #include "sgen-scan-object.h"
564 sgen_check_major_heap_marked (void)
566 setup_valid_nursery_objects ();
568 major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, check_marked_callback, (void*)FALSE);
569 sgen_los_iterate_objects (check_marked_callback, (void*)TRUE);
573 check_nursery_objects_pinned_callback (char *obj, size_t size, void *data /* ScanCopyContext *ctx */)
575 gboolean pinned = (gboolean) (size_t) data;
577 g_assert (!SGEN_OBJECT_IS_FORWARDED (obj));
579 g_assert (SGEN_OBJECT_IS_PINNED (obj));
581 g_assert (!SGEN_OBJECT_IS_PINNED (obj));
585 sgen_check_nursery_objects_pinned (gboolean pinned)
587 sgen_clear_nursery_fragments ();
588 sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
589 (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE);
592 static gboolean scan_object_for_specific_ref_precise = TRUE;
595 #define HANDLE_PTR(ptr,obj) do { \
596 if ((MonoObject*)*(ptr) == key) { \
597 g_print ("found ref to %p in object %p (%s) at offset %td\n", \
598 key, (obj), sgen_safe_name ((obj)), ((char*)(ptr) - (char*)(obj))); \
603 scan_object_for_specific_ref (char *start, MonoObject *key)
607 if ((forwarded = SGEN_OBJECT_IS_FORWARDED (start)))
610 if (scan_object_for_specific_ref_precise) {
611 #include "sgen-scan-object.h"
613 mword *words = (mword*)start;
614 size_t size = safe_object_get_size ((MonoObject*)start);
616 for (i = 0; i < size / sizeof (mword); ++i) {
617 if (words [i] == (mword)key) {
618 g_print ("found possible ref to %p in object %p (%s) at offset %td\n",
619 key, start, sgen_safe_name (start), i * sizeof (mword));
626 scan_object_for_specific_ref_callback (char *obj, size_t size, MonoObject *key)
628 scan_object_for_specific_ref (obj, key);
632 check_root_obj_specific_ref (RootRecord *root, MonoObject *key, MonoObject *obj)
636 g_print ("found ref to %p in root record %p\n", key, root);
639 static MonoObject *check_key = NULL;
640 static RootRecord *check_root = NULL;
643 check_root_obj_specific_ref_from_marker (void **obj)
645 check_root_obj_specific_ref (check_root, check_key, *obj);
649 scan_roots_for_specific_ref (MonoObject *key, int root_type)
655 SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) {
656 mword desc = root->root_desc;
660 switch (desc & ROOT_DESC_TYPE_MASK) {
661 case ROOT_DESC_BITMAP:
662 desc >>= ROOT_DESC_TYPE_SHIFT;
665 check_root_obj_specific_ref (root, key, *start_root);
670 case ROOT_DESC_COMPLEX: {
671 gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc);
672 int bwords = (*bitmap_data) - 1;
673 void **start_run = start_root;
675 while (bwords-- > 0) {
676 gsize bmap = *bitmap_data++;
677 void **objptr = start_run;
680 check_root_obj_specific_ref (root, key, *objptr);
684 start_run += GC_BITS_PER_WORD;
688 case ROOT_DESC_USER: {
689 MonoGCRootMarkFunc marker = sgen_get_user_descriptor_func (desc);
690 marker (start_root, check_root_obj_specific_ref_from_marker);
693 case ROOT_DESC_RUN_LEN:
694 g_assert_not_reached ();
696 g_assert_not_reached ();
698 } SGEN_HASH_TABLE_FOREACH_END;
705 mono_gc_scan_for_specific_ref (MonoObject *key, gboolean precise)
710 scan_object_for_specific_ref_precise = precise;
712 sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
713 (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE);
715 major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key);
717 sgen_los_iterate_objects ((IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key);
719 scan_roots_for_specific_ref (key, ROOT_TYPE_NORMAL);
720 scan_roots_for_specific_ref (key, ROOT_TYPE_WBARRIER);
722 SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_PINNED], ptr, root) {
723 while (ptr < (void**)root->end_root) {
724 check_root_obj_specific_ref (root, *ptr, key);
727 } SGEN_HASH_TABLE_FOREACH_END;
730 static MonoDomain *check_domain = NULL;
733 check_obj_not_in_domain (void **o)
735 g_assert (((MonoObject*)(*o))->vtable->domain != check_domain);
739 sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
743 check_domain = domain;
744 SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) {
745 mword desc = root->root_desc;
747 /* The MonoDomain struct is allowed to hold
748 references to objects in its own domain. */
749 if (start_root == (void**)domain)
752 switch (desc & ROOT_DESC_TYPE_MASK) {
753 case ROOT_DESC_BITMAP:
754 desc >>= ROOT_DESC_TYPE_SHIFT;
756 if ((desc & 1) && *start_root)
757 check_obj_not_in_domain (*start_root);
762 case ROOT_DESC_COMPLEX: {
763 gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc);
764 int bwords = (*bitmap_data) - 1;
765 void **start_run = start_root;
767 while (bwords-- > 0) {
768 gsize bmap = *bitmap_data++;
769 void **objptr = start_run;
771 if ((bmap & 1) && *objptr)
772 check_obj_not_in_domain (*objptr);
776 start_run += GC_BITS_PER_WORD;
780 case ROOT_DESC_USER: {
781 MonoGCRootMarkFunc marker = sgen_get_user_descriptor_func (desc);
782 marker (start_root, check_obj_not_in_domain);
785 case ROOT_DESC_RUN_LEN:
786 g_assert_not_reached ();
788 g_assert_not_reached ();
790 } SGEN_HASH_TABLE_FOREACH_END;
796 is_xdomain_ref_allowed (gpointer *ptr, char *obj, MonoDomain *domain)
798 MonoObject *o = (MonoObject*)(obj);
799 MonoObject *ref = (MonoObject*)*(ptr);
800 int offset = (char*)(ptr) - (char*)o;
802 if (o->vtable->klass == mono_defaults.thread_class && offset == G_STRUCT_OFFSET (MonoThread, internal_thread))
804 if (o->vtable->klass == mono_defaults.internal_thread_class && offset == G_STRUCT_OFFSET (MonoInternalThread, current_appcontext))
807 #ifndef DISABLE_REMOTING
808 if (mono_defaults.real_proxy_class->supertypes && mono_class_has_parent_fast (o->vtable->klass, mono_defaults.real_proxy_class) &&
809 offset == G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server))
812 /* Thread.cached_culture_info */
813 if (!strcmp (ref->vtable->klass->name_space, "System.Globalization") &&
814 !strcmp (ref->vtable->klass->name, "CultureInfo") &&
815 !strcmp(o->vtable->klass->name_space, "System") &&
816 !strcmp(o->vtable->klass->name, "Object[]"))
819 * 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
820 * at System.IO.MemoryStream..ctor (byte[]) [0x00017] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.IO/MemoryStream.cs:81
821 * at (wrapper remoting-invoke-with-check) System.IO.MemoryStream..ctor (byte[]) <IL 0x00020, 0xffffffff>
822 * at System.Runtime.Remoting.Messaging.CADMethodCallMessage.GetArguments () [0x0000d] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.Runtime.Remoting.Messaging/CADMessages.cs:327
823 * at System.Runtime.Remoting.Messaging.MethodCall..ctor (System.Runtime.Remoting.Messaging.CADMethodCallMessage) [0x00017] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodCall.cs:87
824 * at System.AppDomain.ProcessMessageInDomain (byte[],System.Runtime.Remoting.Messaging.CADMethodCallMessage,byte[]&,System.Runtime.Remoting.Messaging.CADMethodReturnMessage&) [0x00018] in /home/schani/Work/novell/trunk/mcs/class/corlib/System/AppDomain.cs:1213
825 * at (wrapper remoting-invoke-with-check) System.AppDomain.ProcessMessageInDomain (byte[],System.Runtime.Remoting.Messaging.CADMethodCallMessage,byte[]&,System.Runtime.Remoting.Messaging.CADMethodReturnMessage&) <IL 0x0003d, 0xffffffff>
826 * at System.Runtime.Remoting.Channels.CrossAppDomainSink.ProcessMessageInDomain (byte[],System.Runtime.Remoting.Messaging.CADMethodCallMessage) [0x00008] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.Runtime.Remoting.Channels/CrossAppDomainChannel.cs:198
827 * at (wrapper runtime-invoke) object.runtime_invoke_CrossAppDomainSink/ProcessMessageRes_object_object (object,intptr,intptr,intptr) <IL 0x0004c, 0xffffffff>
829 if (!strcmp (ref->vtable->klass->name_space, "System") &&
830 !strcmp (ref->vtable->klass->name, "Byte[]") &&
831 !strcmp (o->vtable->klass->name_space, "System.IO") &&
832 !strcmp (o->vtable->klass->name, "MemoryStream"))
834 /* append_job() in threadpool.c */
835 if (!strcmp (ref->vtable->klass->name_space, "System.Runtime.Remoting.Messaging") &&
836 !strcmp (ref->vtable->klass->name, "AsyncResult") &&
837 !strcmp (o->vtable->klass->name_space, "System") &&
838 !strcmp (o->vtable->klass->name, "Object[]") &&
839 mono_thread_pool_is_queue_array ((MonoArray*) o))
845 check_reference_for_xdomain (gpointer *ptr, char *obj, MonoDomain *domain)
847 MonoObject *o = (MonoObject*)(obj);
848 MonoObject *ref = (MonoObject*)*(ptr);
849 int offset = (char*)(ptr) - (char*)o;
851 MonoClassField *field;
854 if (!ref || ref->vtable->domain == domain)
856 if (is_xdomain_ref_allowed (ptr, obj, domain))
860 for (class = o->vtable->klass; class; class = class->parent) {
863 for (i = 0; i < class->field.count; ++i) {
864 if (class->fields[i].offset == offset) {
865 field = &class->fields[i];
873 if (ref->vtable->klass == mono_defaults.string_class)
874 str = mono_string_to_utf8 ((MonoString*)ref);
877 g_print ("xdomain reference in %p (%s.%s) at offset %d (%s) to %p (%s.%s) (%s) - pointed to by:\n",
878 o, o->vtable->klass->name_space, o->vtable->klass->name,
879 offset, field ? field->name : "",
880 ref, ref->vtable->klass->name_space, ref->vtable->klass->name, str ? str : "");
881 mono_gc_scan_for_specific_ref (o, TRUE);
887 #define HANDLE_PTR(ptr,obj) check_reference_for_xdomain ((ptr), (obj), domain)
890 scan_object_for_xdomain_refs (char *start, mword size, void *data)
892 MonoDomain *domain = ((MonoObject*)start)->vtable->domain;
894 #include "sgen-scan-object.h"
898 sgen_check_for_xdomain_refs (void)
902 sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
903 (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE);
905 major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL);
907 for (bigobj = los_object_list; bigobj; bigobj = bigobj->next)
908 scan_object_for_xdomain_refs (bigobj->data, sgen_los_object_size (bigobj), NULL);
911 #endif /*HAVE_SGEN_GC*/