[sgen/mono] Don't leak stack info struct
[mono-project.git] / mono / metadata / handle.c
blob56b9b9353cd706fc6bab6b125dc0112f9b6a4f92
1 /*
2 * handle.c: Handle to object in native code
4 * Authors:
5 * - Ludovic Henry <ludovic@xamarin.com>
6 * - Aleksey Klieger <aleksey.klieger@xamarin.com>
7 * - Rodrigo Kumpera <kumpera@xamarin.com>
9 * Copyright 2016 Dot net foundation.
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13 #include <config.h>
14 #include <glib.h>
16 #include <mono/metadata/handle.h>
17 #include <mono/metadata/object-internals.h>
18 #include <mono/metadata/gc-internals.h>
19 #include <mono/utils/atomic.h>
20 #include <mono/utils/mono-lazy-init.h>
21 #include <mono/utils/mono-threads.h>
22 /* TODO (missing pieces)
24 Add counters for:
25 number of stack marks
26 stack marks per icall
27 mix/max/avg size of stack marks
28 handle stack wastage
30 Actually do something in mono_handle_verify
32 Shrink the handles stack in mono_handle_stack_scan
33 Properly report it to the profiler.
34 Add a boehm implementation
36 TODO (things to explore):
38 There's no convenient way to wrap the object allocation function.
39 Right now we do this:
40 MonoCultureInfoHandle culture = MONO_HANDLE_NEW (MonoCultureInfo, mono_object_new_checked (domain, klass, &error));
42 Maybe what we need is a round of cleanup around all exposed types in the runtime to unify all helpers under the same hoof.
43 Combine: MonoDefaults, GENERATE_GET_CLASS_WITH_CACHE, TYPED_HANDLE_DECL and friends.
44 This would solve the age old issue of making it clear which types are optional and tell that to the linker.
45 We could then generate neat type safe wrappers.
48 const MonoObjectHandle mono_null_value_handle = NULL;
50 #define THIS_IS_AN_OK_NUMBER_OF_HANDLES 100
52 /* Actual handles implementation */
53 MonoRawHandle
54 mono_handle_new (MonoObject *object)
56 MonoThreadInfo *info = mono_thread_info_current ();
57 HandleStack *handles = (HandleStack *)info->handle_stack;
58 HandleChunk *top = handles->top;
60 retry:
61 if (G_LIKELY (top->size < OBJECTS_PER_HANDLES_CHUNK)) {
62 MonoObject **h = &top->objects [top->size++];
63 *h = object;
64 return h;
66 if (G_LIKELY (top->next)) {
67 top = top->next;
68 top->size = 0;
69 handles->top = top;
70 goto retry;
72 HandleChunk *new_chunk = g_new (HandleChunk, 1);
73 new_chunk->size = 0;
74 new_chunk->prev = top;
75 new_chunk->next = NULL;
76 top->next = new_chunk;
77 handles->top = new_chunk;
78 goto retry;
83 HandleStack*
84 mono_handle_stack_alloc (void)
86 HandleStack *stack = g_new (HandleStack, 1);
87 HandleChunk *chunk = g_new (HandleChunk, 1);
89 stack->top = stack->bottom = chunk;
90 chunk->size = 0;
91 chunk->prev = chunk->next = NULL;
92 return stack;
95 void
96 mono_handle_stack_free (HandleStack *stack)
98 if (!stack)
99 return;
100 HandleChunk *c = stack->bottom;
101 while (c) {
102 HandleChunk *next = c->next;
103 g_free (c);
104 c = next;
106 g_free (c);
107 g_free (stack);
110 void
111 mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data)
113 HandleChunk *cur = stack->bottom;
114 HandleChunk *last = stack->top;
116 if (!cur)
117 return;
119 while (cur) {
120 int i;
121 for (i = 0; i < cur->size; ++i)
122 func ((gpointer*)&cur->objects [i], gc_data);
123 if (cur == last)
124 break;
125 cur = cur->next;
129 void
130 mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name)
132 HandleStack *handles = (HandleStack *)info->handle_stack;
133 HandleChunk *cur = stackmark->chunk;
134 int size = -stackmark->size; //discard the starting point of the stack
135 while (cur) {
136 size += cur->size;
137 if (cur == handles->top)
138 break;
139 cur = cur->next;
142 if (size > THIS_IS_AN_OK_NUMBER_OF_HANDLES)
143 printf ("%s USED %d handles\n", func_name, size);
147 * Pop the stack until @stackmark and make @value the top value.
149 * @return the new handle for what @value points to
151 MonoRawHandle
152 mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value)
154 g_error ("impl me");
157 /* Temporary place for some of the handle enabled wrapper functions*/
159 MonoStringHandle
160 mono_string_new_handle (MonoDomain *domain, const char *data)
162 return MONO_HANDLE_NEW (MonoString, mono_string_new (domain, data));
165 MonoArrayHandle
166 mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error)
168 return MONO_HANDLE_NEW (MonoArray, mono_array_new_checked (domain, eclass, n, error));
171 #ifdef ENABLE_CHECKED_BUILD
172 /* Checked build helpers */
173 void
174 mono_handle_verify (MonoRawHandle raw_handle)
178 #endif