+/*
+ * Copyright 2001-2003 Ximian, Inc
+ * Copyright 2003-2010 Novell, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
extern long long stat_copy_object_called_nursery;
extern long long stat_objects_copied_nursery;
DEBUG (9, fprintf (gc_debug_file, " (to %p, %s size: %lu)\n", destination, ((MonoObject*)obj)->vtable->klass->name, (unsigned long)objsize));
binary_protocol_copy (obj, destination, vt, objsize);
- *(MonoVTable**)destination = vt;
if (objsize <= sizeof (gpointer) * 8) {
mword *dest = (mword*)destination;
goto *copy_labels [objsize / sizeof (gpointer)];
LAB_0:
;
} else {
- memcpy (destination + sizeof (mword), (char*)obj + sizeof (mword), objsize - sizeof (mword));
+ /*can't trust memcpy doing word copies */
+ mono_gc_memmove (destination + sizeof (mword), (char*)obj + sizeof (mword), objsize - sizeof (mword));
}
/* adjust array->bounds */
DEBUG (9, g_assert (vt->gc_descr));
mono_sgen_register_moved_object (obj, destination);
obj = destination;
if (queue) {
- DEBUG (9, fprintf (gc_debug_file, "Enqueuing gray object %p (%s)\n", obj, safe_name (obj)));
+ DEBUG (9, fprintf (gc_debug_file, "Enqueuing gray object %p (%s)\n", obj, mono_sgen_safe_name (obj)));
GRAY_OBJECT_ENQUEUE (queue, obj);
}
}
mword objsize = SGEN_ALIGN_UP (mono_sgen_par_object_get_size (vt, (MonoObject*)obj));
char *destination = major_alloc_object (objsize, has_references);
+ if (G_UNLIKELY (!destination)) {
+ if (ptr_in_nursery (obj)) {
+ mono_sgen_pin_object (obj, queue);
+ } else {
+ g_assert (objsize <= SGEN_MAX_SMALL_OBJ_SIZE);
+ pin_major_object (obj, queue);
+ }
+ mono_sgen_set_pinned_from_failed_allocation (objsize);
+ return obj;
+ }
+
+ *(MonoVTable**)destination = vt;
par_copy_object_no_checks (destination, vt, obj, objsize, has_references ? queue : NULL);
/* set the forwarding pointer */
*/
static void
-copy_object (void **obj_slot, SgenGrayQueue *queue)
+nopar_copy_object (void **obj_slot, SgenGrayQueue *queue)
{
char *forwarded;
char *obj = *obj_slot;
*/
if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
- DEBUG (9, g_assert (((MonoVTable*)LOAD_VTABLE(obj))->gc_descr));
+ DEBUG (9, g_assert (((MonoVTable*)SGEN_LOAD_VTABLE(obj))->gc_descr));
DEBUG (9, fprintf (gc_debug_file, " (already forwarded to %p)\n", forwarded));
HEAVY_STAT (++stat_nursery_copy_object_failed_forwarded);
*obj_slot = forwarded;
return;
}
if (SGEN_OBJECT_IS_PINNED (obj)) {
- DEBUG (9, g_assert (((MonoVTable*)LOAD_VTABLE(obj))->gc_descr));
+ DEBUG (9, g_assert (((MonoVTable*)SGEN_LOAD_VTABLE(obj))->gc_descr));
DEBUG (9, fprintf (gc_debug_file, " (pinned, no change)\n"));
HEAVY_STAT (++stat_nursery_copy_object_failed_pinned);
return;
*obj_slot = copy_object_no_checks (obj, queue);
}
+#ifdef SGEN_PARALLEL_MARK
+static void
+copy_object (void **obj_slot, SgenGrayQueue *queue)
+{
+ char *obj = *obj_slot;
+ mword vtable_word, objsize;
+ MonoVTable *vt;
+ void *destination;
+ gboolean has_references;
+
+ DEBUG (9, g_assert (current_collection_generation == GENERATION_NURSERY));
+
+ HEAVY_STAT (++stat_copy_object_called_nursery);
+
+ if (!ptr_in_nursery (obj)) {
+ HEAVY_STAT (++stat_nursery_copy_object_failed_from_space);
+ return;
+ }
+
+ vtable_word = *(mword*)obj;
+ vt = (MonoVTable*)(vtable_word & ~SGEN_VTABLE_BITS_MASK);
+
+ /*
+ * Before we can copy the object we must make sure that we are
+ * allowed to, i.e. that the object not pinned or not already
+ * forwarded.
+ */
+
+ if (vtable_word & SGEN_FORWARDED_BIT) {
+ HEAVY_STAT (++stat_nursery_copy_object_failed_forwarded);
+ *obj_slot = vt;
+ return;
+ }
+ if (vtable_word & SGEN_PINNED_BIT) {
+ HEAVY_STAT (++stat_nursery_copy_object_failed_pinned);
+ return;
+ }
+
+ HEAVY_STAT (++stat_objects_copied_nursery);
+
+ objsize = SGEN_ALIGN_UP (mono_sgen_par_object_get_size (vt, (MonoObject*)obj));
+ has_references = SGEN_VTABLE_HAS_REFERENCES (vt);
+
+ destination = alloc_obj_par (objsize, FALSE, has_references);
+
+ if (G_UNLIKELY (!destination)) {
+ pin_or_update_par (obj_slot, obj, vt, queue);
+ return;
+ }
+
+ *(MonoVTable**)destination = vt;
+
+ if (SGEN_CAS_PTR ((void*)obj, (void*)((mword)destination | SGEN_FORWARDED_BIT), vt) == vt) {
+ par_copy_object_no_checks (destination, vt, obj, objsize, has_references ? queue : NULL);
+ obj = destination;
+ *obj_slot = obj;
+ } else {
+ /* FIXME: unify with code in major_copy_or_mark_object() */
+
+ /* FIXME: Give destination back to the allocator. */
+ *(void**)destination = NULL;
+
+ vtable_word = *(mword*)obj;
+ g_assert (vtable_word & SGEN_FORWARDED_BIT);
+
+ obj = (void*)(vtable_word & ~SGEN_VTABLE_BITS_MASK);
+
+ *obj_slot = obj;
+
+ ++stat_slots_allocated_in_vain;
+ }
+}
+#else
+static void
+copy_object (void **obj_slot, SgenGrayQueue *queue)
+{
+ nopar_copy_object (obj_slot, queue);
+}
+#endif
+
#define FILL_COLLECTOR_COPY_OBJECT(collector) do { \
(collector)->copy_object = copy_object; \
+ (collector)->nopar_copy_object = nopar_copy_object; \
} while (0)