#include "metadata/sgen-gc.h"
#include "metadata/sgen-cardtable.h"
-#include "metadata/sgen-ssb.h"
#include "metadata/sgen-protocol.h"
#include "metadata/sgen-memory-governor.h"
+#include "metadata/sgen-pinning.h"
#define LOAD_VTABLE SGEN_LOAD_VTABLE
*/
const char*descriptor_types [] = {
+ "INVALID",
"run_length",
"small_bitmap",
- "string",
"complex",
"vector",
- "array",
"large_bitmap",
- "complex_arr"
+ "complex_arr",
+ "complex_ptrfree"
};
-void
-describe_ptr (char *ptr)
+static char* describe_nursery_ptr (char *ptr, gboolean need_setup);
+
+static void
+describe_pointer (char *ptr, gboolean need_setup)
{
MonoVTable *vtable;
mword desc;
int type;
char *start;
char *forwarded;
+ mword size;
restart:
if (sgen_ptr_in_nursery (ptr)) {
- printf ("Pointer inside nursery.\n");
+ start = describe_nursery_ptr (ptr, need_setup);
+ if (!start)
+ return;
+ ptr = start;
+ vtable = (MonoVTable*)LOAD_VTABLE (ptr);
} else {
if (sgen_ptr_is_in_los (ptr, &start)) {
if (ptr == start)
else
printf ("Pointer is at offset 0x%x of object %p in LOS space.\n", (int)(ptr - start), start);
ptr = start;
+ mono_sgen_los_describe_pointer (ptr);
+ vtable = (MonoVTable*)LOAD_VTABLE (ptr);
} else if (major_collector.ptr_is_in_non_pinned_space (ptr, &start)) {
if (ptr == start)
printf ("Pointer is the start of object %p in oldspace.\n", start);
printf ("Pointer inside oldspace.\n");
if (start)
ptr = start;
+ vtable = major_collector.describe_pointer (ptr);
} else if (major_collector.obj_is_from_pinned_alloc (ptr)) {
+ // FIXME: Handle pointers to the inside of objects
printf ("Pointer is inside a pinned chunk.\n");
+ vtable = (MonoVTable*)LOAD_VTABLE (ptr);
} else {
printf ("Pointer unknown.\n");
return;
goto restart;
}
- // FIXME: Handle pointers to the inside of objects
- vtable = (MonoVTable*)LOAD_VTABLE (ptr);
-
printf ("VTable: %p\n", vtable);
if (vtable == NULL) {
printf ("VTable is invalid (empty).\n");
- return;
+ goto bridge;
}
if (sgen_ptr_in_nursery (vtable)) {
printf ("VTable is invalid (points inside nursery).\n");
- return;
+ goto bridge;
}
printf ("Class: %s\n", vtable->klass->name);
type = desc & 0x7;
printf ("Descriptor type: %d (%s)\n", type, descriptor_types [type]);
+
+ size = sgen_safe_object_get_size ((MonoObject*)ptr);
+ printf ("Size: %d\n", (int)size);
+
+ bridge:
+ sgen_bridge_describe_pointer ((MonoObject*)ptr);
+}
+
+void
+describe_ptr (char *ptr)
+{
+ describe_pointer (ptr, TRUE);
}
static gboolean missing_remsets;
#define HANDLE_PTR(ptr,obj) do { \
if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
if (!sgen_get_remset ()->find_address ((char*)(ptr))) { \
- SGEN_LOG (1, "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); \
+ 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); \
binary_protocol_missing_remset ((obj), (gpointer)LOAD_VTABLE ((obj)), (char*)(ptr) - (char*)(obj), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
if (!object_is_pinned (*(ptr))) \
missing_remsets = TRUE; \
GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name);
-#define SCAN_OBJECT_ACTION
#include "sgen-scan-object.h"
}
g_assert (!missing_remsets);
}
+static gboolean
+is_major_or_los_object_marked (char *obj)
+{
+ if (sgen_safe_object_get_size ((MonoObject*)obj) > SGEN_MAX_SMALL_OBJ_SIZE) {
+ return sgen_los_object_is_pinned (obj);
+ } else {
+ return sgen_get_major_collector ()->is_object_live (obj);
+ }
+}
+
+#undef HANDLE_PTR
+#define HANDLE_PTR(ptr,obj) do { \
+ if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((char*)*(ptr))) { \
+ if (!sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
+ 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); \
+ binary_protocol_missing_remset ((obj), (gpointer)LOAD_VTABLE ((obj)), (char*)(ptr) - (char*)(obj), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
+ } \
+ } \
+ } while (0)
+
+static void
+check_mod_union_callback (char *start, size_t size, void *dummy)
+{
+ gboolean in_los = (gboolean) (size_t) dummy;
+ GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
+ guint8 *cards;
+ SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name);
+
+ if (!is_major_or_los_object_marked (start))
+ return;
+
+ if (in_los)
+ cards = sgen_los_header_for_object (start)->cardtable_mod_union;
+ else
+ cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_object (start);
+
+ SGEN_ASSERT (0, cards, "we must have mod union for marked major objects");
+
+#include "sgen-scan-object.h"
+}
+
+void
+sgen_check_mod_union_consistency (void)
+{
+ missing_remsets = FALSE;
+
+ major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
+
+ sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_mod_union_callback, (void*)TRUE);
+
+ if (!binary_protocol_is_enabled ())
+ g_assert (!missing_remsets);
+}
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
static void
check_major_refs_callback (char *start, size_t size, void *dummy)
{
-#define SCAN_OBJECT_ACTION
#include "sgen-scan-object.h"
}
valid_nursery_objects [valid_nursery_object_count++] = object;
}
+static void
+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_object_count = 0;
+ sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE);
+}
+
static gboolean
find_object_in_nursery_dump (char *object)
{
return FALSE;
}
-static void
-describe_nursery_ptr (char *ptr)
+static char*
+describe_nursery_ptr (char *ptr, gboolean need_setup)
{
int i;
+ if (need_setup)
+ setup_valid_nursery_objects ();
+
for (i = 0; i < valid_nursery_object_count; ++i) {
if (valid_nursery_objects [i] >= ptr)
break;
}
if (i >= valid_nursery_object_count || valid_nursery_objects [i] + safe_object_get_size ((MonoObject *)valid_nursery_objects [i]) < ptr) {
- SGEN_LOG (1, "nursery-ptr (unalloc'd-memory)");
+ SGEN_LOG (0, "nursery-ptr (unalloc'd-memory)\n");
+ return NULL;
} else {
char *obj = valid_nursery_objects [i];
- MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
- int size = safe_object_get_size ((MonoObject *)obj);
-
if (obj == ptr)
- SGEN_LOG (1, "nursery-ptr (object %s.%s size %d)",
- vtable->klass->name_space, vtable->klass->name, size);
+ SGEN_LOG (0, "nursery-ptr\n");
else
- SGEN_LOG (1, "nursery-ptr (interior-ptr offset %td of %p (%s.%s) size %d)",
- ptr - obj, obj,
- vtable->klass->name_space, vtable->klass->name, size);
+ SGEN_LOG (0, "nursery-ptr (interior-ptr offset %td)\n", ptr - obj);
+ return obj;
}
}
return FALSE;
}
-
-static void
-describe_pointer (char *ptr)
-{
- if (sgen_ptr_in_nursery (ptr)) {
- describe_nursery_ptr (ptr);
- } else if (major_collector.describe_pointer (ptr)) {
- //Nothing really
- } else if (!mono_sgen_los_describe_pointer (ptr)) {
- SGEN_LOG (1, "\tnon-heap-ptr");
- }
-}
-
static void
bad_pointer_spew (char *obj, char **slot)
{
char *ptr = *slot;
MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
- SGEN_LOG (1, "Invalid object pointer %p at offset %td in object %p (%s.%s):", ptr,
+ SGEN_LOG (0, "Invalid object pointer %p at offset %td in object %p (%s.%s):", ptr,
(char*)slot - obj,
obj, vtable->klass->name_space, vtable->klass->name);
- describe_pointer (ptr);
+ describe_pointer (ptr, FALSE);
broken_heap = TRUE;
}
char *ptr = *slot;
MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
- SGEN_LOG (1, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.",
+ SGEN_LOG (0, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.",
ptr, (char*)slot - obj, obj,
vtable->klass->name_space, vtable->klass->name);
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))) \
+ if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup ((char*)*(ptr)) && (!allow_missing_pinned || !SGEN_OBJECT_IS_PINNED ((char*)*(ptr)))) \
missing_remset_spew ((char*)obj, (char**)ptr); \
} \
} \
} while (0)
static void
-verify_object_pointers_callback (char *start, size_t size, void *dummy)
+verify_object_pointers_callback (char *start, size_t size, void *data)
{
-#define SCAN_OBJECT_ACTION
+ gboolean allow_missing_pinned = (gboolean) (size_t) data;
+
#include "sgen-scan-object.h"
}
depend on OP_DUMMY_USE.
*/
void
-sgen_check_whole_heap (void)
+sgen_check_whole_heap (gboolean allow_missing_pinned)
{
- /*setup valid_nursery_objects*/
- if (!valid_nursery_objects)
- valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging data");
- 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);
+ setup_valid_nursery_objects ();
broken_heap = FALSE;
- sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, NULL, FALSE);
- major_collector.iterate_objects (TRUE, TRUE, verify_object_pointers_callback, NULL);
- sgen_los_iterate_objects (verify_object_pointers_callback, NULL);
+ sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE);
+ major_collector.iterate_objects (TRUE, TRUE, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
+ sgen_los_iterate_objects (verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
g_assert (!broken_heap);
}
continue;
while (start < (char**)info->stack_end) {
if (*start >= obj && *start < endobj) {
- SGEN_LOG (1, "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);
+ 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);
}
start++;
}
#endif
if (w >= (mword)obj && w < (mword)obj + size)
- SGEN_LOG (1, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, j, info, (gpointer)mono_thread_info_get_tid (info));
+ 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
}
}
if (!root->root_desc) {
while (start < (char**)root->end_root) {
if (*start >= obj && *start < endobj) {
- SGEN_LOG (1, "Object %p referenced in pinned roots %p-%p\n", obj, start, root->end_root);
+ SGEN_LOG (0, "Object %p referenced in pinned roots %p-%p\n", obj, start, root->end_root);
}
start++;
}
find_pinning_ref_from_thread (obj, size);
}
+#undef HANDLE_PTR
+#define HANDLE_PTR(ptr,obj) do { \
+ char* __target = *(char**)ptr; \
+ if (__target) { \
+ g_assert (is_valid_object_pointer (__target)); \
+ if (sgen_ptr_in_nursery (__target)) { \
+ g_assert (SGEN_OBJECT_IS_PINNED (__target)); \
+ } else if (sgen_los_is_valid_object (__target)) { \
+ g_assert (sgen_los_object_is_pinned (__target)); \
+ } else if (major_collector.is_valid_object (__target)) { \
+ g_assert (major_collector.is_object_live (__target)); \
+ } else { \
+ g_assert_not_reached (); \
+ } \
+ } \
+ } while (0)
+
+static void
+check_marked_callback (char *start, size_t size, void *dummy)
+{
+ gboolean is_los = (gboolean) (size_t) dummy;
+
+ if (is_los) {
+ if (!sgen_los_object_is_pinned (start))
+ return;
+ } else {
+ if (!major_collector.is_object_live (start))
+ return;
+ }
+
+#include "sgen-scan-object.h"
+}
+
+void
+sgen_check_major_heap_marked (void)
+{
+ setup_valid_nursery_objects ();
+
+ major_collector.iterate_objects (TRUE, TRUE, check_marked_callback, (void*)FALSE);
+ sgen_los_iterate_objects (check_marked_callback, (void*)TRUE);
+}
+
+static void
+check_nursery_objects_pinned_callback (char *obj, size_t size, void *data /* ScanCopyContext *ctx */)
+{
+ gboolean pinned = (gboolean) (size_t) data;
+
+ g_assert (!SGEN_OBJECT_IS_FORWARDED (obj));
+ if (pinned)
+ g_assert (SGEN_OBJECT_IS_PINNED (obj));
+ else
+ g_assert (!SGEN_OBJECT_IS_PINNED (obj));
+}
+
+void
+sgen_check_nursery_objects_pinned (gboolean pinned)
+{
+ 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);
+}
+
#endif /*HAVE_SGEN_GC*/