2 * handle.c: Handle to object in native code
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.
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)
27 mix/max/avg size of stack marks
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.
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 MonoObject *null_cell = { NULL };
49 const MonoObjectHandle mono_null_value_handle = { (MonoObject**)&null_cell };
51 #define THIS_IS_AN_OK_NUMBER_OF_HANDLES 100
53 /* Actual handles implementation */
55 mono_handle_new (MonoObject *object)
57 MonoThreadInfo *info = mono_thread_info_current ();
58 HandleStack *handles = (HandleStack *)info->handle_stack;
59 HandleChunk *top = handles->top;
62 if (G_LIKELY (top->size < OBJECTS_PER_HANDLES_CHUNK)) {
63 MonoObject **h = &top->objects [top->size++];
67 if (G_LIKELY (top->next)) {
73 HandleChunk *new_chunk = g_new (HandleChunk, 1);
75 new_chunk->prev = top;
76 new_chunk->next = NULL;
77 top->next = new_chunk;
78 handles->top = new_chunk;
85 mono_handle_stack_alloc (void)
87 HandleStack *stack = g_new (HandleStack, 1);
88 HandleChunk *chunk = g_new (HandleChunk, 1);
90 stack->top = stack->bottom = chunk;
92 chunk->prev = chunk->next = NULL;
97 mono_handle_stack_free (HandleStack *stack)
101 HandleChunk *c = stack->bottom;
103 HandleChunk *next = c->next;
111 mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data)
113 HandleChunk *cur = stack->bottom;
114 HandleChunk *last = stack->top;
121 for (i = 0; i < cur->size; ++i)
122 func ((gpointer*)&cur->objects [i], gc_data);
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
137 if (cur == handles->top)
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
152 mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value)
157 /* Temporary place for some of the handle enabled wrapper functions*/
160 mono_string_new_handle (MonoDomain *domain, const char *data)
162 return MONO_HANDLE_NEW (MonoString, mono_string_new (domain, data));
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 */
174 mono_handle_verify (MonoRawHandle raw_handle)