3 * This is where objects are copied.
5 * Copyright 2001-2003 Ximian, Inc
6 * Copyright 2003-2010 Novell, Inc.
7 * Copyright (C) 2012 Xamarin Inc
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 * GCObject* copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue)
17 * which allocates new space for `obj`, copies it there, forwards `obj` to its new location,
18 * and enqueues the copy into `queue`.
20 * To be defined by the includer:
22 * COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION(vt, obj, objsize, has_refs)
24 * Allocates space for promoting object `obj`, with size `objsize`, and initizializes the
25 * vtable with `vt`. `has_refs` indicates whether the object contains references.
27 * collector_pin_object(obj, queue)
29 * Called when no space for `obj` could be allocated. It must pin `obj` and enqueue it into
30 * `queue` for scanning.
33 extern guint64 stat_copy_object_called_nursery
;
34 extern guint64 stat_objects_copied_nursery
;
36 extern guint64 stat_nursery_copy_object_failed_from_space
;
37 extern guint64 stat_nursery_copy_object_failed_forwarded
;
38 extern guint64 stat_nursery_copy_object_failed_pinned
;
40 extern guint64 stat_slots_allocated_in_vain
;
43 * This function can be used even if the vtable of obj is not valid
44 * anymore, which is the case in the parallel collector.
46 static MONO_ALWAYS_INLINE
void
47 par_copy_object_no_checks (char *destination
, GCVTable vt
, void *obj
, mword objsize
)
49 sgen_client_pre_copy_checks (destination
, vt
, obj
, objsize
);
50 sgen_binary_protocol_copy (obj
, destination
, vt
, objsize
);
52 /* FIXME: assumes object layout */
53 memcpy ((char*)destination
+ sizeof (mword
), (char*)obj
+ sizeof (mword
), objsize
- sizeof (mword
));
55 /* adjust array->bounds */
56 SGEN_ASSERT (9, sgen_vtable_get_descriptor (vt
), "vtable %p has no gc descriptor", vt
);
58 sgen_client_update_copied_object (destination
, vt
, obj
, objsize
);
62 * Copies an object and enqueues it if a queue is given.
63 * This can return OBJ itself on OOM.
65 static MONO_NEVER_INLINE GCObject
*
66 copy_object_no_checks (GCObject
*obj
, SgenGrayQueue
*queue
)
68 GCVTable vt
= SGEN_LOAD_VTABLE_UNCHECKED (obj
);
69 gboolean has_references
= SGEN_VTABLE_HAS_REFERENCES (vt
);
70 mword objsize
= SGEN_ALIGN_UP (sgen_client_par_object_get_size (vt
, obj
));
71 void *destination
= COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION (vt
, obj
, objsize
, has_references
);
73 if (G_UNLIKELY (!destination
)) {
74 /* FIXME: Is this path ever tested? */
75 collector_pin_object (obj
, queue
);
76 sgen_set_pinned_from_failed_allocation (objsize
);
80 par_copy_object_no_checks ((char *)destination
, vt
, obj
, objsize
);
82 /* set the forwarding pointer */
83 SGEN_FORWARD_OBJECT (obj
, destination
);
86 SGEN_LOG (9, "Enqueuing gray object %p (%s)", destination
, sgen_client_vtable_get_name (vt
));
87 GRAY_OBJECT_ENQUEUE_SERIAL (queue
, (GCObject
*)destination
, sgen_vtable_get_descriptor (vt
));
90 return (GCObject
*)destination
;
93 #if defined(COPY_OR_MARK_PARALLEL)
94 static MONO_NEVER_INLINE GCObject
*
95 copy_object_no_checks_par (GCObject
*obj
, SgenGrayQueue
*queue
)
97 mword vtable_word
= *(mword
*)obj
;
98 GCObject
*destination
;
100 destination
= (GCObject
*) SGEN_VTABLE_IS_FORWARDED (vtable_word
);
103 GCVTable vt
= (GCVTable
) vtable_word
;
104 GCObject
*final_destination
;
106 * At this point we know vt is not tagged and we shouldn't access the vtable through obj
107 * since it could get copied at any time by another thread.
109 gboolean has_references
= SGEN_VTABLE_HAS_REFERENCES (vt
);
110 mword objsize
= SGEN_ALIGN_UP (sgen_client_par_object_get_size (vt
, obj
));
111 destination
= COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION (vt
, obj
, objsize
, has_references
);
113 par_copy_object_no_checks ((char*)destination
, vt
, obj
, objsize
);
115 /* FIXME we might need a membar here so other threads see the vtable before we forward */
117 /* set the forwarding pointer */
118 SGEN_FORWARD_OBJECT_PAR (obj
, destination
, final_destination
);
120 if (destination
== final_destination
) {
121 /* In a racing case, only the worker that allocated the object enqueues it */
122 if (has_references
) {
123 SGEN_LOG (9, "Enqueuing gray object %p (%s)", destination
, sgen_client_vtable_get_name (vt
));
124 GRAY_OBJECT_ENQUEUE_PARALLEL (queue
, (GCObject
*)destination
, sgen_vtable_get_descriptor (vt
));
128 * Unlikely case. Clear the allocated object so it doesn't confuse nursery
129 * card table scanning, since it can contain old invalid refs.
130 * FIXME make sure it is not a problem if another threads scans it while we clear
132 mono_gc_bzero_aligned (destination
, objsize
);
133 destination
= final_destination
;
141 #undef COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION
142 #undef COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION
143 #undef collector_pin_object
144 #undef COPY_OR_MARK_PARALLEL