[netcore] Implement/fix enum/nullable comparers.
[mono-project.git] / mono / sgen / sgen-copy-object.h
blob17a6e64facb87d7c7e459ad05962e33b224c951c
1 /**
2 * \file
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.
13 * Defines
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);
77 return obj;
80 par_copy_object_no_checks ((char *)destination, vt, obj, objsize);
82 /* set the forwarding pointer */
83 SGEN_FORWARD_OBJECT (obj, destination);
85 if (has_references) {
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);
102 if (!destination) {
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));
126 } else {
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;
137 return destination;
139 #endif
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