#include "metadata/sgen-gc.h"
#include "metadata/sgen-protocol.h"
#include "metadata/sgen-cardtable.h"
+#include "metadata/sgen-memory-governor.h"
#include "metadata/gc-internal.h"
#define MS_BLOCK_SIZE (16*1024)
};
#ifdef FIXED_HEAP
-static int ms_heap_num_blocks = MS_DEFAULT_HEAP_NUM_BLOCKS;
+static mword ms_heap_num_blocks = MS_DEFAULT_HEAP_NUM_BLOCKS;
static char *ms_heap_start;
static char *ms_heap_end;
char *nursery_start;
mword major_heap_size = ms_heap_num_blocks * MS_BLOCK_SIZE;
mword alloc_size = nursery_size + major_heap_size;
- int i;
+ mword i;
g_assert (ms_heap_num_blocks > 0);
g_assert (nursery_size % MS_BLOCK_SIZE == 0);
if (nursery_align)
g_assert (nursery_align % MS_BLOCK_SIZE == 0);
- nursery_start = sgen_alloc_os_memory_aligned (alloc_size, nursery_align ? nursery_align : MS_BLOCK_SIZE, TRUE);
+ nursery_start = sgen_alloc_os_memory_aligned (alloc_size, nursery_align ? nursery_align : MS_BLOCK_SIZE, TRUE, TRUE, "heap");
ms_heap_start = nursery_start + nursery_size;
ms_heap_end = ms_heap_start + major_heap_size;
- block_infos = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo) * ms_heap_num_blocks, INTERNAL_MEM_MS_BLOCK_INFO);
+ block_infos = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo) * ms_heap_num_blocks, INTERNAL_MEM_MS_BLOCK_INFO, TRUE);
for (i = 0; i < ms_heap_num_blocks; ++i) {
block_infos [i].block = ms_heap_start + i * MS_BLOCK_SIZE;
{
char *start;
if (nursery_align)
- start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE);
+ start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE, TRUE, "nursery");
else
- start = sgen_alloc_os_memory (nursery_size, TRUE);
+ start = sgen_alloc_os_memory (nursery_size, TRUE, TRUE, "nursery");
return start;
}
empty_blocks = block;
block->used = FALSE;
block->zeroed = FALSE;
- sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
+ sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
}
#else
static void*
retry:
if (!empty_blocks) {
- p = sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * MS_BLOCK_ALLOC_NUM, MS_BLOCK_SIZE, TRUE);
+ p = sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * MS_BLOCK_ALLOC_NUM, MS_BLOCK_SIZE, TRUE, TRUE, "major heap section");
for (i = 0; i < MS_BLOCK_ALLOC_NUM; ++i) {
block = p;
{
void *empty;
- sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
+ sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
memset (block, 0, MS_BLOCK_SIZE);
do {
char *obj_start;
int i;
- if (!sgen_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
+ if (!sgen_memgov_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
return FALSE;
#ifdef FIXED_HEAP
*as pinned alloc is requested by the runtime.
*/
if (!res) {
- sgen_collect_major_no_lock ("pinned alloc failure");
- res = alloc_obj (size, TRUE, has_references);
+ sgen_perform_collection (0, GENERATION_OLD, "pinned alloc failure");
+ res = alloc_obj (size, TRUE, has_references);
}
return res;
}
return FALSE;
}
+
+static gboolean
+major_describe_pointer (char *ptr)
+{
+ MSBlockInfo *block;
+
+ FOREACH_BLOCK (block) {
+ int idx;
+ char *obj;
+ gboolean live;
+ MonoVTable *vtable;
+
+ if ((block->block > ptr) || ((block->block + MS_BLOCK_SIZE) <= ptr))
+ continue;
+
+ fprintf (gc_debug_file, "major-ptr (block %p sz %d pin %d ref %d) ",
+ block->block, block->obj_size, block->pinned, block->has_references);
+
+ idx = MS_BLOCK_OBJ_INDEX (ptr, block);
+ obj = (char*)MS_BLOCK_OBJ (block, idx);
+ live = MS_OBJ_ALLOCED (obj, block);
+ vtable = live ? (MonoVTable*)SGEN_LOAD_VTABLE (obj) : NULL;
+
+ if (obj == ptr) {
+ if (live)
+ fprintf (gc_debug_file, "(object %s.%s)", vtable->klass->name_space, vtable->klass->name);
+ else
+ fprintf (gc_debug_file, "(dead-object)");
+ } else {
+ if (live)
+ fprintf (gc_debug_file, "(interior-ptr offset %td of %p %s.%s)",
+ ptr - obj,
+ obj, vtable->klass->name_space, vtable->klass->name);
+ else
+ fprintf (gc_debug_file, "(dead-interior-ptr to %td to %p)",
+ ptr - obj, obj);
+ }
+
+ return TRUE;
+ } END_FOREACH_BLOCK;
+
+ return FALSE;
+}
+
static void
major_check_scan_starts (void)
{
*
* FIXME (2): We should rework this to avoid all those nursery checks.
*/
- if (!sgen_ptr_in_nursery (obj)) { /*marking a nursery object is pretty stupid.*/
+ /*
+ * For the split nursery allocator the object
+ * might still be in the nursery despite
+ * having being promoted, in which case we
+ * can't mark it.
+ */
+ if (!sgen_ptr_in_nursery (obj)) {
block = MS_BLOCK_FOR_OBJ (obj);
MS_CALC_MARK_BIT (word, bit, obj);
DEBUG (9, g_assert (!MS_MARK_BIT (block, word, bit)));
*
* FIXME (2): We should rework this to avoid all those nursery checks.
*/
- if (!sgen_ptr_in_nursery (obj)) { /*marking a nursery object is pretty stupid.*/
+ /*
+ * For the split nursery allocator the object might
+ * still be in the nursery despite having being
+ * promoted, in which case we can't mark it.
+ */
+ if (!sgen_ptr_in_nursery (obj)) {
block = MS_BLOCK_FOR_OBJ (obj);
MS_CALC_MARK_BIT (word, bit, obj);
DEBUG (9, g_assert (!MS_MARK_BIT (block, word, bit)));
if (SGEN_OBJECT_IS_PINNED (obj))
return;
binary_protocol_pin (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size ((MonoObject*)obj));
+ if (MONO_GC_OBJ_PINNED_ENABLED ()) {
+ MONO_GC_OBJ_PINNED (obj, sgen_safe_object_get_size (obj), NULL, GENERATION_OLD);
+ }
SGEN_PIN_OBJECT (obj);
/* FIXME: only enqueue if object has references */
GRAY_OBJECT_ENQUEUE (queue, obj);
} else {
/* an unmarked object */
if (MS_OBJ_ALLOCED (obj, block)) {
+ /*
+ * FIXME: Merge consecutive
+ * slots for lower reporting
+ * overhead. Maybe memset
+ * will also benefit?
+ */
binary_protocol_empty (obj, block->obj_size);
+ MONO_GC_MAJOR_SWEEPED (obj, block->obj_size);
memset (obj, 0, block->obj_size);
}
*(void**)obj = block->free_list;
while (num_empty_blocks > section_reserve) {
void *next = *(void**)empty_blocks;
- sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE);
+ sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE, TRUE);
empty_blocks = next;
/*
* Needs not be atomic because this is running
{
int i;
for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i)
- lists [i] = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+ lists [i] = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
}
#ifdef SGEN_PARALLEL_MARK
#endif
num_block_obj_sizes = ms_calculate_block_obj_sizes (MS_BLOCK_OBJ_SIZE_FACTOR, NULL);
- block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (int) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+ block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (int) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
ms_calculate_block_obj_sizes (MS_BLOCK_OBJ_SIZE_FACTOR, block_obj_sizes);
- evacuate_block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (gboolean) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+ evacuate_block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (gboolean) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
for (i = 0; i < num_block_obj_sizes; ++i)
evacuate_block_obj_sizes [i] = FALSE;
collector->is_worker_thread = major_is_worker_thread;
collector->post_param_init = post_param_init;
collector->is_valid_object = major_is_valid_object;
+ collector->describe_pointer = major_describe_pointer;
collector->major_ops.copy_or_mark_object = major_copy_or_mark_object;
collector->major_ops.scan_object = major_scan_object;