Mon Apr 29 12:47:36 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / gc.c
1 /*
2  * metadata/gc.c: GC icalls.
3  *
4  * Author: Paolo Molaro <lupus@ximian.com>
5  *
6  * (C) 2002 Ximian, Inc.
7  */
8
9 #include <config.h>
10 #include <glib.h>
11
12 #include <mono/metadata/gc.h>
13 #include <mono/metadata/threads.h>
14 #if HAVE_BOEHM_GC
15 #include <gc/gc.h>
16 #endif
17
18 static int finalize_slot = -1;
19
20 /* 
21  * actually, we might want to queue the finalize requests in a separate thread,
22  * but we need to be careful about the execution domain of the thread...
23  */
24 static void
25 run_finalize (void *obj, void *data)
26 {
27         MonoObject *o;
28         o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));
29
30         if (finalize_slot < 0) {
31                 int i;
32                 for (i = 0; i < mono_defaults.object_class->vtable_size; ++i) {
33                         MonoMethod *cm = mono_defaults.object_class->vtable [i];
34                
35                         if (!strcmp (cm->name, "Finalize")) {
36                                 finalize_slot = i;
37                                 break;
38                         }
39                 }
40         }
41         /* speedup later... */
42         /*
43          * mono crashes (see bug#23778)
44          g_print ("finalizer is run on %s at %p\n", mono_object_class(o)->name, o);
45          mono_runtime_invoke (o->vtable->klass->vtable [finalize_slot], obj, NULL);
46          */
47 }
48
49 /*
50  * Some of our objects may point to a different address than the address returned by GC_malloc()
51  * (because of the GetHashCode hack), but we need to pass the real address to register_finalizer.
52  * This also means that in the callback we need to adjust the pointer to get back the real
53  * MonoObject*.
54  * We also need to be consistent in the use of the GC_debug* variants of malloc and register_finalizer, 
55  * since that, too, can cause the underlying pointer to be offset.
56  */
57 static void
58 object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*))
59 {
60 #if HAVE_BOEHM_GC
61         guint offset = 0;
62         if (mono_object_class (obj)->ghcimpl)
63                 offset += 4;
64         /*g_print ("registering %s at %p (base: %p)\n", mono_object_class (obj)->name, obj, GC_base (obj));*/
65         GC_register_finalizer ((char*)obj - offset, run_finalize, GUINT_TO_POINTER (offset), NULL, NULL);
66 #endif
67 }
68
69 void
70 mono_object_register_finalizer (MonoObject *obj)
71 {
72         object_register_finalizer (obj, run_finalize);
73 }
74
75 void
76 ves_icall_System_GC_InternalCollect (int generation)
77 {
78 #if HAVE_BOEHM_GC
79         GC_gcollect ();
80 #endif
81 }
82
83 gint64
84 ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection)
85 {
86 #if HAVE_BOEHM_GC
87         if (forceCollection)
88                 GC_gcollect ();
89         return GC_get_heap_size ();
90 #else
91         return 0;
92 #endif
93 }
94
95 void
96 ves_icall_System_GC_KeepAlive (MonoObject *obj)
97 {
98         /*
99          * Does nothing.
100          */
101 }
102
103 void
104 ves_icall_System_GC_ReRegisterForFinalize (MonoObject *obj)
105 {
106         object_register_finalizer (obj, run_finalize);
107 }
108
109 void
110 ves_icall_System_GC_SuppressFinalize (MonoObject *obj)
111 {
112         object_register_finalizer (obj, NULL);
113 }
114
115 void
116 ves_icall_System_GC_WaitForPendingFinalizers (void)
117 {
118 }
119