2 * metadata/gc.c: GC icalls.
4 * Author: Paolo Molaro <lupus@ximian.com>
6 * (C) 2002 Ximian, Inc.
13 #include <mono/metadata/gc.h>
14 #include <mono/metadata/threads.h>
16 #define GC_I_HIDE_POINTERS
19 #define HIDE_POINTER(v) (v)
20 #define REVEAL_POINTER(v) (v)
23 static int finalize_slot = -1;
26 * actually, we might want to queue the finalize requests in a separate thread,
27 * but we need to be careful about the execution domain of the thread...
30 run_finalize (void *obj, void *data)
32 MonoObject *exc = NULL;
34 o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));
36 if (finalize_slot < 0) {
38 for (i = 0; i < mono_defaults.object_class->vtable_size; ++i) {
39 MonoMethod *cm = mono_defaults.object_class->vtable [i];
41 if (!strcmp (cm->name, "Finalize")) {
47 /* speedup later... */
48 /* g_print ("Finalize run on %s\n", mono_object_class (o)->name); */
49 mono_runtime_invoke (o->vtable->klass->vtable [finalize_slot], o, NULL, &exc);
52 /* fixme: do something useful */
57 * Some of our objects may point to a different address than the address returned by GC_malloc()
58 * (because of the GetHashCode hack), but we need to pass the real address to register_finalizer.
59 * This also means that in the callback we need to adjust the pointer to get back the real
61 * We also need to be consistent in the use of the GC_debug* variants of malloc and register_finalizer,
62 * since that, too, can cause the underlying pointer to be offset.
65 object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*))
70 g_assert (GC_base (obj) == (char*)obj - offset);
71 GC_register_finalizer ((char*)obj - offset, callback, GUINT_TO_POINTER (offset), NULL, NULL);
76 mono_object_register_finalizer (MonoObject *obj)
78 object_register_finalizer (obj, run_finalize);
82 ves_icall_System_GC_InternalCollect (int generation)
90 ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection)
95 return GC_get_heap_size ();
102 ves_icall_System_GC_KeepAlive (MonoObject *obj)
110 ves_icall_System_GC_ReRegisterForFinalize (MonoObject *obj)
112 object_register_finalizer (obj, run_finalize);
116 ves_icall_System_GC_SuppressFinalize (MonoObject *obj)
118 object_register_finalizer (obj, NULL);
122 ves_icall_System_GC_WaitForPendingFinalizers (void)
126 /*static CRITICAL_SECTION handle_section;*/
127 static guint32 next_handle = 0;
128 static gpointer *gc_handles = NULL;
129 static guint32 array_size = 0;
132 * The handle type is encoded in the lower two bits of the handle value:
139 * FIXME: make thread safe and reuse the array entries.
142 ves_icall_System_GCHandle_GetTarget (guint32 handle)
147 obj = gc_handles [handle >> 2];
148 if ((handle & 0x3) > 1)
149 return REVEAL_POINTER (obj);
156 ves_icall_System_GCHandle_GetTargetHandle (MonoObject *obj, guint32 handle, gint32 type)
159 guint32 h, idx = next_handle++;
161 if (idx >= array_size) {
166 new_array = GC_malloc (sizeof (gpointer) * (array_size * 2));
169 memcpy (new_array, gc_handles, sizeof (gpointer) * array_size);
170 /* need to re-register links for weak refs. test if GC_realloc needs the same */
171 for (i = 0; i < array_size; ++i) {
172 if (((gulong)new_array [i]) & 0x1) { /* all and only disguised pointers have it set */
173 GC_general_register_disappearing_link (&(new_array [i]), REVEAL_POINTER (new_array [i]));
178 gc_handles = new_array;
180 g_error ("No GCHandle support built-in");
185 /* resuse the type from the old target */
192 gc_handles [idx] = val;
196 val = (gpointer)HIDE_POINTER (val);
197 gc_handles [idx] = val;
199 GC_general_register_disappearing_link (&(gc_handles [idx]), obj);
201 g_error ("No weakref support");
209 ves_icall_System_GCHandle_FreeHandle (guint32 handle)
211 gc_handles [handle >> 2] = (gpointer)-1;
215 ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle)
220 obj = gc_handles [handle >> 2];
221 if ((handle & 0x3) > 1)
222 return REVEAL_POINTER (obj);