#define MS_MARK_OBJECT_AND_ENQUEUE_CHECKED(obj,desc,block,queue) do { \
int __word, __bit; \
+ SGEN_ASSERT (0, sgen_get_current_collection_generation () == GENERATION_OLD, "Can't majorly enqueue objects when doing minor collection"); \
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 ((block)->has_references) \
+ if (MS_OBJ_ALLOCED ((obj), (block))) { \
+ if ((block)->has_references) { \
GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \
- binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \
+ } else { \
+ MS_SET_MARK_BIT ((block), __word, __bit); \
+ binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \
+ } \
INC_NUM_MAJOR_OBJECTS_MARKED (); \
} \
} while (0)
#define MS_MARK_OBJECT_AND_ENQUEUE(obj,desc,block,queue) do { \
int __word, __bit; \
+ SGEN_ASSERT (0, sgen_get_current_collection_generation () == GENERATION_OLD, "Can't majorly enqueue objects when doing minor collection"); \
MS_CALC_MARK_BIT (__word, __bit, (obj)); \
SGEN_ASSERT (9, MS_OBJ_ALLOCED ((obj), (block)), "object %p not allocated", obj); \
- if (!MS_MARK_BIT ((block), __word, __bit)) { \
- MS_SET_MARK_BIT ((block), __word, __bit); \
- if ((block)->has_references) \
+ { \
+ if ((block)->has_references) { \
GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \
- binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \
+ } else { \
+ MS_SET_MARK_BIT ((block), __word, __bit); \
+ binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \
+ } \
INC_NUM_MAJOR_OBJECTS_MARKED (); \
} \
} while (0)
block = MS_BLOCK_FOR_OBJ (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 ((MonoObject*)obj));
+ if (!SGEN_VTABLE_HAS_REFERENCES (LOAD_VTABLE (obj))) {
+ MS_SET_MARK_BIT (block, word, bit);
+ binary_protocol_mark (obj, (gpointer)LOAD_VTABLE (obj), sgen_safe_object_get_size ((MonoObject*)obj));
+ }
}
} else {
char *forwarded;
}
#endif
- sgen_los_pin_object (obj);
if (SGEN_OBJECT_HAS_REFERENCES (obj))
GRAY_OBJECT_ENQUEUE (queue, obj, sgen_obj_get_descriptor (obj));
}
static gboolean
optimized_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue)
{
- MSBlockInfo *block;
- mword vtable_word = *(mword*)obj;
-
- /* we probably only want to prefetch for major heap objects */
- // PREFETCH ((void*)vtable_word);
-
HEAVY_STAT (++stat_optimized_copy_object_called);
SGEN_ASSERT (9, obj, "null object from pointer %p", ptr);
SGEN_ASSERT (9, current_collection_generation == GENERATION_OLD, "old gen parallel allocator called from a %d collection", current_collection_generation);
if (sgen_ptr_in_nursery (obj)) {
- int word, bit;
+ mword vtable_word = *(mword*)obj;
char *forwarded, *old_obj;
HEAVY_STAT (++stat_optimized_nursery);
old_obj = obj;
obj = copy_object_no_checks (obj, queue);
- if (G_UNLIKELY (old_obj == obj)) {
- HEAVY_STAT (++stat_optimized_nursery_not_copied);
- /*If we fail to evacuate an object we just stop doing it for a given block size as all other will surely fail too.*/
- if (!sgen_ptr_in_nursery (obj)) {
- int size_index;
- block = MS_BLOCK_FOR_OBJ (obj);
- size_index = block->obj_size_index;
- evacuate_block_obj_sizes [size_index] = FALSE;
- MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue);
- return FALSE;
- }
- return TRUE;
- }
+ SGEN_ASSERT (0, old_obj != obj, "Cannot handle copy object failure.");
+
*ptr = obj;
HEAVY_STAT (++stat_optimized_nursery_regular);
- /*
- * FIXME: See comment for copy_object_no_checks(). If
- * we have that, we can let the allocation function
- * give us the block info, too, and we won't have to
- * re-fetch it.
- *
- * FIXME (2): We should rework this to avoid all those nursery checks.
- */
- /*
- * 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.
- */
- block = MS_BLOCK_FOR_OBJ (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 ((MonoObject*)obj));
return FALSE;
} else {
- mword desc = sgen_vtable_get_descriptor ((MonoVTable*)vtable_word);
- int type = desc & 7;
-
- HEAVY_STAT (++stat_optimized_major);
-
- if (type == DESC_TYPE_SMALL_BITMAP) {
- int __word, __bit;
-
- HEAVY_STAT (++stat_optimized_major_small_fast);
-
- block = MS_BLOCK_FOR_OBJ (obj);
- MS_CALC_MARK_BIT (__word, __bit, (obj));
- if (!MS_MARK_BIT ((block), __word, __bit)) {
- MS_SET_MARK_BIT ((block), __word, __bit);
- GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc));
- }
- } else if (SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)obj)) <= SGEN_MAX_SMALL_OBJ_SIZE ) {
- HEAVY_STAT (++stat_optimized_major_small_slow);
-
- block = MS_BLOCK_FOR_OBJ (obj);
- MS_MARK_OBJECT_AND_ENQUEUE (obj, desc, block, queue);
- } else {
- HEAVY_STAT (++stat_optimized_major_large);
-
- if (sgen_los_object_is_pinned (obj))
- return FALSE;
- binary_protocol_pin (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size ((MonoObject*)obj));
-
- sgen_los_pin_object (obj);
- if (SGEN_OBJECT_HAS_REFERENCES (obj))
- GRAY_OBJECT_ENQUEUE (queue, obj, sgen_obj_get_descriptor (obj));
- }
- return FALSE;
+ GRAY_OBJECT_ENQUEUE (queue, obj, 0);
}
+ return FALSE;
}
static gboolean
return TRUE;
#endif
-#ifndef SGEN_GRAY_QUEUE_HAVE_DESCRIPTORS
desc = sgen_obj_get_descriptor_safe (obj);
-#endif
+ type = desc & 7;
+
+ HEAVY_STAT (++stat_optimized_major);
+
+ /* Mark object or, if already marked, don't process. */
+ if (!sgen_ptr_in_nursery (obj)) {
+ if (type == DESC_TYPE_SMALL_BITMAP || SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)obj)) <= SGEN_MAX_SMALL_OBJ_SIZE) {
+ MSBlockInfo *block = MS_BLOCK_FOR_OBJ (obj);
+ int __word, __bit;
+
+ HEAVY_STAT (++stat_optimized_major_small_fast);
+
+ MS_CALC_MARK_BIT (__word, __bit, (obj));
+ if (MS_MARK_BIT ((block), __word, __bit))
+ continue;
+ MS_SET_MARK_BIT ((block), __word, __bit);
+ } else {
+ HEAVY_STAT (++stat_optimized_major_large);
+
+ if (sgen_los_object_is_pinned (obj))
+ continue;
+ sgen_los_pin_object (obj);
+ }
+ }
+
+ /* Now scan the object. */
#ifdef HEAVY_STATISTICS
sgen_descriptor_count_scanned_object (desc);
#endif
- type = desc & 7;
if (type == DESC_TYPE_SMALL_BITMAP) {
void **_objptr = (void**)(obj);
gsize _bmap = (desc) >> 16;
void *__old = *(_objptr);
if (__old) {
- gboolean still_in_nursery;
- still_in_nursery = optimized_copy_or_mark_object (_objptr, __old, queue);
+ gboolean still_in_nursery = optimized_copy_or_mark_object (_objptr, __old, queue);
if (G_UNLIKELY (still_in_nursery && !sgen_ptr_in_nursery ((_objptr)))) {
void *__copy = *(_objptr);
sgen_add_to_global_remset ((_objptr), __copy);
_objptr ++;
} while (_bmap);
} else {
- major_scan_object (obj, desc, queue);
+ major_scan_object_no_mark (obj, desc, queue);
}
}
}
for (i = 0; i < num_block_obj_sizes; ++i) {
float usage = (float)slots_used [i] / (float)slots_available [i];
if (num_blocks [i] > 5 && usage < evacuation_threshold) {
+ g_assert_not_reached ();
evacuate_block_obj_sizes [i] = TRUE;
/*
g_print ("slot size %d - %d of %d used\n",