X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fhandle.c;h=bf538fa6d285f2d5a58a4e46989081bdcbc146a1;hb=1aa82aca7fdd1cc1f9da78625ef21dffa2699498;hp=bf0abc24e4f518b2e1b4b882d9f4d22b7347f669;hpb=1384da6248a8d9a4b96705a56a4c0a58b25c3d19;p=mono.git diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index bf0abc24e4f..bf538fa6d28 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -3,8 +3,11 @@ * * Authors: * - Ludovic Henry + * - Aleksey Klieger + * - Rodrigo Kumpera * - * Copyright 2015 Xamarin, Inc. (www.xamarin.com) + * Copyright 2016 Dot net foundation. + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include @@ -15,192 +18,160 @@ #include #include #include +#include +/* TODO (missing pieces) -#define HANDLES_PER_CHUNK (16 - 2) +Add counters for: + number of stack marks + stack marks per icall + mix/max/avg size of stack marks + handle stack wastage -typedef struct _MonoHandleArenaChunk MonoHandleArenaChunk; -struct _MonoHandleArenaChunk { - MonoHandleArenaChunk *next; - gsize handles_size; - MonoHandleStorage handles [HANDLES_PER_CHUNK]; -}; +Actually do something in mono_handle_verify -struct _MonoHandleArena { - MonoHandleArenaChunk *chunk; - MonoHandleArenaChunk *chunk_last; - MonoHandleArena *prev; -}; +Shrink the handles stack in mono_handle_stack_scan +Properly report it to the profiler. +Add a boehm implementation -static mono_lazy_init_t arena_status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; +TODO (things to explore): -static MonoGCDescriptor arena_desc = MONO_GC_DESCRIPTOR_NULL; +There's no convenient way to wrap the object allocation function. +Right now we do this: + MonoCultureInfoHandle culture = MONO_HANDLE_NEW (MonoCultureInfo, mono_object_new_checked (domain, klass, &error)); -static MonoHandleArenaChunk *chunk_free_list = NULL; +Maybe what we need is a round of cleanup around all exposed types in the runtime to unify all helpers under the same hoof. +Combine: MonoDefaults, GENERATE_GET_CLASS_WITH_CACHE, TYPED_HANDLE_DECL and friends. + This would solve the age old issue of making it clear which types are optional and tell that to the linker. + We could then generate neat type safe wrappers. +*/ -static inline MonoHandleArenaChunk* -chunk_alloc (void) -{ - MonoHandleArenaChunk *old, *new; - - do { - old = chunk_free_list; - if (!old) { - MonoHandleArenaChunk *chunk; - - chunk = g_malloc0 (sizeof (MonoHandleArenaChunk)); - g_assert (chunk); +const MonoObjectHandle mono_null_value_handle = NULL; - return chunk; - } - - new = old->next; - } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, new, old) != old); - - memset (old, 0, sizeof (MonoHandleArenaChunk)); - return old; -} +#define THIS_IS_AN_OK_NUMBER_OF_HANDLES 100 -static inline void -chunk_free (MonoHandleArenaChunk *chunk) +/* Actual handles implementation */ +MonoRawHandle +mono_handle_new (MonoObject *object) { - do { - chunk->next = chunk_free_list; - } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, chunk, chunk->next) != chunk->next); -} - -static MonoHandle -handle_new (MonoHandleArena *arena, MonoObject *obj) -{ - MonoHandleArenaChunk *chunk; - - g_assert (arena->chunk); - g_assert (arena->chunk_last); - - chunk = arena->chunk_last; - - if (chunk->handles_size < HANDLES_PER_CHUNK) { - chunk->handles [chunk->handles_size].__private_obj = obj; - chunk->handles_size += 1; - - return &chunk->handles [chunk->handles_size - 1]; + MonoThreadInfo *info = mono_thread_info_current (); + HandleStack *handles = (HandleStack *)info->handle_stack; + HandleChunk *top = handles->top; + +retry: + if (G_LIKELY (top->size < OBJECTS_PER_HANDLES_CHUNK)) { + MonoObject **h = &top->objects [top->size++]; + *h = object; + return h; } - - chunk = chunk->next = chunk_alloc (); - - chunk->handles [0].__private_obj = obj; - chunk->handles_size = 1; - - arena->chunk_last = chunk; - - return &chunk->handles [0]; + if (G_LIKELY (top->next)) { + top = top->next; + top->size = 0; + handles->top = top; + goto retry; + } + HandleChunk *new_chunk = g_new (HandleChunk, 1); + new_chunk->size = 0; + new_chunk->prev = top; + new_chunk->next = NULL; + top->next = new_chunk; + handles->top = new_chunk; + goto retry; } -MonoHandle -mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj) -{ - g_assert (arena); - return handle_new (arena, obj); -} -/* - * Elevate the handle to the parent arena - */ -MonoHandle -mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle) -{ - g_assert (handle); - g_assert (arena); - g_assert (arena->prev); - - return handle_new (arena->prev, handle->__private_obj); -} -gsize -mono_handle_arena_size (void) +HandleStack* +mono_handle_stack_alloc (void) { - return sizeof (MonoHandleArena) + sizeof (MonoHandleArenaChunk); + HandleStack *stack = g_new (HandleStack, 1); + HandleChunk *chunk = g_new (HandleChunk, 1); + + stack->top = stack->bottom = chunk; + chunk->size = 0; + chunk->prev = chunk->next = NULL; + return stack; } void -mono_handle_arena_stack_push(MonoHandleArena **arena_stack, MonoHandleArena *arena) +mono_handle_stack_free (HandleStack *stack) { - g_assert (arena_stack); - g_assert (arena); - - arena->prev = *arena_stack; - arena->chunk = arena->chunk_last = (MonoHandleArenaChunk*) (((char*) arena) + sizeof (MonoHandleArena)); - - arena->chunk->next = NULL; - arena->chunk->handles_size = 0; - memset (&arena->chunk->handles [0], 0, sizeof (MonoHandleStorage) * HANDLES_PER_CHUNK); - - *arena_stack = arena; + if (!stack) + return; + HandleChunk *c = stack->bottom; + while (c) { + HandleChunk *next = c->next; + g_free (c); + c = next; + } + g_free (c); } void -mono_handle_arena_stack_pop(MonoHandleArena **arena_stack, MonoHandleArena *arena) +mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data) { - MonoHandleArenaChunk *chunk, *next; - - g_assert (arena); - g_assert (arena->chunk); - g_assert (arena->chunk_last); - g_assert (arena_stack); - - *arena_stack = arena->prev; - - for (chunk = arena->chunk; chunk; chunk = next) { - next = chunk->next; - memset (&chunk->handles [0], 0, sizeof (MonoHandleStorage) * HANDLES_PER_CHUNK); - if (chunk != arena->chunk) - chunk_free (chunk); + HandleChunk *cur = stack->bottom; + HandleChunk *last = stack->top; + + if (!cur) + return; + + while (cur) { + int i; + for (i = 0; i < cur->size; ++i) + func ((gpointer*)&cur->objects [i], gc_data); + if (cur == last) + break; + cur = cur->next; } } -static void -arena_scan (gpointer addr, MonoGCMarkFunc mark_func, gpointer gc_data) +void +mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name) { - MonoHandleArena *arena; - MonoHandleArenaChunk *chunk; - int i; - - for (arena = *(MonoHandleArena**) addr; arena; arena = arena->prev) { - for (chunk = arena->chunk; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->handles_size; ++i) { - if (chunk->handles [i].__private_obj != NULL) - mark_func (&chunk->handles [i].__private_obj, gc_data); - } - } + HandleStack *handles = (HandleStack *)info->handle_stack; + HandleChunk *cur = stackmark->chunk; + int size = -stackmark->size; //discard the starting point of the stack + while (cur) { + size += cur->size; + if (cur == handles->top) + break; + cur = cur->next; } -} -static void -initialize (void) -{ - arena_desc = mono_gc_make_root_descr_user (arena_scan); + if (size > THIS_IS_AN_OK_NUMBER_OF_HANDLES) + printf ("%s USED %d handles\n", func_name, size); } -void -mono_handle_arena_initialize (MonoHandleArena **arena_stack) +/* + * Pop the stack until @stackmark and make @value the top value. + * + * @return the new handle for what @value points to + */ +MonoRawHandle +mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value) { - mono_lazy_initialize (&arena_status, initialize); - mono_gc_register_root ((char*) arena_stack, sizeof (MonoHandleArena*), arena_desc, MONO_ROOT_SOURCE_HANDLE, "runtime threads handle arena"); + g_error ("impl me"); } -void -mono_handle_arena_deinitialize (MonoHandleArena **arena_stack) +/* Temporary place for some of the handle enabled wrapper functions*/ + +MonoStringHandle +mono_string_new_handle (MonoDomain *domain, const char *data) { - mono_gc_deregister_root ((char*) arena_stack); + return MONO_HANDLE_NEW (MonoString, mono_string_new (domain, data)); } -MonoHandleArena* -mono_handle_arena_current (void) +MonoArrayHandle +mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error) { - g_assert_not_reached (); + return MONO_HANDLE_NEW (MonoArray, mono_array_new_checked (domain, eclass, n, error)); } -MonoHandleArena** -mono_handle_arena_current_addr (void) +#ifdef ENABLE_CHECKED_BUILD +/* Checked build helpers */ +void +mono_handle_verify (MonoRawHandle raw_handle) { - g_assert_not_reached (); + } +#endif