- MSBlockInfo *block;
-
- HEAVY_STAT (++stat_copy_object_called_major);
-
- 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;
- char *forwarded, *old_obj;
-
- if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
- *ptr = forwarded;
- return;
- }
- if (SGEN_OBJECT_IS_PINNED (obj))
- return;
-
- /* An object in the nursery To Space has already been copied and grayed. Nothing to do. */
- if (sgen_nursery_is_to_space (obj))
- return;
-
- HEAVY_STAT (++stat_objects_copied_major);
-
- do_copy_object:
- old_obj = obj;
- obj = copy_object_no_checks (obj, queue);
- if (G_UNLIKELY (old_obj == obj)) {
- /*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;
- }
- *ptr = obj;
-
- /*
- * 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.
- */
- if (!sgen_ptr_in_nursery (obj)) {
- 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));
- }
- } else {
- char *forwarded;
- mword objsize;