{
}
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_pin_stats (int objects_pinned_in_nursery, size_t bytes_pinned_in_nursery, int objects_pinned_in_major, size_t bytes_pinned_in_major)
+{
+}
+
int sgen_thread_handshake (BOOL suspend);
gboolean sgen_suspend_thread (SgenThreadInfo *info);
gboolean sgen_resume_thread (SgenThreadInfo *info);
major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_PINNED, (IterateObjectCallbackFunc)clear_domain_free_major_pinned_object_callback, domain);
if (domain == mono_get_root_domain ()) {
- sgen_pin_stats_print_class_stats ();
+ sgen_pin_stats_report ();
sgen_object_layout_dump (stdout);
}
pin_object (obj_to_pin);
GRAY_OBJECT_ENQUEUE (queue, obj_to_pin, desc);
- sgen_pin_stats_register_object (obj_to_pin, obj_to_pin_size);
+ sgen_pin_stats_register_object (obj_to_pin, GENERATION_NURSERY);
definitely_pinned [count] = obj_to_pin;
count++;
}
void
sgen_pin_object (GCObject *object, GrayQueue *queue)
{
+ SGEN_ASSERT (0, sgen_ptr_in_nursery (object), "We're only supposed to use this for pinning nursery objects when out of memory.");
+
/*
* All pinned objects are assumed to have been staged, so we need to stage as well.
* Also, the count of staged objects shows that "late pinning" happened.
binary_protocol_pin (object, (gpointer)LOAD_VTABLE (object), safe_object_get_size (object));
++objects_pinned;
- sgen_pin_stats_register_object (object, safe_object_get_size (object));
+ sgen_pin_stats_register_object (object, GENERATION_NURSERY);
GRAY_OBJECT_ENQUEUE (queue, object, sgen_obj_get_descriptor_safe (object));
}
time_minor_scan_remsets += TV_ELAPSED (atv, btv);
SGEN_LOG (2, "Old generation scan: %lld usecs", (long long)TV_ELAPSED (atv, btv));
- sgen_pin_stats_print_class_stats ();
+ sgen_pin_stats_report ();
/* FIXME: Why do we do this at this specific, seemingly random, point? */
sgen_client_collecting_minor (&fin_ready_queue, &critical_fin_queue);
sgen_los_pin_object (bigobj->data);
if (SGEN_OBJECT_HAS_REFERENCES (bigobj->data))
GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data, sgen_obj_get_descriptor ((GCObject*)bigobj->data));
- sgen_pin_stats_register_object (bigobj->data, safe_object_get_size (bigobj->data));
+ sgen_pin_stats_register_object (bigobj->data, GENERATION_OLD);
SGEN_LOG (6, "Marked large object %p (%s) size: %lu from roots", bigobj->data,
sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (bigobj->data)),
(unsigned long)sgen_los_object_size (bigobj));
time_major_scan_mod_union += TV_ELAPSED (btv, atv);
}
- sgen_pin_stats_print_class_stats ();
+ sgen_pin_stats_report ();
}
static void
void sgen_free_internal_dynamic (void *addr, size_t size, int type);
void sgen_pin_stats_enable (void);
-void sgen_pin_stats_register_object (GCObject *obj, size_t size);
+void sgen_pin_stats_register_object (GCObject *obj, int generation);
void sgen_pin_stats_register_global_remset (GCObject *obj);
-void sgen_pin_stats_print_class_stats (void);
+void sgen_pin_stats_report (void);
void sgen_sort_addresses (void **array, size_t size);
void sgen_add_to_global_remset (gpointer ptr, GCObject *obj);
MS_CALC_MARK_BIT (word, bit, obj);
SGEN_ASSERT (9, !MS_MARK_BIT (block, word, bit), "object %p already marked", obj);
MS_SET_MARK_BIT (block, word, bit);
- binary_protocol_mark (obj, (gpointer)LOAD_VTABLE (obj), sgen_safe_object_get_size (obj));
+ binary_protocol_mark (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size (obj));
return FALSE;
#endif
return FALSE;
}
-#define LOAD_VTABLE SGEN_LOAD_VTABLE
-
-#define MS_MARK_OBJECT_AND_ENQUEUE_CHECKED(obj,desc,block,queue) do { \
- int __word, __bit; \
- MS_CALC_MARK_BIT (__word, __bit, (obj)); \
- if (!MS_MARK_BIT ((block), __word, __bit) && MS_OBJ_ALLOCED ((obj), (block))) { \
- MS_SET_MARK_BIT ((block), __word, __bit); \
- if (sgen_gc_descr_has_references (desc)) \
- GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \
- binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((obj))); \
- INC_NUM_MAJOR_OBJECTS_MARKED (); \
- } \
- } while (0)
#define MS_MARK_OBJECT_AND_ENQUEUE(obj,desc,block,queue) do { \
int __word, __bit; \
MS_CALC_MARK_BIT (__word, __bit, (obj)); \
MS_SET_MARK_BIT ((block), __word, __bit); \
if (sgen_gc_descr_has_references (desc)) \
GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \
- binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((obj))); \
+ binary_protocol_mark ((obj), (gpointer)SGEN_LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((obj))); \
INC_NUM_MAJOR_OBJECTS_MARKED (); \
} \
} while (0)
if (first_entry == last_entry)
return;
- block->has_pinned = TRUE;
-
entry = sgen_pinning_get_entry (first_entry);
end = sgen_pinning_get_entry (last_entry);
if (index == last_index)
continue;
obj = MS_BLOCK_OBJ (block, index);
- MS_MARK_OBJECT_AND_ENQUEUE_CHECKED (obj, sgen_obj_get_descriptor (obj), block, queue);
+ if (!MS_OBJ_ALLOCED (obj, block))
+ continue;
+ MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue);
+ sgen_pin_stats_register_object (obj, GENERATION_OLD);
last_index = index;
}
+
+ /*
+ * There might have been potential pinning "pointers" into this block, but none of
+ * them pointed to occupied slots, in which case we don't have to pin the block.
+ */
+ if (last_index >= 0)
+ block->has_pinned = TRUE;
}
static inline void
static void
count_nonpinned_callback (GCObject *obj, size_t size, void *data)
{
- GCVTable vtable = LOAD_VTABLE (obj);
+ GCVTable vtable = SGEN_LOAD_VTABLE (obj);
if (SGEN_VTABLE_HAS_REFERENCES (vtable))
++count_nonpinned_ref;
static void
count_pinned_callback (GCObject *obj, size_t size, void *data)
{
- GCVTable vtable = LOAD_VTABLE (obj);
+ GCVTable vtable = SGEN_LOAD_VTABLE (obj);
if (SGEN_VTABLE_HAS_REFERENCES (vtable))
++count_pinned_ref;
static PinStatAddress *pin_stat_addresses = NULL;
static size_t pinned_byte_counts [PIN_TYPE_MAX];
+static size_t pinned_bytes_in_generation [GENERATION_MAX];
+static int pinned_objects_in_generation [GENERATION_MAX];
+
static SgenPointerQueue pinned_objects = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_STATISTICS);
static SgenHashTable pinned_class_hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_STATISTICS, INTERNAL_MEM_STAT_PINNED_CLASS, sizeof (PinnedClassEntry), g_str_hash, g_str_equal);
pin_stat_addresses = NULL;
for (i = 0; i < PIN_TYPE_MAX; ++i)
pinned_byte_counts [i] = 0;
+ for (i = 0; i < GENERATION_MAX; ++i) {
+ pinned_bytes_in_generation [i] = 0;
+ pinned_objects_in_generation [i] = 0;
+ }
sgen_pointer_queue_clear (&pinned_objects);
sgen_hash_table_clean (&pinned_class_hash_table);
sgen_hash_table_clean (&global_remset_class_hash_table);
}
void
-sgen_pin_stats_register_object (GCObject *obj, size_t size)
+sgen_pin_stats_register_object (GCObject *obj, int generation)
{
int pin_types = 0;
+ size_t size = 0;
+
+ if (binary_protocol_is_enabled ()) {
+ size = sgen_safe_object_get_size (obj);
+ pinned_bytes_in_generation [generation] += size;
+ ++pinned_objects_in_generation [generation];
+ }
if (!do_pin_stats)
return;
+ if (!size)
+ size = sgen_safe_object_get_size (obj);
+
pin_stats_count_object_from_tree (obj, size, pin_stat_addresses, &pin_types);
sgen_pointer_queue_add (&pinned_objects, obj);
}
void
-sgen_pin_stats_print_class_stats (void)
+sgen_pin_stats_report (void)
{
char *name;
PinnedClassEntry *pinned_entry;
GlobalRemsetClassEntry *remset_entry;
+ binary_protocol_pin_stats (pinned_objects_in_generation [GENERATION_NURSERY], pinned_bytes_in_generation [GENERATION_NURSERY],
+ pinned_objects_in_generation [GENERATION_OLD], pinned_bytes_in_generation [GENERATION_OLD]);
+
if (!do_pin_stats)
return;
IS_VTABLE_MATCH (FALSE)
END_PROTOCOL_ENTRY_FLUSH
+BEGIN_PROTOCOL_ENTRY4 (binary_protocol_pin_stats, TYPE_INT, objects_pinned_in_nursery, TYPE_SIZE, bytes_pinned_in_nursery, TYPE_INT, objects_pinned_in_major, TYPE_SIZE, bytes_pinned_in_major)
+DEFAULT_PRINT ()
+IS_ALWAYS_MATCH (TRUE)
+MATCH_INDEX (BINARY_PROTOCOL_MATCH)
+IS_VTABLE_MATCH (FALSE)
+END_PROTOCOL_ENTRY
+
#undef BEGIN_PROTOCOL_ENTRY0
#undef BEGIN_PROTOCOL_ENTRY1
#undef BEGIN_PROTOCOL_ENTRY2