[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mono / metadata / sgen-toggleref.c
blob9a5d98e29339db79f3ce233b13e99bbee2ed3ba7
1 /**
2 * \file
3 * toggleref support for sgen
5 * Author:
6 * Rodrigo Kumpera (kumpera@gmail.com)
8 * Copyright 2011 Xamarin, Inc.
9 * Copyright (C) 2012 Xamarin Inc
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14 #include "config.h"
16 #ifdef HAVE_SGEN_GC
18 #include "sgen/sgen-gc.h"
19 #include "sgen-toggleref.h"
20 #include "sgen/sgen-client.h"
22 #ifndef DISABLE_SGEN_TOGGLEREF
24 /*only one of the two can be non null at a given time*/
25 typedef struct {
26 GCObject *strong_ref;
27 GCObject *weak_ref;
28 } MonoGCToggleRef;
30 static MonoToggleRefStatus (*toggleref_callback) (MonoObject *obj);
31 static MonoGCToggleRef *toggleref_array;
32 static int toggleref_array_size;
33 static int toggleref_array_capacity;
35 void
36 sgen_process_togglerefs (void)
38 int i, w;
39 int toggle_ref_counts [3] = { 0, 0, 0 };
41 SGEN_LOG (4, "Proccessing ToggleRefs %d", toggleref_array_size);
43 for (i = w = 0; i < toggleref_array_size; ++i) {
44 int res;
45 MonoGCToggleRef r = toggleref_array [i];
47 MonoObject *obj;
49 if (r.strong_ref)
50 obj = r.strong_ref;
51 else if (r.weak_ref)
52 obj = r.weak_ref;
53 else
54 continue;
56 res = toggleref_callback (obj);
57 ++toggle_ref_counts [res];
58 switch (res) {
59 case MONO_TOGGLE_REF_DROP:
60 break;
61 case MONO_TOGGLE_REF_STRONG:
62 toggleref_array [w].strong_ref = obj;
63 toggleref_array [w].weak_ref = NULL;
64 ++w;
65 break;
66 case MONO_TOGGLE_REF_WEAK:
67 toggleref_array [w].strong_ref = NULL;
68 toggleref_array [w].weak_ref = obj;
69 ++w;
70 break;
71 default:
72 g_assert_not_reached ();
76 toggleref_array_size = w;
78 SGEN_LOG (4, "Done Proccessing ToggleRefs dropped %d strong %d weak %d final size %d",
79 toggle_ref_counts [MONO_TOGGLE_REF_DROP],
80 toggle_ref_counts [MONO_TOGGLE_REF_STRONG],
81 toggle_ref_counts [MONO_TOGGLE_REF_WEAK],
82 w);
85 void sgen_client_mark_togglerefs (char *start, char *end, ScanCopyContext ctx)
87 CopyOrMarkObjectFunc copy_func = ctx.ops->copy_or_mark_object;
88 SgenGrayQueue *queue = ctx.queue;
89 int i;
91 SGEN_LOG (4, "Marking ToggleRefs %d", toggleref_array_size);
93 for (i = 0; i < toggleref_array_size; ++i) {
94 if (toggleref_array [i].strong_ref) {
95 GCObject *object = toggleref_array [i].strong_ref;
96 if ((char*)object >= start && (char*)object < end) {
97 SGEN_LOG (6, "\tcopying strong slot %d", i);
98 copy_func (&toggleref_array [i].strong_ref, queue);
102 sgen_drain_gray_stack (ctx);
105 void
106 sgen_foreach_toggleref_root (void (*callback)(MonoObject*, gpointer), gpointer data)
108 int i;
109 for (i = 0; i < toggleref_array_size; ++i) {
110 if (toggleref_array [i].strong_ref)
111 callback (toggleref_array [i].strong_ref, data);
115 void sgen_client_clear_togglerefs (char *start, char *end, ScanCopyContext ctx)
117 CopyOrMarkObjectFunc copy_func = ctx.ops->copy_or_mark_object;
118 SgenGrayQueue *queue = ctx.queue;
119 int i;
121 SGEN_LOG (4, "Clearing ToggleRefs %d", toggleref_array_size);
123 for (i = 0; i < toggleref_array_size; ++i) {
124 if (toggleref_array [i].weak_ref) {
125 GCObject *object = toggleref_array [i].weak_ref;
127 if ((char*)object >= start && (char*)object < end) {
128 if (sgen_gc_is_object_ready_for_finalization (object)) {
129 SGEN_LOG (6, "\tcleaning weak slot %d", i);
130 toggleref_array [i].weak_ref = NULL; /* We defer compaction to only happen on the callback step. */
131 } else {
132 SGEN_LOG (6, "\tkeeping weak slot %d", i);
133 copy_func (&toggleref_array [i].weak_ref, queue);
138 sgen_drain_gray_stack (ctx);
141 static void
142 ensure_toggleref_capacity (int capacity)
144 if (!toggleref_array) {
145 toggleref_array_capacity = 32;
146 toggleref_array = (MonoGCToggleRef *)sgen_alloc_internal_dynamic (
147 toggleref_array_capacity * sizeof (MonoGCToggleRef),
148 INTERNAL_MEM_TOGGLEREF_DATA,
149 TRUE);
151 if (toggleref_array_size + capacity >= toggleref_array_capacity) {
152 MonoGCToggleRef *tmp;
153 int old_capacity = toggleref_array_capacity;
154 while (toggleref_array_capacity < toggleref_array_size + capacity)
155 toggleref_array_capacity *= 2;
157 tmp = (MonoGCToggleRef *)sgen_alloc_internal_dynamic (
158 toggleref_array_capacity * sizeof (MonoGCToggleRef),
159 INTERNAL_MEM_TOGGLEREF_DATA,
160 TRUE);
162 memcpy (tmp, toggleref_array, toggleref_array_size * sizeof (MonoGCToggleRef));
164 sgen_free_internal_dynamic (toggleref_array, old_capacity * sizeof (MonoGCToggleRef), INTERNAL_MEM_TOGGLEREF_DATA);
165 toggleref_array = tmp;
170 * mono_gc_toggleref_add:
171 * @object object to register for toggleref processing
172 * @strong_ref if true the object is registered with a strong ref, a weak one otherwise
174 * Register a given object for toggleref processing. It will be stored internally and the toggleref callback will be called
175 * on it until it returns MONO_TOGGLE_REF_DROP or is collected.
177 void
178 mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref)
180 if (!toggleref_callback)
181 return;
183 MONO_ENTER_GC_UNSAFE;
185 SGEN_LOG (4, "Adding toggleref %p %d", object, strong_ref);
187 sgen_gc_lock ();
189 ensure_toggleref_capacity (1);
190 toggleref_array [toggleref_array_size].strong_ref = strong_ref ? object : NULL;
191 toggleref_array [toggleref_array_size].weak_ref = strong_ref ? NULL : object;
192 ++toggleref_array_size;
194 sgen_gc_unlock ();
196 MONO_EXIT_GC_UNSAFE;
200 * mono_gc_toggleref_register_callback:
201 * \param callback callback used to determine the new state of the given object.
203 * The callback must decide the status of a given object. It must return one of the values in the \c MONO_TOGGLE_REF_ enum.
204 * This function is called with the world running but with the GC locked. This means that you can do everything that doesn't
205 * require GC interaction. This includes, but not limited to, allocating objects, (de)registering for finalization, manipulating
206 * gchandles, storing to reference fields or interacting with other threads that might perform such operations.
208 void
209 mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj))
211 toggleref_callback = proccess_toggleref;
214 static MonoToggleRefStatus
215 test_toggleref_callback (MonoObject *obj)
217 MonoToggleRefStatus status = MONO_TOGGLE_REF_DROP;
219 MONO_STATIC_POINTER_INIT (MonoClassField, mono_toggleref_test_field)
221 mono_toggleref_test_field = mono_class_get_field_from_name_full (mono_object_class (obj), "__test", NULL);
222 g_assert (mono_toggleref_test_field);
224 MONO_STATIC_POINTER_INIT_END (MonoClassField, mono_toggleref_test_field)
226 /* In coop mode, important to not call a helper that will pin obj! */
227 mono_field_get_value_internal (obj, mono_toggleref_test_field, &status);
228 printf ("toggleref-cb obj %d\n", status);
229 return status;
232 void
233 sgen_register_test_toggleref_callback (void)
235 toggleref_callback = test_toggleref_callback;
238 #else
240 void
241 mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj))
245 void
246 mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref)
250 #endif
252 #endif