Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / sgen / sgen-copy-object.h
1 /**
2  * \file
3  * This is where objects are copied.
4  *
5  * Copyright 2001-2003 Ximian, Inc
6  * Copyright 2003-2010 Novell, Inc.
7  * Copyright (C) 2012 Xamarin Inc
8  *
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11
12 /*
13  * Defines
14  *
15  *     GCObject* copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue)
16  *
17  * which allocates new space for `obj`, copies it there, forwards `obj` to its new location,
18  * and enqueues the copy into `queue`.
19  *
20  * To be defined by the includer:
21  *
22  *     COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION(vt, obj, objsize, has_refs)
23  *
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.
26  *
27  *     collector_pin_object(obj, queue)
28  *
29  * Called when no space for `obj` could be allocated.  It must pin `obj` and enqueue it into
30  * `queue` for scanning.
31  */
32
33 extern guint64 stat_copy_object_called_nursery;
34 extern guint64 stat_objects_copied_nursery;
35
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;
39
40 extern guint64 stat_slots_allocated_in_vain;
41
42 /*
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.
45  */
46 static MONO_ALWAYS_INLINE void
47 par_copy_object_no_checks (char *destination, GCVTable vt, void *obj, mword objsize)
48 {
49         sgen_client_pre_copy_checks (destination, vt, obj, objsize);
50         binary_protocol_copy (obj, destination, vt, objsize);
51
52         /* FIXME: assumes object layout */
53         memcpy ((char*)destination + sizeof (mword), (char*)obj + sizeof (mword), objsize - sizeof (mword));
54
55         /* adjust array->bounds */
56         SGEN_ASSERT (9, sgen_vtable_get_descriptor (vt), "vtable %p has no gc descriptor", vt);
57
58         sgen_client_update_copied_object (destination, vt, obj, objsize);
59 }
60
61 /*
62  * Copies an object and enqueues it if a queue is given.
63  * This can return OBJ itself on OOM.
64  */
65 static MONO_NEVER_INLINE GCObject *
66 copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue)
67 {
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);
72
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;
78         }
79
80         par_copy_object_no_checks ((char *)destination, vt, obj, objsize);
81
82         /* set the forwarding pointer */
83         SGEN_FORWARD_OBJECT (obj, destination);
84
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));
88         }
89
90         return (GCObject *)destination;
91 }
92
93 #if defined(COPY_OR_MARK_PARALLEL)
94 static MONO_NEVER_INLINE GCObject *
95 copy_object_no_checks_par (GCObject *obj, SgenGrayQueue *queue)
96 {
97         mword vtable_word = *(mword*)obj;
98         GCObject *destination;
99
100         destination = (GCObject*) SGEN_VTABLE_IS_FORWARDED (vtable_word);
101
102         if (!destination) {
103                 GCVTable vt = (GCVTable) vtable_word;
104                 GCObject *final_destination;
105                 /*
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.
108                  */
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);
112
113                 par_copy_object_no_checks ((char*)destination, vt, obj, objsize);
114
115                 /* FIXME we might need a membar here so other threads see the vtable before we forward */
116
117                 /* set the forwarding pointer */
118                 SGEN_FORWARD_OBJECT_PAR (obj, destination, final_destination);
119
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));
125                         }
126                 } else {
127                         /*
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
131                          */
132                         mono_gc_bzero_aligned (destination, objsize);
133                         destination = final_destination;
134                 }
135         }
136
137         return destination;
138 }
139 #endif
140
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