From 1f88a3dd5c4a0dfdc296be5d0f0f821730229381 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 11:23:05 +0000 Subject: [PATCH 01/20] [handle] Rename handle-private.h to handle-arena.h --- mono/metadata/Makefile.am | 2 +- mono/metadata/{handle-private.h => handle-arena.h} | 0 mono/metadata/handle.c | 2 +- mono/unit-tests/test-mono-handle.c | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename mono/metadata/{handle-private.h => handle-arena.h} (100%) diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index a0d7c20748e1..03229a31166b 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -217,7 +217,7 @@ common_sources = \ seq-points-data.c \ handle.c \ handle.h \ - handle-private.h + handle-arena.h # These source files have compile time dependencies on GC code diff --git a/mono/metadata/handle-private.h b/mono/metadata/handle-arena.h similarity index 100% rename from mono/metadata/handle-private.h rename to mono/metadata/handle-arena.h diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index 885c723be733..3b678bf96725 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include diff --git a/mono/unit-tests/test-mono-handle.c b/mono/unit-tests/test-mono-handle.c index 8fa4aed67382..a450fec8df8e 100644 --- a/mono/unit-tests/test-mono-handle.c +++ b/mono/unit-tests/test-mono-handle.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include static void test2_arena_push_pop () From cc309fdc6ff5872d17b38fb30b2a462906ca6a2a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 11:33:57 +0000 Subject: [PATCH 02/20] [handle] Implement mono_handle_(new|elevate) functions --- mono/metadata/handle-arena.h | 6 ++++++ mono/metadata/handle.c | 31 +++++++++++-------------------- mono/metadata/handle.h | 18 +++++++++++++----- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/mono/metadata/handle-arena.h b/mono/metadata/handle-arena.h index a991b9b47b09..a5f36b1db56e 100644 --- a/mono/metadata/handle-arena.h +++ b/mono/metadata/handle-arena.h @@ -26,4 +26,10 @@ mono_handle_arena_initialize (MonoHandleArena **arena_stack); void mono_handle_arena_deinitialize (MonoHandleArena **arena_stack); +MonoHandleArena* +mono_handle_arena_current (void); + +MonoHandleArena** +mono_handle_arena_current_addr (void); + #endif/*__MONO_HANDLE_PRIVATE_H__*/ diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index 3b678bf96725..6a692d2caf10 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -105,16 +105,6 @@ mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj) return handle_new (arena, obj); } -MonoHandle -mono_handle_new (MonoObject *obj) -{ - /* TODO: finish implementation by placing an arena somewhere - * in the current thread */ - g_assert_not_reached (); - MonoHandleArena *arena = NULL; - return mono_handle_arena_new (arena, obj); -} - /* * Elevate the handle to the parent arena */ @@ -128,16 +118,6 @@ mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle) return handle_new (arena->prev, handle->obj); } -MonoHandle -mono_handle_elevate (MonoHandle handle) -{ - /* TODO: finish implementation by placing an arena somewhere - * in the current thread */ - g_assert_not_reached (); - MonoHandleArena *arena = NULL; - return mono_handle_arena_elevate (arena, handle); -} - gsize mono_handle_arena_size (void) { @@ -222,3 +202,14 @@ mono_handle_arena_deinitialize (MonoHandleArena **arena_stack) #endif } +MonoHandleArena* +mono_handle_arena_current (void) +{ + g_assert_not_reached (); +} + +MonoHandleArena** +mono_handle_arena_current_addr (void) +{ + g_assert_not_reached (); +} diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 82fee80a0fb4..3d38a9a45431 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -17,6 +17,7 @@ #include "class.h" #include "class-internals.h" #include "threads-types.h" +#include "handle-arena.h" #include "mono/utils/mono-threads-coop.h" @@ -36,6 +37,18 @@ struct _MonoHandleStorage { MonoObject *obj; }; +static inline MonoHandle +mono_handle_new (MonoObject *obj) +{ + return mono_handle_arena_new (mono_handle_arena_current (), obj); +} + +static inline MonoHandle +mono_handle_elevate (MonoHandle handle) +{ + return mono_handle_arena_elevate (mono_handle_arena_current (), handle); +} + #ifndef CHECKED_BUILD #define mono_handle_obj(handle) ((handle)->obj) @@ -109,13 +122,8 @@ mono_handle_domain (MonoHandle handle) MONO_FINISH_GC_CRITICAL_REGION; \ } while (0) -/* handle arena specific functions */ -MonoHandle -mono_handle_new (MonoObject *rawptr); -MonoHandle -mono_handle_elevate (MonoHandle handle); /* Some common handle types */ From ea53116c1ffa2b0c4fa27b4ce02f873259321d4f Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 11:40:22 +0000 Subject: [PATCH 03/20] [handle] Fix typo --- mono/metadata/handle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 3d38a9a45431..f7fd83557076 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -118,7 +118,7 @@ mono_handle_domain (MonoHandle handle) #define MONO_HANDLE_ARRAY_SET(handle,type,index,value) \ do { \ MONO_PREPARE_GC_CRITICAL_REGION; \ - mono_array_set (mono_handle_obj ((handle)), (type), (index), (value)); \ + mono_array_set (mono_handle_obj ((handle)), type, (index), (value)); \ MONO_FINISH_GC_CRITICAL_REGION; \ } while (0) From 81de6b245dc34bcaec9542ddb6fd4cb397b11a0a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 13:42:01 +0000 Subject: [PATCH 04/20] [handle] Remove SGen dependency --- mono/metadata/handle.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index 6a692d2caf10..69b48eebf284 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -34,9 +34,7 @@ struct _MonoHandleArena { static mono_lazy_init_t arena_status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; -#ifdef HAVE_SGEN_GC static MonoGCDescriptor arena_desc = MONO_GC_DESCRIPTOR_NULL; -#endif static MonoHandleArenaChunk *chunk_free_list = NULL; @@ -180,26 +178,20 @@ arena_scan (gpointer addr, MonoGCMarkFunc mark_func, gpointer gc_data) static void initialize (void) { -#ifdef HAVE_SGEN_GC arena_desc = mono_gc_make_root_descr_user (arena_scan); -#endif } void mono_handle_arena_initialize (MonoHandleArena **arena_stack) { -#ifdef HAVE_SGEN_GC 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"); -#endif } void mono_handle_arena_deinitialize (MonoHandleArena **arena_stack) { -#ifdef HAVE_SGEN_GC mono_gc_deregister_root ((char*) arena_stack); -#endif } MonoHandleArena* From 783a13d32392548fb987c0ee1f154b1660ef6237 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 13:50:56 +0000 Subject: [PATCH 05/20] [handle] Make handle.h use exclusively public headers and MONO_API functions --- mono/metadata/handle.h | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index f7fd83557076..7fe364e1494e 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -13,18 +13,8 @@ #include #include -#include "object.h" -#include "class.h" -#include "class-internals.h" -#include "threads-types.h" -#include "handle-arena.h" - -#include "mono/utils/mono-threads-coop.h" - -G_BEGIN_DECLS - -typedef struct _MonoHandleStorage MonoHandleStorage; -typedef MonoHandleStorage* MonoHandle; +#include +#include /* * DO NOT ACCESS DIRECTLY @@ -33,9 +23,15 @@ typedef MonoHandleStorage* MonoHandle; * The field obj is not private as there is no way to do that * in C, but using a C++ template would simplify that a lot */ -struct _MonoHandleStorage { +typedef struct { MonoObject *obj; -}; +} MonoHandleStorage; + +typedef MonoHandleStorage* MonoHandle; + +#include "handle-arena.h" + +G_BEGIN_DECLS static inline MonoHandle mono_handle_new (MonoObject *obj) @@ -72,13 +68,13 @@ mono_handle_check_in_critical_section () static inline MonoClass* mono_handle_class (MonoHandle handle) { - return handle->obj->vtable->klass; + return mono_object_get_class (handle->obj); } static inline MonoDomain* mono_handle_domain (MonoHandle handle) { - return handle->obj->vtable->domain; + return mono_object_get_domain (handle->obj); } #define MONO_HANDLE_TYPE_DECL(type) typedef struct { type *obj; } type ## HandleStorage ; \ From 11b8401cde795e8b980004b791182930a70b66ba Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 13:57:08 +0000 Subject: [PATCH 06/20] [handle] Add macro to push/pop arena --- mono/metadata/handle-arena.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mono/metadata/handle-arena.h b/mono/metadata/handle-arena.h index a5f36b1db56e..529256b12ed8 100644 --- a/mono/metadata/handle-arena.h +++ b/mono/metadata/handle-arena.h @@ -32,4 +32,24 @@ mono_handle_arena_current (void); MonoHandleArena** mono_handle_arena_current_addr (void); +#define MONO_HANDLE_ARENA_PUSH() \ + do { \ + MonoHandleArena **__arena_stack = mono_handle_arena_current_addr (); \ + MonoHandleArena *__arena = (MonoHandleArena*) g_alloca (mono_handle_arena_size ()); \ + mono_handle_arena_stack_push (__arena_stack, __arena) + +#define MONO_HANDLE_ARENA_POP \ + mono_handle_arena_stack_pop (__arena_stack, __arena); \ + } while (0) + +#define MONO_HANDLE_ARENA_POP_RETURN_UNSAFE(handle,ret) \ + (ret) = (handle)->obj; \ + mono_handle_arena_stack_pop (__arena_stack, __arena); \ + } while (0) + +#define MONO_HANDLE_ARENA_POP_RETURN(handle,ret_handle) \ + *((MonoHandle**)(&(ret_handle))) = mono_handle_elevate ((MonoHandle*)(handle)); \ + mono_handle_arena_stack_pop(__arena_stack, __arena); \ + } while (0) + #endif/*__MONO_HANDLE_PRIVATE_H__*/ From aadbf4a819aaae061aed6d20558a5022544ac8b4 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 14:01:52 +0000 Subject: [PATCH 07/20] [handle] Add GC alloc function These functions, instead of returning a MonoObject*, return a MonoHandle. This way, we have MonoHandle directly from the bottom of the allocation call stack, making it easier to migrate to this new interface. This is in fact the first step in the migration to a MonoObject* mostly-free code. --- mono/metadata/boehm-gc.c | 30 +++ mono/metadata/gc-internals.h | 6 + mono/metadata/null-gc.c | 30 +++ mono/metadata/sgen-mono.c | 363 +++++++++++++++++++++++++---------- mono/sgen/sgen-alloc.c | 16 +- mono/sgen/sgen-client.h | 8 - mono/sgen/sgen-gc.h | 6 +- 7 files changed, 341 insertions(+), 118 deletions(-) diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 0bd92412414f..0cc91309ef5c 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -1868,4 +1868,34 @@ mono_gchandle_free_domain (MonoDomain *domain) } +/* Handle API specifics */ + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_gc_alloc_obj (MonoVTable *vtable, size_t size, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoObject, mono_gc_alloc_obj (vtable, size)); +} + +MONO_HANDLE_TYPE (MonoArray) +mono_handle_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoArray, mono_gc_alloc_vector (vtable, size, max_length)); +} + +MONO_HANDLE_TYPE (MonoArray) +mono_handle_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoArray, mono_gc_alloc_array (vtable, size, max_length, bounds_size)); +} + +MONO_HANDLE_TYPE (MonoString) +mono_handle_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoString, mono_gc_alloc_string (vtable, size, len)); +} + #endif /* no Boehm GC */ diff --git a/mono/metadata/gc-internals.h b/mono/metadata/gc-internals.h index bc9edcbe3ad1..4b0ba96f1f46 100644 --- a/mono/metadata/gc-internals.h +++ b/mono/metadata/gc-internals.h @@ -155,6 +155,12 @@ void* mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length void* mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len); MonoGCDescriptor mono_gc_make_descr_for_string (gsize *bitmap, int numbits); +MONO_HANDLE_TYPE (MonoObject) mono_handle_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size, MonoError *error); +MONO_HANDLE_TYPE (MonoObject) mono_handle_gc_alloc_obj (MonoVTable *vtable, size_t size, MonoError *error); +MONO_HANDLE_TYPE (MonoArray) mono_handle_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length, MonoError *error); +MONO_HANDLE_TYPE (MonoArray) mono_handle_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size, MonoError *error); +MONO_HANDLE_TYPE (MonoString) mono_handle_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len, MonoError *error); + void mono_gc_register_for_finalization (MonoObject *obj, void *user_data); void mono_gc_add_memory_pressure (gint64 value); MONO_API int mono_gc_register_root (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg); diff --git a/mono/metadata/null-gc.c b/mono/metadata/null-gc.c index e5c16e1e9a46..cbc0114c609a 100644 --- a/mono/metadata/null-gc.c +++ b/mono/metadata/null-gc.c @@ -534,4 +534,34 @@ mono_gc_is_null (void) return TRUE; } +/* Handle API specifics */ + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_gc_alloc_obj (MonoVTable *vtable, size_t size, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoObject, mono_gc_alloc_obj (vtable, size)); +} + +MONO_HANDLE_TYPE (MonoArray) +mono_handle_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoArray, mono_gc_alloc_vector (vtable, size, max_length)); +} + +MONO_HANDLE_TYPE (MonoArray) +mono_handle_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoArray, mono_gc_alloc_array (vtable, size, max_length, bounds_size)); +} + +MONO_HANDLE_TYPE (MonoString) +mono_handle_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len, MonoError *error) +{ + mono_error_init (error); + return MONO_HANDLE_NEW (MonoString, mono_gc_alloc_string (vtable, size, len)); +} + #endif diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 8d3b7c137eb4..84a7b5be165d 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -36,6 +36,8 @@ #include "metadata/gc-internals.h" #include "utils/mono-memory-model.h" #include "utils/mono-logger-internals.h" +#include "utils/mono-error.h" +#include "utils/mono-error-internals.h" #ifdef HEAVY_STATISTICS static guint64 stat_wbarrier_set_arrayref = 0; @@ -933,10 +935,19 @@ mono_gc_enable_alloc_events (void) void* mono_gc_alloc_obj (MonoVTable *vtable, size_t size) { - MonoObject *obj = sgen_alloc_obj (vtable, size); + MonoError error; + MonoObject *obj; - if (G_UNLIKELY (alloc_events)) - mono_profiler_allocation (obj); + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoObject) obj_handle = mono_handle_gc_alloc_obj (vtable, size, &error); + + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (obj_handle, obj); + + if (!mono_error_ok (&error)) { + g_assert (mono_error_get_error_code (&error) == MONO_ERROR_OUT_OF_MEMORY); + return mono_gc_out_of_memory (-1); + } return obj; } @@ -944,10 +955,19 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size) void* mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size) { - MonoObject *obj = sgen_alloc_obj_pinned (vtable, size); + MonoError error; + MonoObject *obj; - if (G_UNLIKELY (alloc_events)) - mono_profiler_allocation (obj); + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoObject) obj_handle = mono_handle_gc_alloc_pinned_obj (vtable, size, &error); + + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (obj_handle, obj); + + if (!mono_error_ok (&error)) { + g_assert (mono_error_get_error_code (&error) == MONO_ERROR_OUT_OF_MEMORY); + return mono_gc_out_of_memory (-1); + } return obj; } @@ -955,7 +975,10 @@ mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size) void* mono_gc_alloc_mature (MonoVTable *vtable) { - MonoObject *obj = sgen_alloc_obj_mature (vtable, vtable->klass->instance_size); + MonoError error; + MonoObject *obj = sgen_alloc_obj_mature (vtable, vtable->klass->instance_size, &error); + + g_assert (mono_error_ok (&error)); if (obj && G_UNLIKELY (obj->vtable->klass->has_finalize)) mono_object_register_finalizer (obj); @@ -1712,129 +1735,60 @@ sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 * void* mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length) { + MonoError error; MonoArray *arr; - TLAB_ACCESS_INIT; - if (!SGEN_CAN_ALIGN_UP (size)) - return NULL; + MONO_HANDLE_ARENA_PUSH (); -#ifndef DISABLE_CRITICAL_REGION - ENTER_CRITICAL_REGION; - arr = (MonoArray*)sgen_try_alloc_obj_nolock (vtable, size); - if (arr) { - /*This doesn't require fencing since EXIT_CRITICAL_REGION already does it for us*/ - arr->max_length = (mono_array_size_t)max_length; - EXIT_CRITICAL_REGION; - goto done; - } - EXIT_CRITICAL_REGION; -#endif + MONO_HANDLE_TYPE (MonoArray) arr_handle = mono_handle_gc_alloc_vector (vtable, size, max_length, &error); - LOCK_GC; + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (arr_handle, arr); - arr = (MonoArray*)sgen_alloc_obj_nolock (vtable, size); - if (G_UNLIKELY (!arr)) { - UNLOCK_GC; - return mono_gc_out_of_memory (size); + if (!mono_error_ok (&error)) { + g_assert (mono_error_get_error_code (&error) == MONO_ERROR_OUT_OF_MEMORY); + return mono_gc_out_of_memory (-1); } - arr->max_length = (mono_array_size_t)max_length; - - UNLOCK_GC; - - done: - if (G_UNLIKELY (alloc_events)) - mono_profiler_allocation (&arr->obj); - - SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Vector has incorrect size."); return arr; } void* mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size) { + MonoError error; MonoArray *arr; - MonoArrayBounds *bounds; - TLAB_ACCESS_INIT; - if (!SGEN_CAN_ALIGN_UP (size)) - return NULL; + MONO_HANDLE_ARENA_PUSH (); -#ifndef DISABLE_CRITICAL_REGION - ENTER_CRITICAL_REGION; - arr = (MonoArray*)sgen_try_alloc_obj_nolock (vtable, size); - if (arr) { - /*This doesn't require fencing since EXIT_CRITICAL_REGION already does it for us*/ - arr->max_length = (mono_array_size_t)max_length; - - bounds = (MonoArrayBounds*)((char*)arr + size - bounds_size); - arr->bounds = bounds; - EXIT_CRITICAL_REGION; - goto done; - } - EXIT_CRITICAL_REGION; -#endif + MONO_HANDLE_TYPE (MonoArray) arr_handle = mono_handle_gc_alloc_array (vtable, size, max_length, bounds_size, &error); - LOCK_GC; + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (arr_handle, arr); - arr = (MonoArray*)sgen_alloc_obj_nolock (vtable, size); - if (G_UNLIKELY (!arr)) { - UNLOCK_GC; - return mono_gc_out_of_memory (size); + if (!mono_error_ok (&error)) { + g_assert (mono_error_get_error_code (&error) == MONO_ERROR_OUT_OF_MEMORY); + return mono_gc_out_of_memory (-1); } - arr->max_length = (mono_array_size_t)max_length; - - bounds = (MonoArrayBounds*)((char*)arr + size - bounds_size); - arr->bounds = bounds; - - UNLOCK_GC; - - done: - if (G_UNLIKELY (alloc_events)) - mono_profiler_allocation (&arr->obj); - - SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Array has incorrect size."); return arr; } void* mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len) { + MonoError error; MonoString *str; - TLAB_ACCESS_INIT; - if (!SGEN_CAN_ALIGN_UP (size)) - return NULL; + MONO_HANDLE_ARENA_PUSH (); -#ifndef DISABLE_CRITICAL_REGION - ENTER_CRITICAL_REGION; - str = (MonoString*)sgen_try_alloc_obj_nolock (vtable, size); - if (str) { - /*This doesn't require fencing since EXIT_CRITICAL_REGION already does it for us*/ - str->length = len; - EXIT_CRITICAL_REGION; - goto done; - } - EXIT_CRITICAL_REGION; -#endif + MONO_HANDLE_TYPE (MonoString) str_handle = mono_handle_gc_alloc_string (vtable, size, len, &error); - LOCK_GC; + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (str_handle, str); - str = (MonoString*)sgen_alloc_obj_nolock (vtable, size); - if (G_UNLIKELY (!str)) { - UNLOCK_GC; - return mono_gc_out_of_memory (size); + if (!mono_error_ok (&error)) { + g_assert (mono_error_get_error_code (&error) == MONO_ERROR_OUT_OF_MEMORY); + return mono_gc_out_of_memory (-1); } - str->length = len; - - UNLOCK_GC; - - done: - if (G_UNLIKELY (alloc_events)) - mono_profiler_allocation (&str->object); - return str; } @@ -2704,12 +2658,6 @@ mono_gc_register_altstack (gpointer stack, gint32 stack_size, gpointer altstack, // FIXME: } -void -sgen_client_out_of_memory (size_t size) -{ - mono_gc_out_of_memory (size); -} - guint8* mono_gc_get_card_table (int *shift_bits, gpointer *mask) { @@ -2999,4 +2947,213 @@ mono_gc_is_null (void) return FALSE; } +/* Handle API specifics */ + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size, MonoError *error) +{ + MONO_HANDLE_TYPE (MonoObject) handle = MONO_HANDLE_NEW (MonoObject, sgen_alloc_obj_pinned (vtable, size, error)); + + if (mono_error_ok (error) && G_UNLIKELY (alloc_events)) { + MONO_PREPARE_GC_CRITICAL_REGION; + mono_profiler_allocation (mono_handle_obj (handle)); + MONO_FINISH_GC_CRITICAL_REGION; + } + + return handle; +} + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_gc_alloc_obj (MonoVTable *vtable, size_t size, MonoError *error) +{ + MONO_HANDLE_TYPE (MonoObject) handle = MONO_HANDLE_NEW (MonoObject, sgen_alloc_obj (vtable, size, error)); + + if (mono_error_ok (error) && G_UNLIKELY (alloc_events)) { + MONO_PREPARE_GC_CRITICAL_REGION; + mono_profiler_allocation (mono_handle_obj (handle)); + MONO_FINISH_GC_CRITICAL_REGION; + } + + return handle; +} + +MONO_HANDLE_TYPE (MonoArray) +mono_handle_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length, MonoError *error) +{ + TLAB_ACCESS_INIT; + + MONO_HANDLE_TYPE (MonoArray) arr; + + mono_error_init (error); + + if (!SGEN_CAN_ALIGN_UP (size)) + return MONO_HANDLE_NEW (MonoArray, NULL); + + { + MonoObject *obj; + +#ifndef DISABLE_CRITICAL_REGION + ENTER_CRITICAL_REGION; + obj = sgen_try_alloc_obj_nolock (vtable, size); + if (obj) { + arr = MONO_HANDLE_NEW (MonoArray, obj); + + MONO_HANDLE_SET (arr, max_length, (mono_array_size_t) max_length); + + EXIT_CRITICAL_REGION; + goto done; + } + EXIT_CRITICAL_REGION; +#endif + + LOCK_GC; + + obj = sgen_alloc_obj_nolock (vtable, size); + if (G_UNLIKELY (!obj)) { + UNLOCK_GC; + mono_error_set_out_of_memory (error, "Could not allocate vector of size " G_GSIZE_FORMAT " bytes", size); + return MONO_HANDLE_NEW (MonoArray, NULL); + } + + arr = MONO_HANDLE_NEW (MonoArray, obj); + + MONO_HANDLE_SET (arr, max_length, (mono_array_size_t)max_length); + + UNLOCK_GC; + } + +done: + if (G_UNLIKELY (alloc_events)) { + MONO_PREPARE_GC_CRITICAL_REGION; + mono_profiler_allocation ((MonoObject*) mono_handle_obj (arr)); + MONO_FINISH_GC_CRITICAL_REGION; + } + + MONO_PREPARE_GC_CRITICAL_REGION; + SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*) mono_handle_obj (arr))), "Vector has incorrect size."); + MONO_FINISH_GC_CRITICAL_REGION; + + return arr; +} + +MONO_HANDLE_TYPE (MonoArray) +mono_handle_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size, MonoError *error) +{ + TLAB_ACCESS_INIT; + + MONO_HANDLE_TYPE (MonoArray) arr; + + mono_error_init (error); + + if (!SGEN_CAN_ALIGN_UP (size)) + return MONO_HANDLE_NEW (MonoArray, NULL); + + { + MonoObject *obj; + +#ifndef DISABLE_CRITICAL_REGION + ENTER_CRITICAL_REGION; + obj = sgen_try_alloc_obj_nolock (vtable, size); + if (obj) { + arr = MONO_HANDLE_NEW (MonoArray, obj); + + MONO_PREPARE_GC_CRITICAL_REGION; + MONO_HANDLE_SET (arr, max_length, (mono_array_size_t)max_length); + MONO_HANDLE_SET (arr, bounds, (MonoArrayBounds*) ((char*) mono_handle_obj (arr) + size - bounds_size)); + MONO_FINISH_GC_CRITICAL_REGION; + + EXIT_CRITICAL_REGION; + goto done; + } + EXIT_CRITICAL_REGION; +#endif + + LOCK_GC; + + obj = sgen_alloc_obj_nolock (vtable, size); + if (G_UNLIKELY (!obj)) { + UNLOCK_GC; + mono_error_set_out_of_memory (error, "Could not allocate array of size " G_GSIZE_FORMAT " bytes", size); + return MONO_HANDLE_NEW (MonoArray, NULL); + } + + arr = MONO_HANDLE_NEW (MonoArray, obj); + + MONO_PREPARE_GC_CRITICAL_REGION; + MONO_HANDLE_SET (arr, max_length, (mono_array_size_t)max_length); + MONO_HANDLE_SET (arr, bounds, (MonoArrayBounds*) ((char*) mono_handle_obj (arr) + size - bounds_size)); + MONO_FINISH_GC_CRITICAL_REGION; + + UNLOCK_GC; + } + + done: + if (G_UNLIKELY (alloc_events)) { + MONO_PREPARE_GC_CRITICAL_REGION; + mono_profiler_allocation ((MonoObject*) mono_handle_obj (arr)); + MONO_FINISH_GC_CRITICAL_REGION; + } + + MONO_PREPARE_GC_CRITICAL_REGION; + SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*) mono_handle_obj (arr))), "Array has incorrect size."); + MONO_FINISH_GC_CRITICAL_REGION; + + return arr; +} + +MONO_HANDLE_TYPE (MonoString) +mono_handle_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len, MonoError *error) +{ + TLAB_ACCESS_INIT; + + MONO_HANDLE_TYPE (MonoString) str; + + mono_error_init (error); + + if (!SGEN_CAN_ALIGN_UP (size)) + return MONO_HANDLE_NEW (MonoString, NULL); + + { + MonoObject *obj; + +#ifndef DISABLE_CRITICAL_REGION + ENTER_CRITICAL_REGION; + obj = sgen_try_alloc_obj_nolock (vtable, size); + if (obj) { + str = MONO_HANDLE_NEW (MonoString, obj); + + MONO_HANDLE_SET (str, length, len); + + EXIT_CRITICAL_REGION; + goto done; + } + EXIT_CRITICAL_REGION; +#endif + + LOCK_GC; + + obj = sgen_alloc_obj_nolock (vtable, size); + if (G_UNLIKELY (!obj)) { + UNLOCK_GC; + mono_error_set_out_of_memory (error, "Could not allocate string of size " G_GSIZE_FORMAT " bytes", size); + return MONO_HANDLE_NEW (MonoString, NULL); + } + + str = MONO_HANDLE_NEW (MonoString, obj); + + MONO_HANDLE_SET (str, length, len); + + UNLOCK_GC; + } + + done: + if (G_UNLIKELY (alloc_events)) { + MONO_PREPARE_GC_CRITICAL_REGION; + mono_profiler_allocation ((MonoObject*) mono_handle_obj (str)); + MONO_FINISH_GC_CRITICAL_REGION; + } + + return str; +} + #endif diff --git a/mono/sgen/sgen-alloc.c b/mono/sgen/sgen-alloc.c index ca9d645e6aa7..2a9a3d014105 100644 --- a/mono/sgen/sgen-alloc.c +++ b/mono/sgen/sgen-alloc.c @@ -46,6 +46,8 @@ #include "mono/sgen/sgen-memory-governor.h" #include "mono/sgen/sgen-client.h" #include "mono/utils/mono-memory-model.h" +#include "mono/utils/mono-error.h" +#include "mono/utils/mono-error-internals.h" #define ALIGN_UP SGEN_ALIGN_UP #define ALLOC_ALIGN SGEN_ALLOC_ALIGN @@ -418,11 +420,13 @@ sgen_try_alloc_obj_nolock (GCVTable vtable, size_t size) } GCObject* -sgen_alloc_obj (GCVTable vtable, size_t size) +sgen_alloc_obj (GCVTable vtable, size_t size, MonoError *error) { GCObject *res; TLAB_ACCESS_INIT; + mono_error_init (error); + if (!SGEN_CAN_ALIGN_UP (size)) return NULL; @@ -457,7 +461,7 @@ sgen_alloc_obj (GCVTable vtable, size_t size) res = sgen_alloc_obj_nolock (vtable, size); UNLOCK_GC; if (G_UNLIKELY (!res)) - sgen_client_out_of_memory (size); + mono_error_set_out_of_memory (error, "Could not allocate " G_GSIZE_FORMAT " bytes", size); return res; } @@ -466,10 +470,12 @@ sgen_alloc_obj (GCVTable vtable, size_t size) * We may want to explicitly free these objects. */ GCObject* -sgen_alloc_obj_pinned (GCVTable vtable, size_t size) +sgen_alloc_obj_pinned (GCVTable vtable, size_t size, MonoError *error) { GCObject *p; + mono_error_init (error); + if (!SGEN_CAN_ALIGN_UP (size)) return NULL; size = ALIGN_UP (size); @@ -492,10 +498,12 @@ sgen_alloc_obj_pinned (GCVTable vtable, size_t size) } GCObject* -sgen_alloc_obj_mature (GCVTable vtable, size_t size) +sgen_alloc_obj_mature (GCVTable vtable, size_t size, MonoError *error) { GCObject *res; + mono_error_init (error); + if (!SGEN_CAN_ALIGN_UP (size)) return NULL; size = ALIGN_UP (size); diff --git a/mono/sgen/sgen-client.h b/mono/sgen/sgen-client.h index 5c803b50ae59..edf9dde8439e 100644 --- a/mono/sgen/sgen-client.h +++ b/mono/sgen/sgen-client.h @@ -140,14 +140,6 @@ void sgen_client_degraded_allocation (size_t size); */ void sgen_client_total_allocated_heap_changed (size_t allocated_heap_size); -/* - * Called when an object allocation fails. The suggested action is to abort the program. - * - * FIXME: Don't we want to return a BOOL here that indicates whether to retry the - * allocation? - */ -void sgen_client_out_of_memory (size_t size); - /* * If the client has registered any internal memory types, this must return a string * describing the given type. Only used for debugging. diff --git a/mono/sgen/sgen-gc.h b/mono/sgen/sgen-gc.h index 9e022e12ba90..b86b65c24acc 100644 --- a/mono/sgen/sgen-gc.h +++ b/mono/sgen/sgen-gc.h @@ -978,9 +978,9 @@ typedef enum { void sgen_init_tlab_info (SgenThreadInfo* info); void sgen_clear_tlabs (void); -GCObject* sgen_alloc_obj (GCVTable vtable, size_t size); -GCObject* sgen_alloc_obj_pinned (GCVTable vtable, size_t size); -GCObject* sgen_alloc_obj_mature (GCVTable vtable, size_t size); +GCObject* sgen_alloc_obj (GCVTable vtable, size_t size, MonoError *error); +GCObject* sgen_alloc_obj_pinned (GCVTable vtable, size_t size, MonoError *error); +GCObject* sgen_alloc_obj_mature (GCVTable vtable, size_t size, MonoError *error); /* Debug support */ From 5ad6caa40eea3ce7b3942ea881786a4c307d5535 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 14:23:08 +0000 Subject: [PATCH 08/20] [handle] Add String and Array alloc function --- mono/metadata/handle.h | 42 +++- mono/metadata/object.c | 462 ++++++++++++++++++++++++++++++++++------- 2 files changed, 429 insertions(+), 75 deletions(-) diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 7fe364e1494e..d282b68df154 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -15,6 +15,7 @@ #include #include +#include /* * DO NOT ACCESS DIRECTLY @@ -118,14 +119,51 @@ mono_handle_domain (MonoHandle handle) MONO_FINISH_GC_CRITICAL_REGION; \ } while (0) +/* Some common handle types */ +MONO_HANDLE_TYPE_DECL (MonoArray); +MONO_HANDLE_TYPE (MonoArray) +mono_handle_array_new (MonoDomain *domain, MonoClass *element_class, uintptr_t size, MonoError *error); -/* Some common handle types */ +MONO_HANDLE_TYPE (MonoArray) +mono_handle_array_new_specific (MonoVTable *vtable, uintptr_t size, MonoError *error); + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_array_value_box (MonoDomain *domain, MonoClass *element_class, MONO_HANDLE_TYPE (MonoArray) arr_handle, gint32 pos, MonoError *error); + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_array_nullable_box (MonoDomain *domain, MonoClass *element_class, MONO_HANDLE_TYPE (MonoArray) arr_handle, gint32 pos, MonoError *error); + +static inline guint8* +mono_handle_array_addr_with_size (MONO_HANDLE_TYPE (MonoArray) arr_handle, gsize element_size, gint32 pos) +{ + return (guint8*) mono_array_addr_with_size (mono_handle_obj (arr_handle), element_size, pos); +} + +void +mono_handle_array_nullable_init (MonoDomain *domain, MonoClass *element_class, MONO_HANDLE_TYPE (MonoArray) arr_handle, gint32 pos, MONO_HANDLE_TYPE (MonoObject) value_handle, MonoError *error); -MONO_HANDLE_TYPE_DECL (MonoArray); MONO_HANDLE_TYPE_DECL (MonoString); +MONO_HANDLE_TYPE (MonoString) +mono_handle_string_new (MonoDomain *domain, const gchar *text, MonoError *error); + +MONO_HANDLE_TYPE (MonoString) +mono_handle_string_new_size (MonoDomain *domain, gint32 len, MonoError *error); + +MONO_HANDLE_TYPE (MonoString) +mono_handle_string_new_utf16 (MonoDomain *domain, const guint16 *text, glong len, MonoError *error); + +gunichar2* +mono_handle_string_chars (MONO_HANDLE_TYPE (MonoString) handle); + +gint32 +mono_handle_string_length (MONO_HANDLE_TYPE (MonoString) handle); + +gchar* +mono_handle_string_to_utf8 (MONO_HANDLE_TYPE (MonoString) handle, MonoError *error); + G_END_DECLS #endif /* __MONO_HANDLE_H__ */ diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 5a5c31b3e6cb..ce5fba846033 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -4920,14 +4920,27 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng MonoArray * mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n) { - MONO_REQ_GC_UNSAFE_MODE; + MonoError error; + MonoArray *arr; + + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoArray) arr_handle = mono_handle_array_new (domain, eclass, n, &error); - MonoClass *ac; + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (arr_handle, arr); - ac = mono_array_class_get (eclass, 1); - g_assert (ac); + if (G_UNLIKELY (!mono_error_ok (&error))) { + switch (mono_error_get_error_code (&error)) { + case MONO_ERROR_OUT_OF_MEMORY: + mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + break; + default: + mono_error_raise_exception (&error); + break; + } + } - return mono_array_new_specific (mono_class_vtable_full (domain, ac, TRUE), n); + return arr; } /** @@ -4941,25 +4954,28 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n) MonoArray * mono_array_new_specific (MonoVTable *vtable, uintptr_t n) { - MONO_REQ_GC_UNSAFE_MODE; + MonoError error; + MonoArray *arr; - MonoObject *o; - MonoArray *ao; - uintptr_t byte_len; + MONO_HANDLE_ARENA_PUSH (); - if (G_UNLIKELY (n > MONO_ARRAY_MAX_INDEX)) { - arith_overflow (); - return NULL; - } + MONO_HANDLE_TYPE (MonoArray) arr_handle = mono_handle_array_new_specific (vtable, n, &error); - if (!mono_array_calc_byte_len (vtable->klass, n, &byte_len)) { - mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); - return NULL; + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (arr_handle, arr); + + if (G_UNLIKELY (!mono_error_ok (&error))) { + switch (mono_error_get_error_code (&error)) { + case MONO_ERROR_OUT_OF_MEMORY: + mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + break; + default: + mono_error_raise_exception (&error); + break; + } + g_assert_not_reached (); } - o = (MonoObject *)mono_gc_alloc_vector (vtable, byte_len, n); - ao = (MonoArray*)o; - return ao; + return arr; } /** @@ -4972,16 +4988,28 @@ mono_array_new_specific (MonoVTable *vtable, uintptr_t n) MonoString * mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len) { - MONO_REQ_GC_UNSAFE_MODE; + MonoError error; + MonoString *str; - MonoString *s; - - s = mono_string_new_size (domain, len); - g_assert (s != NULL); + MONO_HANDLE_ARENA_PUSH (); - memcpy (mono_string_chars (s), text, len * 2); + MONO_HANDLE_TYPE (MonoString) str_handle = mono_handle_string_new_utf16 (domain, text, len, &error); - return s; + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (str_handle, str); + + if (G_UNLIKELY (!mono_error_ok (&error))) { + switch (mono_error_get_error_code (&error)) { + case MONO_ERROR_OUT_OF_MEMORY: + mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + break; + default: + mono_error_raise_exception (&error); + break; + } + g_assert_not_reached (); + } + + return str; } /** @@ -5029,25 +5057,28 @@ mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len MonoString * mono_string_new_size (MonoDomain *domain, gint32 len) { - MONO_REQ_GC_UNSAFE_MODE; - - MonoString *s; - MonoVTable *vtable; - size_t size; + MonoError error; + MonoString *str; - /* check for overflow */ - if (len < 0 || len > ((SIZE_MAX - G_STRUCT_OFFSET (MonoString, chars) - 8) / 2)) - mono_gc_out_of_memory (-1); + MONO_HANDLE_ARENA_PUSH (); - size = (G_STRUCT_OFFSET (MonoString, chars) + (((size_t)len + 1) * 2)); - g_assert (size > 0); + MONO_HANDLE_TYPE (MonoString) str_handle = mono_handle_string_new_size (domain, len, &error); - vtable = mono_class_vtable (domain, mono_defaults.string_class); - g_assert (vtable); + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (str_handle, str); - s = (MonoString *)mono_gc_alloc_string (vtable, size, len); + if (G_UNLIKELY (!mono_error_ok (&error))) { + switch (mono_error_get_error_code (&error)) { + case MONO_ERROR_OUT_OF_MEMORY: + mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + break; + default: + mono_error_raise_exception (&error); + break; + } + g_assert_not_reached (); + } - return s; + return str; } /** @@ -5088,44 +5119,27 @@ mono_string_new_len (MonoDomain *domain, const char *text, guint length) MonoString* mono_string_new (MonoDomain *domain, const char *text) { - MONO_REQ_GC_UNSAFE_MODE; - - GError *error = NULL; - MonoString *o = NULL; - guint16 *ut; - glong items_written; - int l; - - l = strlen (text); - - ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error); + MonoError error; + MonoString *str; - if (!error) - o = mono_string_new_utf16 (domain, ut, items_written); - else - g_error_free (error); + MONO_HANDLE_ARENA_PUSH (); - g_free (ut); -/*FIXME g_utf8_get_char, g_utf8_next_char and g_utf8_validate are not part of eglib.*/ -#if 0 - gunichar2 *str; - const gchar *end; - int len; - MonoString *o = NULL; + MONO_HANDLE_TYPE (MonoString) str_handle = mono_handle_string_new (domain, text, &error); - if (!g_utf8_validate (text, -1, &end)) - return NULL; - - len = g_utf8_strlen (text, -1); - o = mono_string_new_size (domain, len); - str = mono_string_chars (o); + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (str_handle, str); - while (text < end) { - *str++ = g_utf8_get_char (text); - text = g_utf8_next_char (text); + if (G_UNLIKELY (!mono_error_ok (&error))) { + switch (mono_error_get_error_code (&error)) { + case MONO_ERROR_OUT_OF_MEMORY: + mono_raise_exception (mono_domain_get ()->out_of_memory_ex); + break; + default: + mono_error_raise_exception (&error); + break; + } } -#endif - return o; + + return str; } /** @@ -6931,3 +6945,305 @@ mono_glist_to_array (GList *list, MonoClass *eclass) return res; } +/* Handle API specifics */ + +/** + * mono_string_new: + * @text: a pointer to an utf8 string + * + * Returns: A newly created string object which contains @text. + */ +MONO_HANDLE_TYPE (MonoString) +mono_handle_string_new (MonoDomain *domain, const gchar *text, MonoError *error) +{ + GError *gerror = NULL; + MONO_HANDLE_TYPE (MonoString) handle; + guint16 *u16; + glong u16_written; + + mono_error_init (error); + + u16 = g_utf8_to_utf16 (text, strlen (text), NULL, &u16_written, &gerror); + + if (!gerror) { + handle = mono_handle_string_new_utf16 (domain, u16, u16_written, error); + } else { + handle = MONO_HANDLE_NEW (MonoString, NULL); + g_error_free (gerror); + } + + g_free (u16); + + return handle; +} + +/** + * mono_string_new_size: + * @text: a pointer to an utf16 string + * @len: the length of the string + * + * Returns: A newly created string object of @len + */ +MONO_HANDLE_TYPE (MonoString) +mono_handle_string_new_size (MonoDomain *domain, gint32 len, MonoError *error) +{ + MonoVTable *vtable; + size_t size; + + mono_error_init (error); + + /* check for overflow */ + if (len < 0 || len > ((SIZE_MAX - G_STRUCT_OFFSET (MonoString, chars) - 8) / 2)) { + mono_error_set_out_of_memory (error, "Could not allocate string of length %d", len); + return MONO_HANDLE_NEW (MonoString, NULL); + } + + size = (G_STRUCT_OFFSET (MonoString, chars) + (((size_t)len + 1) * 2)); + g_assert (size > 0); + + vtable = mono_class_vtable (domain, mono_defaults.string_class); + g_assert (vtable); + + return mono_handle_gc_alloc_string (vtable, size, len, error); +} + +/** + * mono_string_new_utf16: + * @text: a pointer to an utf16 string + * @len: the length of the string + * + * Returns: A newly created string object which contains @text. + */ +MONO_HANDLE_TYPE (MonoString) +mono_handle_string_new_utf16 (MonoDomain *domain, const guint16 *text, glong len, MonoError *error) +{ + MONO_HANDLE_TYPE (MonoString) handle; + + handle = mono_handle_string_new_size (domain, len, error); + g_assert (!mono_handle_obj_is_null (handle)); + + MONO_PREPARE_GC_CRITICAL_REGION; + memcpy (mono_handle_string_chars (handle), text, len * 2); + MONO_FINISH_GC_CRITICAL_REGION; + + return handle; +} + +/** + * mono_string_chars: + * @handle: a MonoString handle + * + * Returns a pointer to the UCS16 characters stored in the MonoString + */ +gunichar2* +mono_handle_string_chars (MONO_HANDLE_TYPE (MonoString) handle) +{ + return mono_handle_obj (handle)->chars; +} + +/** + * mono_string_length: + * @s: MonoString + * + * Returns the lenght in characters of the string + */ +gint32 +mono_handle_string_length (MONO_HANDLE_TYPE (MonoString) handle) +{ + return mono_handle_obj (handle)->length; +} + +/** + * mono_string_to_utf8_checked: + * @handle: a System.String handle + * @error: a MonoError. + * + * Converts a MonoString to its UTF8 representation. May fail; check + * @error to determine whether the conversion was successful. + * The resulting buffer should be freed with mono_free(). + */ +gchar* +mono_handle_string_to_utf8 (MONO_HANDLE_TYPE (MonoString) handle, MonoError *error) +{ + gchar *u8_chars; + glong u8_length = 0; + gunichar2 *str_chars; + gint32 str_length; + + mono_error_init (error); + + if (mono_handle_obj_is_null (handle)) + return NULL; + + MONO_PREPARE_GC_CRITICAL_REGION; + + str_chars = mono_handle_string_chars (handle); + str_length = mono_handle_string_length (handle); + + if (str_length == 0) { + u8_chars = g_strdup (""); + } else { + GError *gerror; + + u8_length = 0; + gerror = NULL; + u8_chars = g_utf16_to_utf8 (str_chars, str_length, NULL, &u8_length, &gerror); + if (gerror) { + mono_error_set_argument (error, "string", "%s", gerror->message); + g_error_free (gerror); + u8_chars = NULL; + } else { + /* g_utf16_to_utf8 may not be able to complete the convertion (e.g. NULL values were found, #335488) */ + if (u8_length < str_length) { + /* allocate the total length and copy the part of the string that has been converted */ + gchar *u8_2 = (gchar*) g_malloc0 (str_length); + memcpy (u8_2, u8_chars, u8_length); + g_free (u8_chars); + u8_chars = u8_2; + } + } + } + + MONO_FINISH_GC_CRITICAL_REGION; + + return u8_chars; +} + +/** + * mono_array_new: + * @domain: domain where the object is created + * @element_class: element class + * @size: number of array elements + * @error: a MonoError + * + * This routine creates a new szarray with @n elements of type @eclass. + */ +MONO_HANDLE_TYPE (MonoArray) +mono_handle_array_new (MonoDomain *domain, MonoClass *element_class, uintptr_t size, MonoError *error) +{ + MonoClass *array_class; + + array_class = mono_array_class_get (element_class, 1); + g_assert (array_class); + + return mono_handle_array_new_specific (mono_class_vtable_full (domain, array_class, TRUE), size, error); +} + +/** + * mono_array_new_specific: + * @vtable: a vtable in the appropriate domain for an initialized class + * @size: number of array elements + * @error: a MonoError + * + * This routine is a fast alternative to mono_array_new() for code which + * can be sure about the domain it operates in. + */ +MONO_HANDLE_TYPE (MonoArray) +mono_handle_array_new_specific (MonoVTable *vtable, uintptr_t size, MonoError *error) +{ + uintptr_t byte_size; + + mono_error_init (error); + + if (G_UNLIKELY (size > MONO_ARRAY_MAX_INDEX)) { + mono_error_set_generic_error (error, "System", "OverflowException", ""); + return MONO_HANDLE_NEW (MonoArray, NULL); + } + + if (!mono_array_calc_byte_len (vtable->klass, size, &byte_size)) { + mono_error_set_out_of_memory (error, "Could not allocate array of size " G_GSIZE_FORMAT, size); + return MONO_HANDLE_NEW (MonoArray, NULL); + } + + return mono_handle_gc_alloc_vector (vtable, byte_size, size, error); +} + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_array_value_box (MonoDomain *domain, MonoClass *element_class, MONO_HANDLE_TYPE (MonoArray) arr_handle, gint32 pos, MonoError *error) +{ + MONO_HANDLE_TYPE (MonoObject) ret; + MonoVTable *vtable; + gsize element_size; + + g_assert (element_class->valuetype); + if (mono_class_is_nullable (element_class)) + return mono_handle_array_nullable_box (domain, element_class, arr_handle, pos, error); + + mono_error_init (error); + + vtable = mono_class_vtable (domain, element_class); + if (!vtable) + return MONO_HANDLE_NEW (MonoObject, NULL); + + ret = mono_handle_object_new_alloc_specific (vtable, error); + + if (!mono_error_ok (error)) + return ret; + + element_size = mono_class_instance_size (element_class) - sizeof (MonoObject); + + MONO_PREPARE_GC_CRITICAL_REGION; + + guint8 *src = (guint8*) mono_handle_array_addr_with_size (arr_handle, element_size, pos); + guint8 *dst = (guint8*) mono_handle_obj (ret) + sizeof (MonoObject); + + mono_gc_wbarrier_value_copy (dst, src, 1, element_class); + + MONO_FINISH_GC_CRITICAL_REGION; + + return ret; +} + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_array_nullable_box (MonoDomain *domain, MonoClass *element_class, MONO_HANDLE_TYPE (MonoArray) arr_handle, gint32 pos, MonoError *error) +{ + MonoClass *param_class; + MonoBoolean has_value; + gsize element_size; + + mono_error_init (error); + + param_class = element_class->cast_class; + + mono_class_setup_fields_locking (element_class); + g_assert (element_class->fields_inited); + + g_assert (mono_class_from_mono_type (element_class->fields [0].type) == param_class); + g_assert (mono_class_from_mono_type (element_class->fields [1].type) == mono_defaults.boolean_class); + + element_size = mono_class_instance_size (element_class) - sizeof (MonoObject); + + MONO_PREPARE_GC_CRITICAL_REGION; + has_value = *(mono_handle_array_addr_with_size (arr_handle, element_size, pos) + element_class->fields [1].offset - sizeof (MonoObject)); + MONO_FINISH_GC_CRITICAL_REGION; + + if (!has_value) { + return MONO_HANDLE_NEW (MonoObject, NULL); + } else { + MONO_HANDLE_TYPE (MonoObject) ret; + + ret = mono_handle_object_new (domain, param_class, error); + if (!mono_error_ok (error)) + return ret; + + /* mono_gc_wbarrier_value_copy -> mono_class_value_size -> mono_class_instance_size -> mono_class_init can enter a safepoint */ + mono_class_init (param_class); + + MONO_PREPARE_GC_CRITICAL_REGION; + + guint8 *src = (guint8*) mono_handle_array_addr_with_size (arr_handle, element_size, pos) + element_class->fields [0].offset - sizeof (MonoObject); + guint8 *dst = (guint8*) mono_handle_obj (ret) + sizeof (MonoObject); + + mono_gc_wbarrier_value_copy (dst, src, 1, param_class); + + MONO_FINISH_GC_CRITICAL_REGION; + + return ret; + } +} + +void +mono_handle_array_nullable_init (MonoDomain *domain, MonoClass *element_class, MONO_HANDLE_TYPE (MonoArray) arr_handle, gint32 pos, MONO_HANDLE_TYPE (MonoObject) value_handle, MonoError *error) +{ + g_error ("not implemented"); +} From 5c80c8070fd0c857a1dc0c050f04d4c0865f7979 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 8 Jan 2016 12:03:37 +0000 Subject: [PATCH 09/20] [handle] Add Object alloc function --- mono/metadata/handle.h | 17 +++++++ mono/metadata/object.c | 102 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index d282b68df154..31122c646b4c 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -121,6 +121,23 @@ mono_handle_domain (MonoHandle handle) /* Some common handle types */ +MONO_HANDLE_TYPE_DECL (MonoObject); + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new (MonoDomain *domain, MonoClass *klass, MonoError *error); + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new_specific (MonoVTable *vtable, MonoError *error); + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new_alloc_specific (MonoVTable *vtable, MonoError *error); + +gboolean +mono_handle_object_isinst (MONO_HANDLE_TYPE (MonoObject) handle, MonoClass *klass); + +void +mono_handle_runtime_object_init (MONO_HANDLE_TYPE (MonoObject) this_handle); + MONO_HANDLE_TYPE_DECL (MonoArray); MONO_HANDLE_TYPE (MonoArray) diff --git a/mono/metadata/object.c b/mono/metadata/object.c index ce5fba846033..3d62f083e558 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -80,6 +80,36 @@ mono_runtime_object_init (MonoObject *this_obj) mono_runtime_invoke (method, this_obj, NULL, NULL); } +void +mono_handle_runtime_object_init (MONO_HANDLE_TYPE (MonoObject) handle) +{ + MonoClass *klass; + MonoMethod *method; + gpointer obj; + guint32 gchandle; + + klass = mono_handle_class ((MonoHandle) handle); + method = mono_class_get_method_from_name (klass, ".ctor", 0); + if (!method) + g_error ("Could not lookup zero argument constructor for class %s", mono_type_get_full_name (klass)); + + MONO_PREPARE_GC_CRITICAL_REGION; + + /* FIXME: still not safe as there can be a call to alloc_handle -> + * handle_data_grow -> sgen_register_root which will lock the GC */ + gchandle = mono_gchandle_new (mono_handle_obj (handle), TRUE); + + obj = method->klass->valuetype ? + mono_object_unbox (mono_handle_obj (handle)) : + mono_handle_obj (handle); + + MONO_FINISH_GC_CRITICAL_REGION; + + mono_runtime_invoke (method, obj, NULL, NULL); + + mono_gchandle_free (gchandle); +} + /* The pseudo algorithm for type initialization from the spec Note it doesn't say anything about domains - only threads. @@ -6947,6 +6977,78 @@ mono_glist_to_array (GList *list, MonoClass *eclass) /* Handle API specifics */ +/** + * mono_handle_object_new: + * @domain: the domain of the object we want to create + * @klass: the class of the object that we want to create + * + * Returns: a newly created object whose definition is + * looked up using @klass. This will not invoke any constructors, + * so the consumer of this routine has to invoke any constructors on + * its own to initialize the object. + * + * It returns NULL on failure. + */ +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new (MonoDomain *domain, MonoClass *klass, MonoError *error) +{ + MonoVTable *vtable; + + mono_error_init (error); + + vtable = mono_class_vtable (domain, klass); + if (!vtable) + return MONO_HANDLE_NEW (MonoObject, NULL); + + return mono_handle_object_new_specific (vtable, error); +} + +/** + * mono_handle_object_new_specific: + * @vtable: the vtable of the object that we want to create + * + * Returns: A newly created object with class and domain specified + * by @vtable + */ +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new_specific (MonoVTable *vtable, MonoError *error) +{ + mono_error_init (error); + + if (mono_vtable_is_remote (vtable) || mono_class_is_com_object (vtable->klass)) + g_error ("not implemented"); + + return mono_handle_object_new_alloc_specific (vtable, error); +} + +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new_alloc_specific (MonoVTable *vtable, MonoError *error) +{ + MONO_HANDLE_TYPE (MonoObject) handle = mono_handle_gc_alloc_obj (vtable, vtable->klass->instance_size, error); + + if (mono_error_ok (error) && G_UNLIKELY (vtable->klass->has_finalize)) + g_error ("not implemented"); + + return handle; +} + +gboolean +mono_handle_object_isinst (MONO_HANDLE_TYPE (MonoObject) handle, MonoClass *klass) +{ + gboolean ret; + + if (!klass->inited) + mono_class_init (klass); + + MONO_PREPARE_GC_CRITICAL_REGION; + + ret = mono_object_isinst (mono_handle_obj (handle), klass) != NULL; + + MONO_FINISH_GC_CRITICAL_REGION; + + return ret; +} + /** * mono_string_new: * @text: a pointer to an utf8 string From 5115814c6783d87106707be76ed06d355f0ae693 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 14:24:35 +0000 Subject: [PATCH 10/20] [handle] Add mono_handle_obj_is_null utility function --- mono/metadata/handle.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 31122c646b4c..cc8961567afe 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -78,6 +78,8 @@ mono_handle_domain (MonoHandle handle) return mono_object_get_domain (handle->obj); } +#define mono_handle_obj_is_null(handle) ((handle)->obj == NULL) + #define MONO_HANDLE_TYPE_DECL(type) typedef struct { type *obj; } type ## HandleStorage ; \ typedef type ## HandleStorage * type ## Handle #define MONO_HANDLE_TYPE(type) type ## Handle From fefb2c6d49559c776b33ab98af6eb5ac5d9a8391 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 15:35:55 +0000 Subject: [PATCH 11/20] [handle] Rename MonoHandleStorage->obj to MonoHandleStorage->__private_obj --- mono/metadata/handle-arena.h | 2 +- mono/metadata/handle.c | 10 +++++----- mono/metadata/handle.h | 20 ++++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mono/metadata/handle-arena.h b/mono/metadata/handle-arena.h index 529256b12ed8..99337f7c91dd 100644 --- a/mono/metadata/handle-arena.h +++ b/mono/metadata/handle-arena.h @@ -43,7 +43,7 @@ mono_handle_arena_current_addr (void); } while (0) #define MONO_HANDLE_ARENA_POP_RETURN_UNSAFE(handle,ret) \ - (ret) = (handle)->obj; \ + (ret) = (handle)->__private_obj; \ mono_handle_arena_stack_pop (__arena_stack, __arena); \ } while (0) diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index 69b48eebf284..f2a2be690f17 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -80,7 +80,7 @@ handle_new (MonoHandleArena *arena, MonoObject *obj) chunk = arena->chunk_last; if (chunk->handles_size < HANDLES_PER_CHUNK) { - chunk->handles [chunk->handles_size].obj = obj; + chunk->handles [chunk->handles_size].__private_obj = obj; chunk->handles_size += 1; return &chunk->handles [chunk->handles_size - 1]; @@ -88,7 +88,7 @@ handle_new (MonoHandleArena *arena, MonoObject *obj) chunk = chunk->next = chunk_alloc (); - chunk->handles [0].obj = obj; + chunk->handles [0].__private_obj = obj; chunk->handles_size = 1; arena->chunk_last = chunk; @@ -113,7 +113,7 @@ mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle) g_assert (arena); g_assert (arena->prev); - return handle_new (arena->prev, handle->obj); + return handle_new (arena->prev, handle->__private_obj); } gsize @@ -168,8 +168,8 @@ arena_scan (gpointer addr, MonoGCMarkFunc mark_func, gpointer gc_data) 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].obj != NULL) - mark_func (&chunk->handles [i].obj, gc_data); + if (chunk->handles [i].__private_obj != NULL) + mark_func (&chunk->handles [i].__private_obj, gc_data); } } } diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index cc8961567afe..66d9f736d19c 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -25,7 +25,7 @@ * in C, but using a C++ template would simplify that a lot */ typedef struct { - MonoObject *obj; + MonoObject *__private_obj; } MonoHandleStorage; typedef MonoHandleStorage* MonoHandle; @@ -48,9 +48,9 @@ mono_handle_elevate (MonoHandle handle) #ifndef CHECKED_BUILD -#define mono_handle_obj(handle) ((handle)->obj) +#define mono_handle_obj(handle) ((handle)->__private_obj) -#define mono_handle_assign(handle,rawptr) do { (handle)->obj = (rawptr); } while(0) +#define mono_handle_assign(handle,rawptr) do { (handle)->__private_obj = (rawptr); } while(0) #else @@ -60,31 +60,31 @@ mono_handle_check_in_critical_section () MONO_REQ_GC_UNSAFE_MODE; } -#define mono_handle_obj(handle) (mono_handle_check_in_critical_section (), (handle)->obj) +#define mono_handle_obj(handle) (mono_handle_check_in_critical_section (), (handle)->__private_obj) -#define mono_handle_assign(handle,rawptr) do { mono_handle_check_in_critical_section (); (handle)->obj = (rawptr); } while (0) +#define mono_handle_assign(handle,rawptr) do { mono_handle_check_in_critical_section (); (handle)->__private_obj = (rawptr); } while (0) #endif static inline MonoClass* mono_handle_class (MonoHandle handle) { - return mono_object_get_class (handle->obj); + return mono_object_get_class (handle->__private_obj); } static inline MonoDomain* mono_handle_domain (MonoHandle handle) { - return mono_object_get_domain (handle->obj); + return mono_object_get_domain (handle->__private_obj); } -#define mono_handle_obj_is_null(handle) ((handle)->obj == NULL) +#define mono_handle_obj_is_null(handle) ((handle)->__private_obj == NULL) -#define MONO_HANDLE_TYPE_DECL(type) typedef struct { type *obj; } type ## HandleStorage ; \ +#define MONO_HANDLE_TYPE_DECL(type) typedef struct { type *__private_obj; } type ## HandleStorage ; \ typedef type ## HandleStorage * type ## Handle #define MONO_HANDLE_TYPE(type) type ## Handle #define MONO_HANDLE_NEW(type,obj) ((type ## Handle) mono_handle_new ((MonoObject*) (obj))) -#define MONO_HANDLE_ELEVATE(type,handle) ((type ## Handle) mono_handle_elevate ((MonoObject*) (handle)->obj)) +#define MONO_HANDLE_ELEVATE(type,handle) ((type ## Handle) mono_handle_elevate ((MonoObject*) (handle)->__private_obj)) #define MONO_HANDLE_ASSIGN(handle,rawptr) \ do { \ From f9b01872f29770e357c0bc7b6b07d038f8666b6f Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Thu, 7 Jan 2016 18:21:15 -0500 Subject: [PATCH 12/20] [handle] Add _SETREF_NULL macros for MonoObjectHandle and MonoArrayHandle --- mono/metadata/handle.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 66d9f736d19c..5f4ed88aa9c9 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -99,6 +99,14 @@ mono_handle_domain (MonoHandle handle) MONO_FINISH_GC_CRITICAL_REGION; \ } while (0) +#define MONO_HANDLE_SETREF_NULL(handle,fieldname) \ + do { \ + MONO_PREPARE_GC_CRITICAL_REGION; \ + MONO_OBJECT_SETREF (mono_handle_obj ((handle)), fieldname, NULL); \ + MONO_FINISH_GC_CRITICAL_REGION; \ + } while (0) + + #define MONO_HANDLE_SET(handle,fieldname,value) \ do { \ MONO_PREPARE_GC_CRITICAL_REGION; \ @@ -114,6 +122,14 @@ mono_handle_domain (MonoHandle handle) MONO_FINISH_GC_CRITICAL_REGION; \ } while (0) +#define MONO_HANDLE_ARRAY_SETREF_NULL(handle,index) \ + do { \ + MONO_PREPARE_GC_CRITICAL_REGION; \ + mono_array_setref (mono_handle_obj ((handle)), (index), NULL); \ + MONO_FINISH_GC_CRITICAL_REGION; \ + } while (0) + + #define MONO_HANDLE_ARRAY_SET(handle,type,index,value) \ do { \ MONO_PREPARE_GC_CRITICAL_REGION; \ From 670f9ce22988196760155102ac16a2b6df651b61 Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Mon, 28 Dec 2015 17:49:15 -0500 Subject: [PATCH 13/20] [coop] store MonoHandleArena pointer in MonoThreadInfo --- mono/metadata/handle.c | 5 +++-- mono/metadata/sgen-mono.c | 5 +++++ mono/utils/mono-threads.h | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index f2a2be690f17..e6a4899f50b7 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -16,6 +16,7 @@ #include #include #include +#include #define HANDLES_PER_CHUNK (16 - 2) @@ -197,11 +198,11 @@ mono_handle_arena_deinitialize (MonoHandleArena **arena_stack) MonoHandleArena* mono_handle_arena_current (void) { - g_assert_not_reached (); + return (MonoHandleArena*) mono_thread_info_current ()->handle_arena; } MonoHandleArena** mono_handle_arena_current_addr (void) { - g_assert_not_reached (); + return (MonoHandleArena**) &mono_thread_info_current ()->handle_arena; } diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 84a7b5be165d..a6382b896244 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -34,6 +34,7 @@ #include "metadata/runtime.h" #include "metadata/sgen-bridge-internals.h" #include "metadata/gc-internals.h" +#include "metadata/handle.h" #include "utils/mono-memory-model.h" #include "utils/mono-logger-internals.h" #include "utils/mono-error.h" @@ -2230,6 +2231,8 @@ thread_in_critical_region (SgenThreadInfo *info) static void sgen_thread_attach (SgenThreadInfo *info) { + mono_handle_arena_initialize ((MonoHandleArena**) &info->client_info.info.handle_arena); + if (mono_gc_get_gc_callbacks ()->thread_attach_func && !info->client_info.runtime_data) info->client_info.runtime_data = mono_gc_get_gc_callbacks ()->thread_attach_func (); } @@ -2245,6 +2248,8 @@ sgen_thread_detach (SgenThreadInfo *p) */ if (mono_domain_get ()) mono_thread_detach_internal (mono_thread_internal_current ()); + + mono_handle_arena_deinitialize ((MonoHandleArena**) &p->client_info.info.handle_arena); } gboolean diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index 5fe411dbe1ae..111146811de5 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -250,6 +250,9 @@ typedef struct { void *jit_data; MonoThreadInfoInterruptToken *interrupt_token; + + /* MonoHandleArena for coop handles */ + gpointer handle_arena; } MonoThreadInfo; typedef struct { From fc7ff95e2be7dc785ec68cf67bff5d7daf724a3c Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Mon, 4 Jan 2016 11:26:55 -0500 Subject: [PATCH 14/20] [checked] Nest MONO_{PREPARE,FINISH}_GC_CRITICAL_REGION --- mono/utils/checked-build.c | 8 ++++---- mono/utils/checked-build.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mono/utils/checked-build.c b/mono/utils/checked-build.c index 5c4fd4249e9a..dfe9880e560f 100644 --- a/mono/utils/checked-build.c +++ b/mono/utils/checked-build.c @@ -81,7 +81,7 @@ translate_backtrace (gpointer native_trace[], int size) typedef struct { GPtrArray *transitions; - gboolean in_gc_critical_region; + guint32 in_gc_critical_region; } CheckState; typedef struct { @@ -235,7 +235,7 @@ void * critical_gc_region_begin(void) { CheckState *state = get_state (); - state->in_gc_critical_region = TRUE; + state->in_gc_critical_region++; return state; } @@ -245,14 +245,14 @@ critical_gc_region_end(void* token) { CheckState *state = get_state(); g_assert (state == token); - state->in_gc_critical_region = FALSE; + state->in_gc_critical_region--; } void assert_not_in_gc_critical_region(void) { CheckState *state = get_state(); - if (state->in_gc_critical_region) { + if (state->in_gc_critical_region > 0) { MonoThreadInfo *cur = mono_thread_info_current(); state = mono_thread_info_current_state(cur); assertion_fail("Expected GC Unsafe mode, but was in %s state", mono_thread_state_name(state)); diff --git a/mono/utils/checked-build.h b/mono/utils/checked-build.h index 83efd67c0548..092ed1d3016e 100644 --- a/mono/utils/checked-build.h +++ b/mono/utils/checked-build.h @@ -83,7 +83,7 @@ Functions that can be called from both coop or preept modes. * The GC critical region must only occur in unsafe mode. */ #define MONO_PREPARE_GC_CRITICAL_REGION \ - MON_REQ_GC_UNSAFE_MODE \ + MONO_REQ_GC_UNSAFE_MODE \ do { \ void* __critical_gc_region_cookie = critical_gc_region_begin() From a61a721cd57291fdb5807b14ba9005c09b06aab1 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 11 Jan 2016 14:00:48 +0000 Subject: [PATCH 15/20] [checked-build] Add in GC critical region assertion --- mono/metadata/handle.h | 3 ++- mono/utils/checked-build.c | 12 +++++++++--- mono/utils/checked-build.h | 9 ++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 5f4ed88aa9c9..d911a967d792 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -16,6 +16,7 @@ #include #include #include +#include /* * DO NOT ACCESS DIRECTLY @@ -57,7 +58,7 @@ mono_handle_elevate (MonoHandle handle) static inline void mono_handle_check_in_critical_section () { - MONO_REQ_GC_UNSAFE_MODE; + MONO_REQ_GC_CRITICAL; } #define mono_handle_obj(handle) (mono_handle_check_in_critical_section (), (handle)->__private_obj) diff --git a/mono/utils/checked-build.c b/mono/utils/checked-build.c index dfe9880e560f..35dc1773016d 100644 --- a/mono/utils/checked-build.c +++ b/mono/utils/checked-build.c @@ -253,12 +253,18 @@ assert_not_in_gc_critical_region(void) { CheckState *state = get_state(); if (state->in_gc_critical_region > 0) { - MonoThreadInfo *cur = mono_thread_info_current(); - state = mono_thread_info_current_state(cur); - assertion_fail("Expected GC Unsafe mode, but was in %s state", mono_thread_state_name(state)); + assertion_fail("Expected GC Unsafe mode, but was in %s state", mono_thread_state_name (mono_thread_info_current_state (mono_thread_info_current ()))); } } +void +assert_in_gc_critical_region (void) +{ + CheckState *state = get_state(); + if (state->in_gc_critical_region == 0) + assertion_fail("Expected GC critical region"); +} + // check_metadata_store et al: The goal of these functions is to verify that if there is a pointer from one mempool into // another, that the pointed-to memory is protected by the reference count mechanism for MonoImages. // diff --git a/mono/utils/checked-build.h b/mono/utils/checked-build.h index 092ed1d3016e..b2e90d0469f0 100644 --- a/mono/utils/checked-build.h +++ b/mono/utils/checked-build.h @@ -88,7 +88,7 @@ Functions that can be called from both coop or preept modes. void* __critical_gc_region_cookie = critical_gc_region_begin() #define MONO_FINISH_GC_CRITICAL_REGION \ - critical_gc_region_end(__critical_gc_region_cookie); \ + critical_gc_region_end(__critical_gc_region_cookie); \ } while(0) /* Verify that the thread is not currently in a GC critical region. */ @@ -96,6 +96,11 @@ Functions that can be called from both coop or preept modes. assert_not_in_gc_critical_region(); \ } while(0) +/* Verify that the thread is currently in a GC critical region. */ +#define MONO_REQ_GC_CRITICAL do { \ + assert_in_gc_critical_region(); \ + } while(0) + // Use when writing a pointer from one image or imageset to another. #define CHECKED_METADATA_WRITE_PTR(ptr, val) do { \ check_metadata_store (&(ptr), (val)); \ @@ -137,6 +142,7 @@ void assert_gc_neutral_mode (void); void* critical_gc_region_begin(void); void critical_gc_region_end(void* token); void assert_not_in_gc_critical_region(void); +void assert_in_gc_critical_region (void); void checked_build_init (void); void checked_build_thread_transition(const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta); @@ -158,6 +164,7 @@ void check_metadata_store_local(void *from, void *to); #define MONO_FINISH_GC_CRITICAL_REGION #define MONO_REQ_GC_NOT_CRITICAL +#define MONO_REQ_GC_CRITICAL #define CHECKED_MONO_INIT() From 7757891ef009a96d4b19366479f9705ec92be5bf Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 6 Jan 2016 14:36:35 +0000 Subject: [PATCH 16/20] [handle] Move System.Globalization icalls --- mono/metadata/icall-def.h | 2 +- mono/metadata/locales.c | 1143 ++++++++++++++++++------------ mono/metadata/locales.h | 96 ++- mono/metadata/object-internals.h | 152 ---- 4 files changed, 760 insertions(+), 633 deletions(-) diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 88fb2539e833..4e4bd7f1d603 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -843,7 +843,7 @@ ICALL_TYPE(TENC, "System.Text.EncodingHelper", TENC_1) ICALL(TENC_1, "InternalCodePage", ves_icall_System_Text_EncodingHelper_InternalCodePage) ICALL_TYPE(UNORM, "System.Text.Normalization", UNORM_1) -ICALL(UNORM_1, "load_normalization_resource", load_normalization_resource) +ICALL(UNORM_1, "load_normalization_resource", ves_icall_System_Text_Normalization_load_normalization_resource) ICALL_TYPE(ILOCK, "System.Threading.Interlocked", ILOCK_1) ICALL(ILOCK_1, "Add(int&,int)", ves_icall_System_Threading_Interlocked_Add_Int) diff --git a/mono/metadata/locales.c b/mono/metadata/locales.c index 52e97eaca1ef..3d1ea792905e 100644 --- a/mono/metadata/locales.c +++ b/mono/metadata/locales.c @@ -18,12 +18,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include #ifndef DISABLE_NORMALIZATION @@ -37,25 +39,170 @@ #undef DEBUG -static gint32 string_invariant_compare_char (gunichar2 c1, gunichar2 c2, - gint32 options); -static gint32 string_invariant_compare (MonoString *str1, gint32 off1, - gint32 len1, MonoString *str2, - gint32 off2, gint32 len2, - gint32 options); -static MonoString *string_invariant_replace (MonoString *me, - MonoString *oldValue, - MonoString *newValue); -static gint32 string_invariant_indexof (MonoString *source, gint32 sindex, - gint32 count, MonoString *value, - MonoBoolean first); -static gint32 string_invariant_indexof_char (MonoString *source, gint32 sindex, - gint32 count, gunichar2 value, - MonoBoolean first); - -static const CultureInfoEntry* culture_info_entry_from_lcid (int lcid); - -static const RegionInfoEntry* region_info_entry_from_lcid (int lcid); +enum { + CompareOptions_None = 0x00, + CompareOptions_IgnoreCase = 0x01, + CompareOptions_IgnoreNonSpace = 0x02, + CompareOptions_IgnoreSymbols = 0x04, + CompareOptions_IgnoreKanaType = 0x08, + CompareOptions_IgnoreWidth = 0x10, + CompareOptions_StringSort = 0x20000000, + CompareOptions_Ordinal = 0x40000000, +}; + +struct _MonoCalendarData { + MonoObject obj; + MonoString *NativeName; + MonoArray *ShortDatePatterns; + MonoArray *YearMonthPatterns; + MonoArray *LongDatePatterns; + MonoString *MonthDayPattern; + + MonoArray *EraNames; + MonoArray *AbbreviatedEraNames; + MonoArray *AbbreviatedEnglishEraNames; + MonoArray *DayNames; + MonoArray *AbbreviatedDayNames; + MonoArray *SuperShortDayNames; + MonoArray *MonthNames; + MonoArray *AbbreviatedMonthNames; + MonoArray *GenitiveMonthNames; + MonoArray *GenitiveAbbreviatedMonthNames; +}; + +struct _MonoCompareInfo { + MonoObject obj; + gint32 lcid; + MonoString *icu_name; + gpointer ICU_collator; +}; + +struct _MonoCultureData { + MonoObject obj; + MonoString *AMDesignator; + MonoString *PMDesignator; + MonoString *TimeSeparator; + MonoArray *LongTimePatterns; + MonoArray *ShortTimePatterns; + guint32 FirstDayOfWeek; + guint32 CalendarWeekRule; +}; + +struct _MonoCultureInfo { + MonoObject obj; + MonoBoolean is_read_only; + gint32 lcid; + gint32 parent_lcid; + gint32 datetime_index; + gint32 number_index; + gint32 calendar_type; + MonoBoolean use_user_override; + MonoNumberFormatInfo *number_format; + MonoDateTimeFormatInfo *datetime_format; + MonoObject *textinfo; + MonoString *name; + MonoString *englishname; + MonoString *nativename; + MonoString *iso3lang; + MonoString *iso2lang; + MonoString *win3lang; + MonoString *territory; + MonoArray *native_calendar_names; + MonoCompareInfo *compareinfo; + const void* text_info_data; +}; + +struct _MonoDateTimeFormatInfo { + MonoObject obj; + MonoBoolean readOnly; + MonoString *AMDesignator; + MonoString *PMDesignator; + MonoString *DateSeparator; + MonoString *TimeSeparator; + MonoString *ShortDatePattern; + MonoString *LongDatePattern; + MonoString *ShortTimePattern; + MonoString *LongTimePattern; + MonoString *MonthDayPattern; + MonoString *YearMonthPattern; + guint32 FirstDayOfWeek; + guint32 CalendarWeekRule; + MonoArray *AbbreviatedDayNames; + MonoArray *DayNames; + MonoArray *MonthNames; + MonoArray *GenitiveMonthNames; + MonoArray *AbbreviatedMonthNames; + MonoArray *GenitiveAbbreviatedMonthNames; + MonoArray *ShortDatePatterns; + MonoArray *LongDatePatterns; + MonoArray *ShortTimePatterns; + MonoArray *LongTimePatterns; + MonoArray *MonthDayPatterns; + MonoArray *YearMonthPatterns; + MonoArray *ShortestDayNames; +}; + +struct _MonoNumberFormatInfo { + MonoObject obj; + MonoArray *numberGroupSizes; + MonoArray *currencyGroupSizes; + MonoArray *percentGroupSizes; + MonoString *positiveSign; + MonoString *negativeSign; + MonoString *numberDecimalSeparator; + MonoString *numberGroupSeparator; + MonoString *currencyGroupSeparator; + MonoString *currencyDecimalSeparator; + MonoString *currencySymbol; + MonoString *ansiCurrencySymbol; /* unused */ + MonoString *naNSymbol; + MonoString *positiveInfinitySymbol; + MonoString *negativeInfinitySymbol; + MonoString *percentDecimalSeparator; + MonoString *percentGroupSeparator; + MonoString *percentSymbol; + MonoString *perMilleSymbol; + MonoString *nativeDigits; /* unused */ + gint32 dataItem; /* unused */ + guint32 numberDecimalDigits; + gint32 currencyDecimalDigits; + gint32 currencyPositivePattern; + gint32 currencyNegativePattern; + gint32 numberNegativePattern; + gint32 percentPositivePattern; + gint32 percentNegativePattern; + gint32 percentDecimalDigits; +}; + +struct _MonoRegionInfo { + MonoObject obj; + gint32 geo_id; + MonoString *iso2name; + MonoString *iso3name; + MonoString *win3name; + MonoString *english_name; + MonoString *native_name; + MonoString *currency_symbol; + MonoString *iso_currency_symbol; + MonoString *currency_english_name; + MonoString *currency_native_name; +}; + +struct _MonoSortKey { + MonoObject obj; + MonoString *str; + gint32 options; + MonoArray *key; + gint32 lcid; +}; + +MONO_HANDLE_TYPE_DECL (MonoCalendarData); +MONO_HANDLE_TYPE_DECL (MonoCompareInfo); +MONO_HANDLE_TYPE_DECL (MonoCultureData); +MONO_HANDLE_TYPE_DECL (MonoCultureInfo); +MONO_HANDLE_TYPE_DECL (MonoNumberFormatInfo); +MONO_HANDLE_TYPE_DECL (MonoRegionInfo); +MONO_HANDLE_TYPE_DECL (MonoSortKey); static int culture_lcid_locator (const void *a, const void *b) @@ -90,56 +237,68 @@ region_name_locator (const void *a, const void *b) return ret; } -static MonoArray* -create_group_sizes_array (const gint *gs, gint ml) +static MONO_HANDLE_TYPE (MonoArray) +create_group_sizes_array (const gint *gs, gint ml, MonoError *error) { - MonoArray *ret; - int i, len = 0; + MONO_HANDLE_TYPE (MonoArray) ret; + gsize i, len = 0; for (i = 0; i < ml; i++) { if (gs [i] == -1) break; len++; } - - ret = mono_array_new_cached (mono_domain_get (), - mono_get_int32_class (), len); - for(i = 0; i < len; i++) - mono_array_set (ret, gint32, i, gs [i]); + ret = mono_handle_array_new (mono_domain_get (), mono_get_int32_class (), len, error); + if (!mono_error_ok (error)) + goto done; + + for (i = 0; i < len; i++) + MONO_HANDLE_ARRAY_SET (ret, gint32, i, gs [i]); +done: return ret; } -static MonoArray* -create_names_array_idx (const guint16 *names, int ml) +static MONO_HANDLE_TYPE (MonoArray) +create_names_array_idx (const guint16 *names, gsize ml, MonoError *error) { - MonoArray *ret; + MONO_HANDLE_TYPE (MonoArray) ret; MonoDomain *domain; - int i; + gsize i; if (names == NULL) - return NULL; + return MONO_HANDLE_NEW (MonoArray, NULL); domain = mono_domain_get (); - ret = mono_array_new_cached (mono_domain_get (), mono_get_string_class (), ml); + ret = mono_handle_array_new (domain, mono_get_string_class (), ml, error); + if (!mono_error_ok (error)) + goto done; + + MONO_HANDLE_ARENA_PUSH (); - for(i = 0; i < ml; i++) - mono_array_setref (ret, i, mono_string_new (domain, idx2string (names [i]))); + for (i = 0; i < ml; i++) { + MONO_HANDLE_ARRAY_SETREF (ret, i, mono_handle_string_new (domain, idx2string (names [i]), error)); + if (!mono_error_ok (error)) + break; + } + MONO_HANDLE_ARENA_POP; + +done: return ret; } -static MonoArray* -create_names_array_idx_dynamic (const guint16 *names, int ml) +static MONO_HANDLE_TYPE (MonoArray) +create_names_array_idx_dynamic (const guint16 *names, gsize ml, MonoError *error) { - MonoArray *ret; + MONO_HANDLE_TYPE (MonoArray) ret; MonoDomain *domain; - int i, len = 0; + gsize i, len = 0; if (names == NULL) - return NULL; + return MONO_HANDLE_NEW (MonoArray, NULL); domain = mono_domain_get (); @@ -149,193 +308,310 @@ create_names_array_idx_dynamic (const guint16 *names, int ml) len++; } - ret = mono_array_new_cached (mono_domain_get (), mono_get_string_class (), len); + ret = mono_handle_array_new (domain, mono_get_string_class (), len, error); + if (!mono_error_ok (error)) + goto done; - for(i = 0; i < len; i++) - mono_array_setref (ret, i, mono_string_new (domain, idx2string (names [i]))); + MONO_HANDLE_ARENA_PUSH (); + for (i = 0; i < len; i++) { + MONO_HANDLE_ARRAY_SETREF (ret, i, mono_handle_string_new (domain, idx2string (names [i]), error)); + if (!mono_error_ok (error)) + break; + } + + MONO_HANDLE_ARENA_POP; + +done: return ret; } MonoBoolean ves_icall_System_Globalization_CalendarData_fill_calendar_data (MonoCalendarData *this_obj, MonoString *name, gint32 calendar_index) { - MonoDomain *domain; - const DateTimeFormatEntry *dfe; - const CultureInfoNameEntry *ne; - const CultureInfoEntry *ci; - char *n; + MonoBoolean ret; - n = mono_string_to_utf8 (name); - ne = (const CultureInfoNameEntry *)mono_binary_search (n, culture_name_entries, NUM_CULTURE_ENTRIES, - sizeof (CultureInfoNameEntry), culture_name_locator); - g_free (n); - if (ne == NULL) { - return FALSE; - } + MONO_HANDLE_ARENA_PUSH (); - ci = &culture_entries [ne->culture_entry_index]; - dfe = &datetime_format_entries [ci->datetime_format_index]; + MONO_HANDLE_TYPE (MonoCalendarData) this_obj_handle = MONO_HANDLE_NEW (MonoCalendarData, this_obj); + MONO_HANDLE_TYPE (MonoString) name_handle = MONO_HANDLE_NEW (MonoString, name); - domain = mono_domain_get (); + MonoError error; + gchar *name_utf8; + const CultureInfoNameEntry *name_entry; - MONO_OBJECT_SETREF (this_obj, NativeName, mono_string_new (domain, idx2string (ci->nativename))); - MONO_OBJECT_SETREF (this_obj, ShortDatePatterns, create_names_array_idx_dynamic (dfe->short_date_patterns, - NUM_SHORT_DATE_PATTERNS)); - MONO_OBJECT_SETREF (this_obj, YearMonthPatterns, create_names_array_idx_dynamic (dfe->year_month_patterns, - NUM_YEAR_MONTH_PATTERNS)); - - MONO_OBJECT_SETREF (this_obj, LongDatePatterns, create_names_array_idx_dynamic (dfe->long_date_patterns, - NUM_LONG_DATE_PATTERNS)); - MONO_OBJECT_SETREF (this_obj, MonthDayPattern, mono_string_new (domain, idx2string (dfe->month_day_pattern))); - - MONO_OBJECT_SETREF (this_obj, DayNames, create_names_array_idx (dfe->day_names, NUM_DAYS)); - MONO_OBJECT_SETREF (this_obj, AbbreviatedDayNames, create_names_array_idx (dfe->abbreviated_day_names, - NUM_DAYS)); - MONO_OBJECT_SETREF (this_obj, SuperShortDayNames, create_names_array_idx (dfe->shortest_day_names, NUM_DAYS)); - MONO_OBJECT_SETREF (this_obj, MonthNames, create_names_array_idx (dfe->month_names, NUM_MONTHS)); - MONO_OBJECT_SETREF (this_obj, AbbreviatedMonthNames, create_names_array_idx (dfe->abbreviated_month_names, - NUM_MONTHS)); - MONO_OBJECT_SETREF (this_obj, GenitiveMonthNames, create_names_array_idx (dfe->month_genitive_names, NUM_MONTHS)); - MONO_OBJECT_SETREF (this_obj, GenitiveAbbreviatedMonthNames, create_names_array_idx (dfe->abbreviated_month_genitive_names, NUM_MONTHS)); + ret = TRUE; - return TRUE; + name_utf8 = mono_handle_string_to_utf8 (name_handle, &error); + g_assert (mono_error_ok (&error)); + + name_entry = mono_binary_search (name_utf8, culture_name_entries, NUM_CULTURE_ENTRIES, sizeof (CultureInfoNameEntry), culture_name_locator); + + g_free (name_utf8); + + if (!name_entry) { + ret = FALSE; + } else { + MonoDomain *domain; + const DateTimeFormatEntry *dfe; + const CultureInfoEntry *ci; + + domain = mono_domain_get (); + + ci = &culture_entries [name_entry->culture_entry_index]; + dfe = &datetime_format_entries [ci->datetime_format_index]; + + MONO_HANDLE_SETREF (this_obj_handle, NativeName, mono_handle_string_new (domain, idx2string (ci->nativename), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, ShortDatePatterns, create_names_array_idx_dynamic (dfe->short_date_patterns, NUM_SHORT_DATE_PATTERNS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, YearMonthPatterns, create_names_array_idx_dynamic (dfe->year_month_patterns, NUM_YEAR_MONTH_PATTERNS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, LongDatePatterns, create_names_array_idx_dynamic (dfe->long_date_patterns, NUM_LONG_DATE_PATTERNS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, MonthDayPattern, mono_handle_string_new (domain, idx2string (dfe->month_day_pattern), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, DayNames, create_names_array_idx (dfe->day_names, NUM_DAYS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, AbbreviatedDayNames, create_names_array_idx (dfe->abbreviated_day_names, NUM_DAYS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, SuperShortDayNames, create_names_array_idx (dfe->shortest_day_names, NUM_DAYS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, MonthNames, create_names_array_idx (dfe->month_names, NUM_MONTHS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, AbbreviatedMonthNames, create_names_array_idx (dfe->abbreviated_month_names, NUM_MONTHS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, GenitiveMonthNames, create_names_array_idx (dfe->month_genitive_names, NUM_MONTHS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, GenitiveAbbreviatedMonthNames, create_names_array_idx (dfe->abbreviated_month_genitive_names, NUM_MONTHS, &error)); + g_assert (mono_error_ok (&error)); + } + + MONO_HANDLE_ARENA_POP; + + return ret; } void ves_icall_System_Globalization_CultureData_fill_culture_data (MonoCultureData *this_obj, gint32 datetime_index) { + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoCultureData) this_obj_handle = MONO_HANDLE_NEW (MonoCultureData, this_obj); + + MonoError error; MonoDomain *domain; const DateTimeFormatEntry *dfe; g_assert (datetime_index >= 0); - dfe = &datetime_format_entries [datetime_index]; domain = mono_domain_get (); - MONO_OBJECT_SETREF (this_obj, AMDesignator, mono_string_new (domain, idx2string (dfe->am_designator))); - MONO_OBJECT_SETREF (this_obj, PMDesignator, mono_string_new (domain, idx2string (dfe->pm_designator))); - MONO_OBJECT_SETREF (this_obj, TimeSeparator, mono_string_new (domain, idx2string (dfe->time_separator))); - MONO_OBJECT_SETREF (this_obj, LongTimePatterns, create_names_array_idx_dynamic (dfe->long_time_patterns, - NUM_LONG_TIME_PATTERNS)); - MONO_OBJECT_SETREF (this_obj, ShortTimePatterns, create_names_array_idx_dynamic (dfe->short_time_patterns, - NUM_SHORT_TIME_PATTERNS)); - this_obj->FirstDayOfWeek = dfe->first_day_of_week; - this_obj->CalendarWeekRule = dfe->calendar_week_rule; + MONO_HANDLE_SETREF (this_obj_handle, AMDesignator, mono_handle_string_new (domain, idx2string (dfe->am_designator), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, PMDesignator, mono_handle_string_new (domain, idx2string (dfe->pm_designator), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, TimeSeparator, mono_handle_string_new (domain, idx2string (dfe->time_separator), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, LongTimePatterns, create_names_array_idx_dynamic (dfe->long_time_patterns, NUM_LONG_TIME_PATTERNS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, ShortTimePatterns, create_names_array_idx_dynamic (dfe->short_time_patterns, NUM_SHORT_TIME_PATTERNS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SET (this_obj_handle, FirstDayOfWeek, dfe->first_day_of_week); + + MONO_HANDLE_SET (this_obj_handle, CalendarWeekRule, dfe->calendar_week_rule); + + MONO_HANDLE_ARENA_POP; } void ves_icall_System_Globalization_CultureData_fill_number_data (MonoNumberFormatInfo* number, gint32 number_index) { + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoNumberFormatInfo) number_handle = MONO_HANDLE_NEW (MonoNumberFormatInfo, number); + + MonoError error; MonoDomain *domain; const NumberFormatEntry *nfe; g_assert (number_index >= 0); - nfe = &number_format_entries [number_index]; domain = mono_domain_get (); - number->currencyDecimalDigits = nfe->currency_decimal_digits; - MONO_OBJECT_SETREF (number, currencyDecimalSeparator, mono_string_new (domain, - idx2string (nfe->currency_decimal_separator))); - MONO_OBJECT_SETREF (number, currencyGroupSeparator, mono_string_new (domain, - idx2string (nfe->currency_group_separator))); - MONO_OBJECT_SETREF (number, currencyGroupSizes, create_group_sizes_array (nfe->currency_group_sizes, - GROUP_SIZE)); - number->currencyNegativePattern = nfe->currency_negative_pattern; - number->currencyPositivePattern = nfe->currency_positive_pattern; - MONO_OBJECT_SETREF (number, currencySymbol, mono_string_new (domain, idx2string (nfe->currency_symbol))); - MONO_OBJECT_SETREF (number, naNSymbol, mono_string_new (domain, idx2string (nfe->nan_symbol))); - MONO_OBJECT_SETREF (number, negativeInfinitySymbol, mono_string_new (domain, - idx2string (nfe->negative_infinity_symbol))); - MONO_OBJECT_SETREF (number, negativeSign, mono_string_new (domain, idx2string (nfe->negative_sign))); - number->numberDecimalDigits = nfe->number_decimal_digits; - MONO_OBJECT_SETREF (number, numberDecimalSeparator, mono_string_new (domain, - idx2string (nfe->number_decimal_separator))); - MONO_OBJECT_SETREF (number, numberGroupSeparator, mono_string_new (domain, idx2string (nfe->number_group_separator))); - MONO_OBJECT_SETREF (number, numberGroupSizes, create_group_sizes_array (nfe->number_group_sizes, - GROUP_SIZE)); - number->numberNegativePattern = nfe->number_negative_pattern; - number->percentNegativePattern = nfe->percent_negative_pattern; - number->percentPositivePattern = nfe->percent_positive_pattern; - MONO_OBJECT_SETREF (number, percentSymbol, mono_string_new (domain, idx2string (nfe->percent_symbol))); - MONO_OBJECT_SETREF (number, perMilleSymbol, mono_string_new (domain, idx2string (nfe->per_mille_symbol))); - MONO_OBJECT_SETREF (number, positiveInfinitySymbol, mono_string_new (domain, - idx2string (nfe->positive_infinity_symbol))); - MONO_OBJECT_SETREF (number, positiveSign, mono_string_new (domain, idx2string (nfe->positive_sign))); + MONO_HANDLE_SET (number_handle, currencyDecimalDigits, nfe->currency_decimal_digits); + + MONO_HANDLE_SETREF (number_handle, currencyDecimalSeparator, mono_handle_string_new (domain, idx2string (nfe->currency_decimal_separator), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, currencyGroupSeparator, mono_handle_string_new (domain, idx2string (nfe->currency_group_separator), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, currencyGroupSizes, create_group_sizes_array (nfe->currency_group_sizes, GROUP_SIZE, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SET (number_handle, currencyNegativePattern, nfe->currency_negative_pattern); + + MONO_HANDLE_SET (number_handle, currencyPositivePattern, nfe->currency_positive_pattern); + + MONO_HANDLE_SETREF (number_handle, currencySymbol, mono_handle_string_new (domain, idx2string (nfe->currency_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, naNSymbol, mono_handle_string_new (domain, idx2string (nfe->nan_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, negativeInfinitySymbol, mono_handle_string_new (domain, idx2string (nfe->negative_infinity_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, negativeSign, mono_handle_string_new (domain, idx2string (nfe->negative_sign), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SET (number_handle, numberDecimalDigits, nfe->number_decimal_digits); + + MONO_HANDLE_SETREF (number_handle, numberDecimalSeparator, mono_handle_string_new (domain, idx2string (nfe->number_decimal_separator), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, numberGroupSeparator, mono_handle_string_new (domain, idx2string (nfe->number_group_separator), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, numberGroupSizes, create_group_sizes_array (nfe->number_group_sizes, GROUP_SIZE, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SET (number_handle, numberNegativePattern, nfe->number_negative_pattern); + + MONO_HANDLE_SET (number_handle, percentNegativePattern, nfe->percent_negative_pattern); + + MONO_HANDLE_SET (number_handle, percentPositivePattern, nfe->percent_positive_pattern); + + MONO_HANDLE_SETREF (number_handle, percentSymbol, mono_handle_string_new (domain, idx2string (nfe->percent_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, perMilleSymbol, mono_handle_string_new (domain, idx2string (nfe->per_mille_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, positiveInfinitySymbol, mono_handle_string_new (domain, idx2string (nfe->positive_infinity_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (number_handle, positiveSign, mono_handle_string_new (domain, idx2string (nfe->positive_sign), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_ARENA_POP; } static MonoBoolean -construct_culture (MonoCultureInfo *this_obj, const CultureInfoEntry *ci) +construct_culture (MONO_HANDLE_TYPE (MonoCultureInfo) this_obj_handle, const CultureInfoEntry *ci) { - MonoDomain *domain = mono_domain_get (); + MONO_HANDLE_ARENA_PUSH (); + + MonoError error; + MonoDomain *domain; + + domain = mono_domain_get (); - this_obj->lcid = ci->lcid; - MONO_OBJECT_SETREF (this_obj, name, mono_string_new (domain, idx2string (ci->name))); - MONO_OBJECT_SETREF (this_obj, englishname, mono_string_new (domain, idx2string (ci->englishname))); - MONO_OBJECT_SETREF (this_obj, nativename, mono_string_new (domain, idx2string (ci->nativename))); - MONO_OBJECT_SETREF (this_obj, win3lang, mono_string_new (domain, idx2string (ci->win3lang))); - MONO_OBJECT_SETREF (this_obj, iso3lang, mono_string_new (domain, idx2string (ci->iso3lang))); - MONO_OBJECT_SETREF (this_obj, iso2lang, mono_string_new (domain, idx2string (ci->iso2lang))); + MONO_HANDLE_SET (this_obj_handle, lcid, ci->lcid); + + MONO_HANDLE_SETREF (this_obj_handle, name, mono_handle_string_new (domain, idx2string (ci->name), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, englishname, mono_handle_string_new (domain, idx2string (ci->englishname), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, nativename, mono_handle_string_new (domain, idx2string (ci->nativename), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, win3lang, mono_handle_string_new (domain, idx2string (ci->win3lang), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, iso3lang, mono_handle_string_new (domain, idx2string (ci->iso3lang), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, iso2lang, mono_handle_string_new (domain, idx2string (ci->iso2lang), &error)); + g_assert (mono_error_ok (&error)); // It's null for neutral cultures - if (ci->territory > 0) - MONO_OBJECT_SETREF (this_obj, territory, mono_string_new (domain, idx2string (ci->territory))); - MONO_OBJECT_SETREF (this_obj, native_calendar_names, create_names_array_idx (ci->native_calendar_names, NUM_CALENDARS)); - this_obj->parent_lcid = ci->parent_lcid; - this_obj->datetime_index = ci->datetime_format_index; - this_obj->number_index = ci->number_format_index; - this_obj->calendar_type = ci->calendar_type; - this_obj->text_info_data = &ci->text_info; - + if (ci->territory > 0) { + MONO_HANDLE_SETREF (this_obj_handle, territory, mono_handle_string_new (domain, idx2string (ci->territory), &error)); + g_assert (mono_error_ok (&error)); + } + + MONO_HANDLE_SETREF (this_obj_handle, native_calendar_names, create_names_array_idx (ci->native_calendar_names, NUM_CALENDARS, &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SET (this_obj_handle, parent_lcid, ci->parent_lcid); + + MONO_HANDLE_SET (this_obj_handle, datetime_index, ci->datetime_format_index); + + MONO_HANDLE_SET (this_obj_handle, number_index, ci->number_format_index); + + MONO_HANDLE_SET (this_obj_handle, calendar_type, ci->calendar_type); + + MONO_HANDLE_SET (this_obj_handle, text_info_data, &ci->text_info); + + MONO_HANDLE_ARENA_POP; + return TRUE; } static MonoBoolean -construct_region (MonoRegionInfo *this_obj, const RegionInfoEntry *ri) +construct_region (MONO_HANDLE_TYPE (MonoRegionInfo) this_obj_handle, const RegionInfoEntry *ri) { - MonoDomain *domain = mono_domain_get (); - - this_obj->geo_id = ri->geo_id; - MONO_OBJECT_SETREF (this_obj, iso2name, mono_string_new (domain, idx2string (ri->iso2name))); - MONO_OBJECT_SETREF (this_obj, iso3name, mono_string_new (domain, idx2string (ri->iso3name))); - MONO_OBJECT_SETREF (this_obj, win3name, mono_string_new (domain, idx2string (ri->win3name))); - MONO_OBJECT_SETREF (this_obj, english_name, mono_string_new (domain, idx2string (ri->english_name))); - MONO_OBJECT_SETREF (this_obj, native_name, mono_string_new (domain, idx2string (ri->native_name))); - MONO_OBJECT_SETREF (this_obj, currency_symbol, mono_string_new (domain, idx2string (ri->currency_symbol))); - MONO_OBJECT_SETREF (this_obj, iso_currency_symbol, mono_string_new (domain, idx2string (ri->iso_currency_symbol))); - MONO_OBJECT_SETREF (this_obj, currency_english_name, mono_string_new (domain, idx2string (ri->currency_english_name))); - MONO_OBJECT_SETREF (this_obj, currency_native_name, mono_string_new (domain, idx2string (ri->currency_native_name))); - - return TRUE; -} + MONO_HANDLE_ARENA_PUSH (); -static const CultureInfoEntry* -culture_info_entry_from_lcid (int lcid) -{ - const CultureInfoEntry *ci; + MonoError error; + MonoDomain *domain; - ci = (const CultureInfoEntry *)mono_binary_search (&lcid, culture_entries, NUM_CULTURE_ENTRIES, sizeof (CultureInfoEntry), culture_lcid_locator); + domain = mono_domain_get (); - return ci; -} + MONO_HANDLE_SET (this_obj_handle, geo_id, ri->geo_id); -static const RegionInfoEntry* -region_info_entry_from_lcid (int lcid) -{ - const RegionInfoEntry *entry; - const CultureInfoEntry *ne; + MONO_HANDLE_SETREF (this_obj_handle, iso2name, mono_handle_string_new (domain, idx2string (ri->iso2name), &error)); + g_assert (mono_error_ok (&error)); - ne = (const CultureInfoEntry *)mono_binary_search (&lcid, culture_entries, NUM_CULTURE_ENTRIES, sizeof (CultureInfoEntry), culture_lcid_locator); + MONO_HANDLE_SETREF (this_obj_handle, iso3name, mono_handle_string_new (domain, idx2string (ri->iso3name), &error)); + g_assert (mono_error_ok (&error)); - if (ne == NULL) - return FALSE; + MONO_HANDLE_SETREF (this_obj_handle, win3name, mono_handle_string_new (domain, idx2string (ri->win3name), &error)); + g_assert (mono_error_ok (&error)); - entry = ®ion_entries [ne->region_entry_index]; + MONO_HANDLE_SETREF (this_obj_handle, english_name, mono_handle_string_new (domain, idx2string (ri->english_name), &error)); + g_assert (mono_error_ok (&error)); - return entry; + MONO_HANDLE_SETREF (this_obj_handle, native_name, mono_handle_string_new (domain, idx2string (ri->native_name), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, currency_symbol, mono_handle_string_new (domain, idx2string (ri->currency_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, iso_currency_symbol, mono_handle_string_new (domain, idx2string (ri->iso_currency_symbol), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, currency_english_name, mono_handle_string_new (domain, idx2string (ri->currency_english_name), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_SETREF (this_obj_handle, currency_native_name, mono_handle_string_new (domain, idx2string (ri->currency_native_name), &error)); + g_assert (mono_error_ok (&error)); + + MONO_HANDLE_ARENA_POP; + + return TRUE; } #if defined (__APPLE__) @@ -473,114 +749,165 @@ get_current_locale_name (void) MonoString* ves_icall_System_Globalization_CultureInfo_get_current_locale_name (void) { - gchar *locale; MonoString* ret; - MonoDomain *domain; + + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoString) ret_handle; + + MonoError error; + gchar *locale; locale = get_current_locale_name (); - if (locale == NULL) - return NULL; + if (!locale) { + ret_handle = MONO_HANDLE_NEW (MonoString, NULL); + } else { + ret_handle = mono_handle_string_new (mono_domain_get (), locale, &error); + g_assert (mono_error_ok (&error)); - domain = mono_domain_get (); - ret = mono_string_new (domain, locale); - g_free (locale); + g_free (locale); + } + + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (ret_handle, ret); return ret; } +static const CultureInfoEntry* +culture_info_entry_from_lcid (int lcid) +{ + return mono_binary_search (&lcid, culture_entries, NUM_CULTURE_ENTRIES, sizeof (CultureInfoEntry), culture_lcid_locator); +} + MonoBoolean -ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_lcid (MonoCultureInfo *this_obj, - gint lcid) +ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_lcid (MonoCultureInfo *this_obj, gint lcid) { + MonoBoolean ret; + + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoCultureInfo) this_obj_handle = MONO_HANDLE_NEW (MonoCultureInfo, this_obj); + const CultureInfoEntry *ci; - + ci = culture_info_entry_from_lcid (lcid); if(ci == NULL) - return FALSE; + ret = FALSE; + else + ret = construct_culture (this_obj_handle, ci); + + MONO_HANDLE_ARENA_POP; - return construct_culture (this_obj, ci); + return ret; } MonoBoolean -ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_name (MonoCultureInfo *this_obj, - MonoString *name) +ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_name (MonoCultureInfo *this_obj, MonoString *name) { - const CultureInfoNameEntry *ne; - char *n; - - n = mono_string_to_utf8 (name); - ne = (const CultureInfoNameEntry *)mono_binary_search (n, culture_name_entries, NUM_CULTURE_ENTRIES, - sizeof (CultureInfoNameEntry), culture_name_locator); + MonoBoolean ret; - if (ne == NULL) { - /*g_print ("ne (%s) is null\n", n);*/ - g_free (n); - return FALSE; - } - g_free (n); + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoCultureInfo) this_obj_handle = MONO_HANDLE_NEW (MonoCultureInfo, this_obj); + MONO_HANDLE_TYPE (MonoString) name_handle = MONO_HANDLE_NEW (MonoString, name); + + MonoError error; + gchar *name_utf8; + const CultureInfoNameEntry *name_entry; + + name_utf8 = mono_handle_string_to_utf8 (name_handle, &error); + g_assert (mono_error_ok (&error)); - return construct_culture (this_obj, &culture_entries [ne->culture_entry_index]); + name_entry = mono_binary_search (name_utf8, culture_name_entries, NUM_CULTURE_ENTRIES, sizeof (CultureInfoNameEntry), culture_name_locator); + + g_free (name_utf8); + + ret = name_entry ? construct_culture (this_obj_handle, &culture_entries [name_entry->culture_entry_index]) : FALSE; + + MONO_HANDLE_ARENA_POP; + + return ret; } -/* -MonoBoolean -ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_specific_name (MonoCultureInfo *ci, - MonoString *name) + +static const RegionInfoEntry* +region_info_entry_from_lcid (int lcid) { - gchar *locale; - gboolean ret; + const RegionInfoEntry *entry; + const CultureInfoEntry *ne; - locale = mono_string_to_utf8 (name); - ret = construct_culture_from_specific_name (ci, locale); - g_free (locale); + ne = mono_binary_search (&lcid, culture_entries, NUM_CULTURE_ENTRIES, sizeof (CultureInfoEntry), culture_lcid_locator); - return ret; + if (ne == NULL) + return FALSE; + + entry = ®ion_entries [ne->region_entry_index]; + + return entry; } -*/ + MonoBoolean -ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_lcid (MonoRegionInfo *this_obj, - gint lcid) +ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_lcid (MonoRegionInfo *this_obj, gint lcid) { + MonoBoolean ret; + + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoRegionInfo) this_obj_handle = MONO_HANDLE_NEW (MonoRegionInfo, this_obj); + const RegionInfoEntry *ri; - + ri = region_info_entry_from_lcid (lcid); - if(ri == NULL) - return FALSE; - return construct_region (this_obj, ri); + ret = ri ? construct_region (this_obj_handle, ri) : FALSE; + + MONO_HANDLE_ARENA_POP; + + return ret; } MonoBoolean -ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_name (MonoRegionInfo *this_obj, - MonoString *name) +ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_name (MonoRegionInfo *this_obj, MonoString *name) { - const RegionInfoNameEntry *ne; - char *n; - - n = mono_string_to_utf8 (name); - ne = (const RegionInfoNameEntry *)mono_binary_search (n, region_name_entries, NUM_REGION_ENTRIES, - sizeof (RegionInfoNameEntry), region_name_locator); + MonoBoolean ret; - if (ne == NULL) { - /*g_print ("ne (%s) is null\n", n);*/ - g_free (n); - return FALSE; - } - g_free (n); + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoRegionInfo) this_obj_handle = MONO_HANDLE_NEW (MonoRegionInfo, this_obj); + MONO_HANDLE_TYPE (MonoString) name_handle = MONO_HANDLE_NEW (MonoString, name); + + MonoError error; + gchar *name_utf8; + const RegionInfoNameEntry *name_entry; + + name_utf8 = mono_handle_string_to_utf8 (name_handle, &error); + g_assert (mono_error_ok (&error)); - return construct_region (this_obj, ®ion_entries [ne->region_entry_index]); + name_entry = mono_binary_search (name_utf8, region_name_entries, NUM_REGION_ENTRIES, sizeof (RegionInfoNameEntry), region_name_locator); + + g_free (name_utf8); + + ret = name_entry ? construct_region (this_obj_handle, ®ion_entries [name_entry->region_entry_index]) : FALSE; + + MONO_HANDLE_ARENA_POP; + + return ret; } MonoArray* -ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean neutral, - MonoBoolean specific, MonoBoolean installed) +ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean neutral, MonoBoolean specific, MonoBoolean installed) { MonoArray *ret; + + MONO_HANDLE_ARENA_PUSH (); + + MONO_HANDLE_TYPE (MonoArray) ret_handle; + + MonoError error; MonoClass *klass; - MonoCultureInfo *culture; MonoDomain *domain; - const CultureInfoEntry *ci; gint i, len; gboolean is_neutral; + const CultureInfoEntry *ci; domain = mono_domain_get (); @@ -592,103 +919,65 @@ ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean ne len++; } - klass = mono_class_from_name (mono_get_corlib (), - "System.Globalization", "CultureInfo"); + klass = mono_class_from_name (mono_get_corlib (), "System.Globalization", "CultureInfo"); /* The InvariantCulture is not in culture_entries */ /* We reserve the first slot in the array for it */ if (neutral) len++; - ret = mono_array_new (domain, klass, len); + ret_handle = mono_handle_array_new (domain, klass, len, &error); + g_assert (mono_error_ok (&error)); - if (len == 0) - return ret; + if (len != 0) { + gint last = 0; - len = 0; - if (neutral) - mono_array_setref (ret, len++, NULL); + if (neutral) + MONO_HANDLE_ARRAY_SETREF_NULL (ret_handle, last++); - for (i = 0; i < NUM_CULTURE_ENTRIES; i++) { - ci = &culture_entries [i]; - is_neutral = ci->territory == 0; - if ((neutral && is_neutral) || (specific && !is_neutral)) { - culture = (MonoCultureInfo *) mono_object_new (domain, klass); - mono_runtime_object_init ((MonoObject *) culture); - construct_culture (culture, ci); - culture->use_user_override = TRUE; - mono_array_setref (ret, len++, culture); - } - } + for (i = 0; i < NUM_CULTURE_ENTRIES; i++) { + ci = &culture_entries [i]; + is_neutral = ci->territory == 0; + if ((neutral && is_neutral) || (specific && !is_neutral)) { + MONO_HANDLE_ARENA_PUSH (); - return ret; -} + MONO_HANDLE_TYPE (MonoCultureInfo) culture_handle; -int ves_icall_System_Globalization_CompareInfo_internal_compare (MonoCompareInfo *this_obj, MonoString *str1, gint32 off1, gint32 len1, MonoString *str2, gint32 off2, gint32 len2, gint32 options) -{ - /* Do a normal ascii string compare, as we only know the - * invariant locale if we dont have ICU - */ - return(string_invariant_compare (str1, off1, len1, str2, off2, len2, - options)); -} + culture_handle = (MONO_HANDLE_TYPE (MonoCultureInfo)) mono_handle_object_new (domain, klass, &error); + g_assert (mono_error_ok (&error)); -void ves_icall_System_Globalization_CompareInfo_assign_sortkey (MonoCompareInfo *this_obj, MonoSortKey *key, MonoString *source, gint32 options) -{ - MonoArray *arr; - gint32 keylen, i; + mono_handle_runtime_object_init ((MONO_HANDLE_TYPE (MonoObject)) culture_handle); - keylen=mono_string_length (source); - - arr=mono_array_new (mono_domain_get (), mono_get_byte_class (), - keylen); - for(i=0; i 0) ? 1 : 0); } -static gint32 string_invariant_compare (MonoString *str1, gint32 off1, - gint32 len1, MonoString *str2, - gint32 off2, gint32 len2, - gint32 options) +int +ves_icall_System_Globalization_CompareInfo_internal_compare (MonoCompareInfo *this_obj, MonoString *str1, gint32 off1, gint32 len1, MonoString *str2, gint32 off2, gint32 len2, gint32 options) { - /* c translation of C# code from old string.cs.. :) */ + int ret; gint32 length; gint32 charcmp; gunichar2 *ustr1; gunichar2 *ustr2; gint32 pos; - if(len1 >= len2) { - length=len1; - } else { - length=len2; - } + MONO_PREPARE_GC_CRITICAL_REGION; - ustr1 = mono_string_chars(str1)+off1; - ustr2 = mono_string_chars(str2)+off2; + /* Do a normal ascii string compare, as we only know the + * invariant locale if we dont have ICU */ + + ustr1 = mono_string_chars (str1) + off1; + ustr2 = mono_string_chars (str2) + off2; - pos = 0; + length = len1 >= len2 ? len1 : len2; for (pos = 0; pos != length; pos++) { if (pos >= len1 || pos >= len2) break; - charcmp = string_invariant_compare_char(ustr1[pos], ustr2[pos], - options); + charcmp = string_invariant_compare_char (ustr1 [pos], ustr2 [pos], options); if (charcmp != 0) { - return(charcmp); + ret = charcmp; + goto done; } } /* the lesser wins, so if we have looped until length we just - * need to check the last char - */ + * need to check the last char */ if (pos == length) { - return(string_invariant_compare_char(ustr1[pos - 1], - ustr2[pos - 1], options)); + ret = string_invariant_compare_char (ustr1 [pos - 1], ustr2 [pos - 1], options); + goto done; } /* Test if one of the strings has been compared to the end */ - if (pos >= len1) { - if (pos >= len2) { - return(0); - } else { - return(-1); - } + if (pos >= len1 && pos >= len2) { + ret = 0; + goto done; + } else if (pos >= len1) { + ret = -1; + goto done; } else if (pos >= len2) { - return(1); + ret = 1; + goto done; } /* if not, check our last char only.. (can this happen?) */ - return(string_invariant_compare_char(ustr1[pos], ustr2[pos], options)); + ret = string_invariant_compare_char (ustr1 [pos], ustr2 [pos], options); + +done: + MONO_FINISH_GC_CRITICAL_REGION; + + return ret; } -static MonoString *string_invariant_replace (MonoString *me, - MonoString *oldValue, - MonoString *newValue) +void +ves_icall_System_Globalization_CompareInfo_assign_sortkey (MonoCompareInfo *this_obj, MonoSortKey *key, MonoString *source, gint32 options) { - MonoString *ret; - gunichar2 *src; - gunichar2 *dest=NULL; /* shut gcc up */ - gunichar2 *oldstr; - gunichar2 *newstr=NULL; /* shut gcc up here too */ - gint32 i, destpos; - gint32 occurr; - gint32 newsize; - gint32 oldstrlen; - gint32 newstrlen; - gint32 srclen; - - occurr = 0; - destpos = 0; - - oldstr = mono_string_chars(oldValue); - oldstrlen = mono_string_length(oldValue); - - if (NULL != newValue) { - newstr = mono_string_chars(newValue); - newstrlen = mono_string_length(newValue); - } else - newstrlen = 0; - - src = mono_string_chars(me); - srclen = mono_string_length(me); - - if (oldstrlen != newstrlen) { - i = 0; - while (i <= srclen - oldstrlen) { - if (0 == memcmp(src + i, oldstr, oldstrlen * sizeof(gunichar2))) { - occurr++; - i += oldstrlen; - } - else - i ++; - } - if (occurr == 0) - return me; - newsize = srclen + ((newstrlen - oldstrlen) * occurr); - } else - newsize = srclen; - - ret = NULL; - i = 0; - while (i < srclen) { - if (0 == memcmp(src + i, oldstr, oldstrlen * sizeof(gunichar2))) { - if (ret == NULL) { - ret = mono_string_new_size( mono_domain_get (), newsize); - dest = mono_string_chars(ret); - memcpy (dest, src, i * sizeof(gunichar2)); - } - if (newstrlen > 0) { - memcpy(dest + destpos, newstr, newstrlen * sizeof(gunichar2)); - destpos += newstrlen; - } - i += oldstrlen; - continue; - } else if (ret != NULL) { - dest[destpos] = src[i]; - } - destpos++; - i++; - } - - if (ret == NULL) - return me; + MONO_HANDLE_ARENA_PUSH (); - return ret; + MONO_HANDLE_TYPE (MonoString) source_handle = MONO_HANDLE_NEW (MonoString, source); + MONO_HANDLE_TYPE (MonoSortKey) key_handle = MONO_HANDLE_NEW (MonoSortKey, key); + MONO_HANDLE_TYPE (MonoArray) array_handle; + + MonoError error; + gint32 source_len, i; + + source_len = mono_handle_string_length (source_handle); + + array_handle = mono_handle_array_new (mono_domain_get (), mono_get_byte_class (), source_len, &error); + g_assert (mono_error_ok (&error)); + + MONO_PREPARE_GC_CRITICAL_REGION; + + gunichar2 *source_chars = mono_handle_string_chars (source_handle); + + for (i = 0; i < source_len; i++) + MONO_HANDLE_ARRAY_SET (array_handle, guint8, i, source_chars [i]); + + MONO_FINISH_GC_CRITICAL_REGION; + + MONO_HANDLE_SETREF (key_handle, key, array_handle); + + MONO_HANDLE_ARENA_POP; } -static gint32 string_invariant_indexof (MonoString *source, gint32 sindex, - gint32 count, MonoString *value, - MonoBoolean first) +int +ves_icall_System_Globalization_CompareInfo_internal_index (MonoCompareInfo *this_obj, MonoString *source, gint32 sindex, gint32 count, MonoString *value, gint32 options, MonoBoolean first) { + gint ret; + gint32 lencmpstr; gunichar2 *src; gunichar2 *cmpstr; - gint32 pos,i; - - lencmpstr = mono_string_length(value); - - src = mono_string_chars(source); - cmpstr = mono_string_chars(value); + gint32 pos, i; + + ret = -1; + + MONO_PREPARE_GC_CRITICAL_REGION; - if(first) { + src = mono_string_chars (source); + cmpstr = mono_string_chars (value); + lencmpstr = mono_string_length (value); + + if (first) { count -= lencmpstr; - for(pos=sindex;pos <= sindex+count;pos++) { - for(i=0;src[pos+i]==cmpstr[i];) { - if(++i==lencmpstr) { - return(pos); + for (pos = sindex; pos <= sindex + count; pos++) { + for (i = 0; src [pos + i] == cmpstr [i]; ) { + if (++i == lencmpstr) { + ret = pos; + break; } } } - - return(-1); } else { - for(pos=sindex-lencmpstr+1;pos>sindex-count;pos--) { - if(memcmp (src+pos, cmpstr, - lencmpstr*sizeof(gunichar2))==0) { - return(pos); + for (pos = sindex - lencmpstr + 1; pos > sindex - count; pos--) { + if (memcmp (src + pos, cmpstr, lencmpstr * sizeof (gunichar2)) == 0) { + ret = pos; + break; } } - - return(-1); } + + MONO_FINISH_GC_CRITICAL_REGION; + + return ret; } -static gint32 string_invariant_indexof_char (MonoString *source, gint32 sindex, - gint32 count, gunichar2 value, - MonoBoolean first) +int +ves_icall_System_Globalization_CompareInfo_internal_index_char (MonoCompareInfo *this_obj, MonoString *source, gint32 sindex, gint32 count, gunichar2 value, gint32 options, MonoBoolean first) { + gint ret; + gint32 pos; gunichar2 *src; - src = mono_string_chars(source); - if(first) { + ret = -1; + + MONO_PREPARE_GC_CRITICAL_REGION; + + src = mono_string_chars (source); + + if (first) { for (pos = sindex; pos != count + sindex; pos++) { if (src [pos] == value) { - return(pos); + ret = pos; + break; } } - - return(-1); } else { for (pos = sindex; pos > sindex - count; pos--) { - if (src [pos] == value) - return(pos); + if (src [pos] == value) { + ret = pos; + break; + } } - - return(-1); } + + MONO_FINISH_GC_CRITICAL_REGION; + + return ret; } -void load_normalization_resource (guint8 **argProps, - guint8 **argMappedChars, - guint8 **argCharMapIndex, - guint8 **argHelperIndex, - guint8 **argMapIdxToComposite, - guint8 **argCombiningClass) +int +ves_icall_System_Threading_Thread_current_lcid (void) +{ + /* Invariant */ + return 0x007F; +} + +void +ves_icall_System_Text_Normalization_load_normalization_resource (guint8 **argProps, guint8 **argMappedChars, guint8 **argCharMapIndex, guint8 **argHelperIndex, guint8 **argMapIdxToComposite, guint8 **argCombiningClass) { #ifdef DISABLE_NORMALIZATION mono_set_pending_exception (mono_get_exception_not_supported ("This runtime has been compiled without string normalization support.")); - return; #else *argProps = (guint8*)props; *argMappedChars = (guint8*) mappedChars; @@ -923,5 +1186,3 @@ void load_normalization_resource (guint8 **argProps, *argCombiningClass = (guint8*)combiningClass; #endif } - - diff --git a/mono/metadata/locales.h b/mono/metadata/locales.h index 67234f64f6d7..4eb9c02409cc 100644 --- a/mono/metadata/locales.h +++ b/mono/metadata/locales.h @@ -12,45 +12,63 @@ #include -#include - -/* This is a copy of System.Globalization.CompareOptions */ -typedef enum { - CompareOptions_None=0x00, - CompareOptions_IgnoreCase=0x01, - CompareOptions_IgnoreNonSpace=0x02, - CompareOptions_IgnoreSymbols=0x04, - CompareOptions_IgnoreKanaType=0x08, - CompareOptions_IgnoreWidth=0x10, - CompareOptions_StringSort=0x20000000, - CompareOptions_Ordinal=0x40000000 -} MonoCompareOptions; - -extern MonoBoolean ves_icall_System_Globalization_CalendarData_fill_calendar_data (MonoCalendarData *this_obj, MonoString *name, gint32 calendar_index); -extern void ves_icall_System_Globalization_CultureData_fill_culture_data (MonoCultureData *this_obj, gint32 datetime_index); -extern void ves_icall_System_Globalization_CultureData_fill_number_data (MonoNumberFormatInfo* number, gint32 number_index); -extern void ves_icall_System_Globalization_CultureInfo_construct_internal_locale (MonoCultureInfo *this_obj, MonoString *locale); -extern MonoString* ves_icall_System_Globalization_CultureInfo_get_current_locale_name (void); -extern MonoBoolean ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_lcid (MonoCultureInfo *this_obj, gint lcid); -extern MonoBoolean ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_name (MonoCultureInfo *this_obj, MonoString *name); -extern MonoArray *ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean neutral, MonoBoolean specific, MonoBoolean installed); -extern void ves_icall_System_Globalization_CompareInfo_construct_compareinfo (MonoCompareInfo *comp, MonoString *locale); -extern int ves_icall_System_Globalization_CompareInfo_internal_compare (MonoCompareInfo *this_obj, MonoString *str1, gint32 off1, gint32 len1, MonoString *str2, gint32 off2, gint32 len2, gint32 options); -extern void ves_icall_System_Globalization_CompareInfo_free_internal_collator (MonoCompareInfo *this_obj); -extern MonoBoolean +#include + +typedef struct _MonoCalendarData MonoCalendarData; +typedef struct _MonoCompareInfo MonoCompareInfo; +typedef struct _MonoCultureData MonoCultureData; +typedef struct _MonoCultureInfo MonoCultureInfo; +typedef struct _MonoDateTimeFormatInfo MonoDateTimeFormatInfo; +typedef struct _MonoNumberFormatInfo MonoNumberFormatInfo; +typedef struct _MonoRegionInfo MonoRegionInfo; +typedef struct _MonoSortKey MonoSortKey; + +MonoBoolean +ves_icall_System_Globalization_CalendarData_fill_calendar_data (MonoCalendarData *this_obj, MonoString *name, gint32 calendar_index); + +void +ves_icall_System_Globalization_CultureData_fill_culture_data (MonoCultureData *this_obj, gint32 datetime_index); + +void +ves_icall_System_Globalization_CultureData_fill_number_data (MonoNumberFormatInfo* number, gint32 number_index); + +void +ves_icall_System_Globalization_CultureInfo_construct_internal_locale (MonoCultureInfo *this_obj, MonoString *locale); + +MonoString* +ves_icall_System_Globalization_CultureInfo_get_current_locale_name (void); + +MonoBoolean +ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_lcid (MonoCultureInfo *this_obj, gint lcid); + +MonoBoolean +ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_name (MonoCultureInfo *this_obj, MonoString *name); + +MonoArray* +ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean neutral, MonoBoolean specific, MonoBoolean installed); + +int +ves_icall_System_Globalization_CompareInfo_internal_compare (MonoCompareInfo *this_obj, MonoString *str1, gint32 off1, gint32 len1, MonoString *str2, gint32 off2, gint32 len2, gint32 options); + +MonoBoolean ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_lcid (MonoRegionInfo *this_obj, gint lcid); -extern MonoBoolean -ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_name (MonoRegionInfo *this_obj, - MonoString *name); -extern void ves_icall_System_Globalization_CompareInfo_assign_sortkey (MonoCompareInfo *this_obj, MonoSortKey *key, MonoString *source, gint32 options); -extern int ves_icall_System_Globalization_CompareInfo_internal_index (MonoCompareInfo *this_obj, MonoString *source, gint32 sindex, gint32 count, MonoString *value, gint32 options, MonoBoolean first); -extern int ves_icall_System_Globalization_CompareInfo_internal_index_char (MonoCompareInfo *this_obj, MonoString *source, gint32 sindex, gint32 count, gunichar2 value, gint32 options, MonoBoolean first); -extern int ves_icall_System_Threading_Thread_current_lcid (void); -extern MonoString *ves_icall_System_String_InternalReplace_Str_Comp (MonoString *this_obj, MonoString *old, MonoString *new_str, MonoCompareInfo *comp); -extern MonoString *ves_icall_System_String_InternalToLower_Comp (MonoString *this_obj, MonoCultureInfo *cult); -extern MonoString *ves_icall_System_String_InternalToUpper_Comp (MonoString *this_obj, MonoCultureInfo *cult); -extern gunichar2 ves_icall_System_Char_InternalToUpper_Comp (gunichar2 c, MonoCultureInfo *cult); -extern gunichar2 ves_icall_System_Char_InternalToLower_Comp (gunichar2 c, MonoCultureInfo *cult); -extern void load_normalization_resource (guint8 **argProps, guint8** argMappedChars, guint8** argCharMapIndex, guint8** argHelperIndex, guint8** argMapIdxToComposite, guint8** argCombiningClass); + +MonoBoolean +ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_name (MonoRegionInfo *this_obj, MonoString *name); + +void +ves_icall_System_Globalization_CompareInfo_assign_sortkey (MonoCompareInfo *this_obj, MonoSortKey *key, MonoString *source, gint32 options); + +int +ves_icall_System_Globalization_CompareInfo_internal_index (MonoCompareInfo *this_obj, MonoString *source, gint32 sindex, gint32 count, MonoString *value, gint32 options, MonoBoolean first); + +int +ves_icall_System_Globalization_CompareInfo_internal_index_char (MonoCompareInfo *this_obj, MonoString *source, gint32 sindex, gint32 count, gunichar2 value, gint32 options, MonoBoolean first); + +int +ves_icall_System_Threading_Thread_current_lcid (void); + +void +ves_icall_System_Text_Normalization_load_normalization_resource (guint8 **argProps, guint8** argMappedChars, guint8** argCharMapIndex, guint8** argHelperIndex, guint8** argMapIdxToComposite, guint8** argCombiningClass); #endif /* _MONO_METADATA_FILEIO_H_ */ diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 60cfaac692c5..a6ed0a926874 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -438,158 +438,6 @@ struct _MonoThread { MonoObject *start_obj; }; -typedef struct { - guint32 state; - MonoObject *additional; -} MonoStreamingContext; - -typedef struct { - MonoObject obj; - MonoBoolean readOnly; - MonoString *AMDesignator; - MonoString *PMDesignator; - MonoString *DateSeparator; - MonoString *TimeSeparator; - MonoString *ShortDatePattern; - MonoString *LongDatePattern; - MonoString *ShortTimePattern; - MonoString *LongTimePattern; - MonoString *MonthDayPattern; - MonoString *YearMonthPattern; - guint32 FirstDayOfWeek; - guint32 CalendarWeekRule; - MonoArray *AbbreviatedDayNames; - MonoArray *DayNames; - MonoArray *MonthNames; - MonoArray *GenitiveMonthNames; - MonoArray *AbbreviatedMonthNames; - MonoArray *GenitiveAbbreviatedMonthNames; - MonoArray *ShortDatePatterns; - MonoArray *LongDatePatterns; - MonoArray *ShortTimePatterns; - MonoArray *LongTimePatterns; - MonoArray *MonthDayPatterns; - MonoArray *YearMonthPatterns; - MonoArray *ShortestDayNames; -} MonoDateTimeFormatInfo; - -typedef struct -{ - MonoObject obj; - MonoArray *numberGroupSizes; - MonoArray *currencyGroupSizes; - MonoArray *percentGroupSizes; - MonoString *positiveSign; - MonoString *negativeSign; - MonoString *numberDecimalSeparator; - MonoString *numberGroupSeparator; - MonoString *currencyGroupSeparator; - MonoString *currencyDecimalSeparator; - MonoString *currencySymbol; - MonoString *ansiCurrencySymbol; /* unused */ - MonoString *naNSymbol; - MonoString *positiveInfinitySymbol; - MonoString *negativeInfinitySymbol; - MonoString *percentDecimalSeparator; - MonoString *percentGroupSeparator; - MonoString *percentSymbol; - MonoString *perMilleSymbol; - MonoString *nativeDigits; /* unused */ - gint32 dataItem; /* unused */ - guint32 numberDecimalDigits; - gint32 currencyDecimalDigits; - gint32 currencyPositivePattern; - gint32 currencyNegativePattern; - gint32 numberNegativePattern; - gint32 percentPositivePattern; - gint32 percentNegativePattern; - gint32 percentDecimalDigits; -} MonoNumberFormatInfo; - -typedef struct { - MonoObject obj; - gint32 lcid; - MonoString *icu_name; - gpointer ICU_collator; -} MonoCompareInfo; - -typedef struct { - MonoObject obj; - MonoString *NativeName; - MonoArray *ShortDatePatterns; - MonoArray *YearMonthPatterns; - MonoArray *LongDatePatterns; - MonoString *MonthDayPattern; - - MonoArray *EraNames; - MonoArray *AbbreviatedEraNames; - MonoArray *AbbreviatedEnglishEraNames; - MonoArray *DayNames; - MonoArray *AbbreviatedDayNames; - MonoArray *SuperShortDayNames; - MonoArray *MonthNames; - MonoArray *AbbreviatedMonthNames; - MonoArray *GenitiveMonthNames; - MonoArray *GenitiveAbbreviatedMonthNames; -} MonoCalendarData; - -typedef struct { - MonoObject obj; - MonoString *AMDesignator; - MonoString *PMDesignator; - MonoString *TimeSeparator; - MonoArray *LongTimePatterns; - MonoArray *ShortTimePatterns; - guint32 FirstDayOfWeek; - guint32 CalendarWeekRule; -} MonoCultureData; - -typedef struct { - MonoObject obj; - MonoBoolean is_read_only; - gint32 lcid; - gint32 parent_lcid; - gint32 datetime_index; - gint32 number_index; - gint32 calendar_type; - MonoBoolean use_user_override; - MonoNumberFormatInfo *number_format; - MonoDateTimeFormatInfo *datetime_format; - MonoObject *textinfo; - MonoString *name; - MonoString *englishname; - MonoString *nativename; - MonoString *iso3lang; - MonoString *iso2lang; - MonoString *win3lang; - MonoString *territory; - MonoArray *native_calendar_names; - MonoCompareInfo *compareinfo; - const void* text_info_data; -} MonoCultureInfo; - -typedef struct { - MonoObject obj; - gint32 geo_id; - MonoString *iso2name; - MonoString *iso3name; - MonoString *win3name; - MonoString *english_name; - MonoString *native_name; - MonoString *currency_symbol; - MonoString *iso_currency_symbol; - MonoString *currency_english_name; - MonoString *currency_native_name; -} MonoRegionInfo; - -typedef struct { - MonoObject obj; - MonoString *str; - gint32 options; - MonoArray *key; - gint32 lcid; -} MonoSortKey; - typedef struct { MonoObject object; guint32 intType; From 75af549299abf7dc26ca0e9ff71186fd247d47e6 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 8 Jan 2016 18:42:20 +0000 Subject: [PATCH 17/20] [handle] Move ves_icall_System_Array_(Set|Get)Value(Impl) icall --- mono/metadata/icall.c | 361 +++++++++++++++++++++++------------------- 1 file changed, 196 insertions(+), 165 deletions(-) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 69c89e9faf12..3a05740f0fc1 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -123,19 +123,27 @@ mono_class_init_or_throw (MonoClass *klass) ICALL_EXPORT MonoObject * ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos) { - MonoClass *ac; - gint32 esize; - gpointer *ea; + MonoClass *arr_class = mono_object_class (arr); - ac = (MonoClass *)arr->obj.vtable->klass; + if (!arr_class->element_class->valuetype) { + return *(MonoObject**) mono_array_addr_with_size (arr, mono_array_element_size (arr_class), pos); + } else { + MonoError error; + MonoObject *ret; - esize = mono_array_element_size (ac); - ea = (gpointer*)((char*)arr->vector + (pos * esize)); + MONO_HANDLE_ARENA_PUSH (); - if (ac->element_class->valuetype) - return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea); - else - return (MonoObject *)*ea; + MONO_HANDLE_TYPE (MonoArray) arr_handle = MONO_HANDLE_NEW (MonoArray, arr); + MONO_HANDLE_TYPE (MonoObject) ret_handle; + + ret_handle = mono_handle_array_value_box (mono_handle_domain ((MonoHandle) arr_handle), arr_class->element_class, arr_handle, pos, &error); + + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (ret_handle, ret); + + mono_error_raise_exception (&error); + + return ret; + } } ICALL_EXPORT MonoObject * @@ -148,9 +156,9 @@ ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs) MONO_CHECK_ARG_NULL (idxs, NULL); io = idxs; - ic = (MonoClass *)io->obj.vtable->klass; - - ac = (MonoClass *)arr->obj.vtable->klass; + ic = mono_object_class (io); + + ac = mono_object_class (arr); g_assert (ic->rank == 1); if (io->bounds != NULL || io->max_length != ac->rank) { @@ -167,90 +175,70 @@ ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs) } return ves_icall_System_Array_GetValueImpl (arr, *ind); - } - - for (i = 0; i < ac->rank; i++) { - if ((ind [i] < arr->bounds [i].lower_bound) || - (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) { - mono_set_pending_exception (mono_get_exception_index_out_of_range ()); - return NULL; + } else { + for (i = 0; i < ac->rank; i++) { + if ((ind [i] < arr->bounds [i].lower_bound) || + (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) { + mono_set_pending_exception (mono_get_exception_index_out_of_range ()); + return NULL; + } } - } - pos = ind [0] - arr->bounds [0].lower_bound; - for (i = 1; i < ac->rank; i++) - pos = pos * arr->bounds [i].length + ind [i] - - arr->bounds [i].lower_bound; + pos = ind [0] - arr->bounds [0].lower_bound; + for (i = 1; i < ac->rank; i++) + pos = pos * arr->bounds [i].length + ind [i] - arr->bounds [i].lower_bound; - return ves_icall_System_Array_GetValueImpl (arr, pos); + return ves_icall_System_Array_GetValueImpl (arr, pos); + } } ICALL_EXPORT void ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos) { - MonoClass *ac, *vc, *ec; - gint32 esize, vsize; - gpointer *ea, *va; - int et, vt; - - guint64 u64 = 0; - gint64 i64 = 0; - gdouble r64 = 0; + MONO_HANDLE_ARENA_PUSH (); - if (value) - vc = value->vtable->klass; - else - vc = NULL; + MONO_HANDLE_TYPE (MonoArray) arr_handle = MONO_HANDLE_NEW (MonoArray, arr); + MONO_HANDLE_TYPE (MonoObject) value_handle = MONO_HANDLE_NEW (MonoObject, value); - ac = arr->obj.vtable->klass; - ec = ac->element_class; + MonoClass *arr_class, *value_class, *element_class; + gint32 element_size, value_size; + int element_type, value_type; - esize = mono_array_element_size (ac); - ea = (gpointer*)((char*)arr->vector + (pos * esize)); - va = (gpointer*)((char*)value + sizeof (MonoObject)); + arr_class = mono_handle_class ((MonoHandle) arr_handle); + element_class = arr_class->element_class; - if (mono_class_is_nullable (ec)) { - mono_nullable_init ((guint8*)ea, value, ec); - return; + if (mono_class_is_nullable (element_class)) { + MonoError error; + mono_handle_array_nullable_init (mono_domain_get (), element_class, arr_handle, pos, value_handle, &error); + mono_error_set_pending_exception (&error); + goto done; } + element_size = mono_array_element_size (arr_class); + if (!value) { - mono_gc_bzero_atomic (ea, esize); - return; + MONO_PREPARE_GC_CRITICAL_REGION; + mono_gc_bzero_atomic (mono_handle_array_addr_with_size (arr_handle, element_size, pos), element_size); + MONO_FINISH_GC_CRITICAL_REGION; + goto done; } -#define NO_WIDENING_CONVERSION G_STMT_START{\ - mono_set_pending_exception (mono_get_exception_argument ( \ - "value", "not a widening conversion")); \ - return; \ -}G_STMT_END - -#define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\ - if (esize < vsize + (extra)) { \ - mono_set_pending_exception (mono_get_exception_argument ( \ - "value", "not a widening conversion")); \ - return; \ - } \ -}G_STMT_END - -#define INVALID_CAST G_STMT_START{ \ - mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \ - mono_set_pending_exception (mono_get_exception_invalid_cast ()); \ - return; \ -}G_STMT_END + value_class = mono_handle_class ((MonoHandle) value_handle); /* Check element (destination) type. */ - switch (ec->byval_arg.type) { + switch (element_class->byval_arg.type) { case MONO_TYPE_STRING: - switch (vc->byval_arg.type) { + switch (value_class->byval_arg.type) { case MONO_TYPE_STRING: break; default: - INVALID_CAST; + mono_get_runtime_callbacks ()->set_cast_details (value_class, element_class); + mono_set_pending_exception (mono_get_exception_invalid_cast ()); + goto done; } break; case MONO_TYPE_BOOLEAN: - switch (vc->byval_arg.type) { + switch (value_class->byval_arg.type) { case MONO_TYPE_BOOLEAN: break; case MONO_TYPE_CHAR: @@ -264,53 +252,82 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 case MONO_TYPE_I8: case MONO_TYPE_R4: case MONO_TYPE_R8: - NO_WIDENING_CONVERSION; + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); + goto done; default: - INVALID_CAST; + mono_get_runtime_callbacks ()->set_cast_details (value_class, element_class); + mono_set_pending_exception (mono_get_exception_invalid_cast ()); + goto done; } break; default: break; } - if (!ec->valuetype) { - if (!mono_object_isinst (value, ec)) - INVALID_CAST; - mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value); - return; + if (!element_class->valuetype) { + if (!mono_handle_object_isinst (value_handle, element_class)) { + mono_get_runtime_callbacks ()->set_cast_details (value_class, element_class); + mono_set_pending_exception (mono_get_exception_invalid_cast ()); + } else { + MONO_PREPARE_GC_CRITICAL_REGION; + mono_gc_wbarrier_set_arrayref (mono_handle_obj (arr_handle), mono_handle_array_addr_with_size (arr_handle, element_size, pos), mono_handle_obj (value_handle)); + MONO_FINISH_GC_CRITICAL_REGION; + } + + goto done; } - if (mono_object_isinst (value, ec)) { - if (ec->has_references) - mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec); - else - mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize); - return; + if (mono_handle_object_isinst (value_handle, element_class)) { + MONO_PREPARE_GC_CRITICAL_REGION; + + guint8 *src = (guint8*) mono_handle_obj (value_handle) + sizeof (MonoObject); + guint8 *dst = (guint8*) mono_handle_array_addr_with_size (arr_handle, element_size, pos); + + mono_gc_wbarrier_value_copy (dst, src, 1, element_class); + + MONO_FINISH_GC_CRITICAL_REGION; + + goto done; + } + + if (!value_class->valuetype) { + mono_get_runtime_callbacks ()->set_cast_details (value_class, element_class); + mono_set_pending_exception (mono_get_exception_invalid_cast ()); + goto done; } - if (!vc->valuetype) - INVALID_CAST; + element_type = element_class->byval_arg.type; + if (element_type == MONO_TYPE_VALUETYPE && element_class->byval_arg.data.klass->enumtype) + element_type = mono_class_enum_basetype (element_class->byval_arg.data.klass)->type; + + value_type = value_class->byval_arg.type; + if (value_type == MONO_TYPE_VALUETYPE && value_class->byval_arg.data.klass->enumtype) + value_type = mono_class_enum_basetype (value_class->byval_arg.data.klass)->type; + + value_size = mono_class_instance_size (value_class) - sizeof (MonoObject); - vsize = mono_class_instance_size (vc) - sizeof (MonoObject); + MONO_PREPARE_GC_CRITICAL_REGION; - et = ec->byval_arg.type; - if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype) - et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type; + guint8 *src = (guint8*) mono_handle_obj (value_handle) + sizeof (MonoObject); + guint8 *dst = (guint8*) mono_handle_array_addr_with_size (arr_handle, element_size, pos); - vt = vc->byval_arg.type; - if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype) - vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type; + guint64 u64 = 0; + gint64 i64 = 0; + gdouble r64 = 0; -#define ASSIGN_UNSIGNED(etype) G_STMT_START{\ - switch (vt) { \ +#define ASSIGN_UNSIGNED(etype) do {\ + switch (value_type) { \ case MONO_TYPE_U1: \ case MONO_TYPE_U2: \ case MONO_TYPE_U4: \ case MONO_TYPE_U8: \ case MONO_TYPE_CHAR: \ - CHECK_WIDENING_CONVERSION(0); \ - *(etype *) ea = (etype) u64; \ - return; \ + if (element_size < value_size) { \ + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); \ + goto done_critical; \ + } \ + *(etype *) dst = (etype) u64; \ + goto done_critical; \ /* You can't assign a signed value to an unsigned array. */ \ case MONO_TYPE_I1: \ case MONO_TYPE_I2: \ @@ -319,19 +336,23 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 /* You can't assign a floating point number to an integer array. */ \ case MONO_TYPE_R4: \ case MONO_TYPE_R8: \ - NO_WIDENING_CONVERSION; \ + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); \ + goto done_critical; \ } \ -}G_STMT_END +} while (0) -#define ASSIGN_SIGNED(etype) G_STMT_START{\ - switch (vt) { \ +#define ASSIGN_SIGNED(etype) do {\ + switch (value_type) { \ case MONO_TYPE_I1: \ case MONO_TYPE_I2: \ case MONO_TYPE_I4: \ case MONO_TYPE_I8: \ - CHECK_WIDENING_CONVERSION(0); \ - *(etype *) ea = (etype) i64; \ - return; \ + if (element_size < value_size) { \ + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); \ + goto done_critical; \ + } \ + *(etype *) dst = (etype) i64; \ + goto done_critical; \ /* You can assign an unsigned value to a signed array if the array's */ \ /* element size is larger than the value size. */ \ case MONO_TYPE_U1: \ @@ -339,78 +360,84 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 case MONO_TYPE_U4: \ case MONO_TYPE_U8: \ case MONO_TYPE_CHAR: \ - CHECK_WIDENING_CONVERSION(1); \ - *(etype *) ea = (etype) u64; \ - return; \ + if (element_size < value_size + 1) { \ + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); \ + goto done_critical; \ + } \ + *(etype *) dst = (etype) u64; \ + goto done_critical; \ /* You can't assign a floating point number to an integer array. */ \ case MONO_TYPE_R4: \ case MONO_TYPE_R8: \ - NO_WIDENING_CONVERSION; \ + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); \ + goto done_critical; \ } \ -}G_STMT_END +} while (0) -#define ASSIGN_REAL(etype) G_STMT_START{\ - switch (vt) { \ +#define ASSIGN_REAL(etype) do {\ + switch (value_type) { \ case MONO_TYPE_R4: \ case MONO_TYPE_R8: \ - CHECK_WIDENING_CONVERSION(0); \ - *(etype *) ea = (etype) r64; \ - return; \ - /* All integer values fit into a floating point array, so we don't */ \ - /* need to CHECK_WIDENING_CONVERSION here. */ \ + if (element_size < value_size) { \ + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); \ + goto done_critical; \ + } \ + *(etype *) dst = (etype) r64; \ + goto done_critical; \ + /* All integer values fit into a floating point array */ \ case MONO_TYPE_I1: \ case MONO_TYPE_I2: \ case MONO_TYPE_I4: \ case MONO_TYPE_I8: \ - *(etype *) ea = (etype) i64; \ - return; \ + *(etype *) dst = (etype) i64; \ + goto done_critical; \ case MONO_TYPE_U1: \ case MONO_TYPE_U2: \ case MONO_TYPE_U4: \ case MONO_TYPE_U8: \ case MONO_TYPE_CHAR: \ - *(etype *) ea = (etype) u64; \ - return; \ + *(etype *) dst = (etype) u64; \ + goto done_critical; \ } \ -}G_STMT_END +} while (0) - switch (vt) { + switch (value_type) { case MONO_TYPE_U1: - u64 = *(guint8 *) va; + u64 = *(guint8 *) src; break; case MONO_TYPE_U2: - u64 = *(guint16 *) va; + u64 = *(guint16 *) src; break; case MONO_TYPE_U4: - u64 = *(guint32 *) va; + u64 = *(guint32 *) src; break; case MONO_TYPE_U8: - u64 = *(guint64 *) va; + u64 = *(guint64 *) src; break; case MONO_TYPE_I1: - i64 = *(gint8 *) va; + i64 = *(gint8 *) src; break; case MONO_TYPE_I2: - i64 = *(gint16 *) va; + i64 = *(gint16 *) src; break; case MONO_TYPE_I4: - i64 = *(gint32 *) va; + i64 = *(gint32 *) src; break; case MONO_TYPE_I8: - i64 = *(gint64 *) va; + i64 = *(gint64 *) src; break; case MONO_TYPE_R4: - r64 = *(gfloat *) va; + r64 = *(gfloat *) src; break; case MONO_TYPE_R8: - r64 = *(gdouble *) va; + r64 = *(gdouble *) src; break; case MONO_TYPE_CHAR: - u64 = *(guint16 *) va; + u64 = *(guint16 *) src; break; case MONO_TYPE_BOOLEAN: /* Boolean is only compatible with itself. */ - switch (et) { + switch (element_type) { case MONO_TYPE_CHAR: case MONO_TYPE_U1: case MONO_TYPE_U2: @@ -422,15 +449,18 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 case MONO_TYPE_I8: case MONO_TYPE_R4: case MONO_TYPE_R8: - NO_WIDENING_CONVERSION; + mono_set_pending_exception (mono_get_exception_argument ("value", "not a widening conversion")); + goto done_critical; default: - INVALID_CAST; + mono_get_runtime_callbacks ()->set_cast_details (value_class, element_class); + mono_set_pending_exception (mono_get_exception_invalid_cast ()); + goto done_critical; } break; } /* If we can't do a direct copy, let's try a widening conversion. */ - switch (et) { + switch (element_type) { case MONO_TYPE_CHAR: ASSIGN_UNSIGNED (guint16); case MONO_TYPE_U1: @@ -455,29 +485,32 @@ ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 ASSIGN_REAL (gdouble); } - INVALID_CAST; - /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */ - return; + mono_get_runtime_callbacks ()->set_cast_details (value_class, element_class); + mono_set_pending_exception (mono_get_exception_invalid_cast ()); -#undef INVALID_CAST -#undef NO_WIDENING_CONVERSION -#undef CHECK_WIDENING_CONVERSION -#undef ASSIGN_UNSIGNED -#undef ASSIGN_SIGNED #undef ASSIGN_REAL +#undef ASSIGN_SIGNED +#undef ASSIGN_UNSIGNED + +done_critical: + + MONO_FINISH_GC_CRITICAL_REGION; + +done: + + MONO_HANDLE_ARENA_POP; } ICALL_EXPORT void -ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value, - MonoArray *idxs) +ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value, MonoArray *idxs) { MonoClass *ac, *ic; gint32 i, pos, *ind; MONO_CHECK_ARG_NULL (idxs,); - ic = idxs->obj.vtable->klass; - ac = arr->obj.vtable->klass; + ic = mono_object_class (idxs); + ac = mono_object_class (arr); g_assert (ic->rank == 1); if (idxs->bounds != NULL || idxs->max_length != ac->rank) { @@ -485,7 +518,7 @@ ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value, return; } - ind = (gint32 *)idxs->vector; + ind = (gint32 *) idxs->vector; if (arr->bounds == NULL) { if (*ind < 0 || *ind >= arr->max_length) { @@ -494,22 +527,20 @@ ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value, } ves_icall_System_Array_SetValueImpl (arr, value, *ind); - return; - } - - for (i = 0; i < ac->rank; i++) - if ((ind [i] < arr->bounds [i].lower_bound) || - (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) { - mono_set_pending_exception (mono_get_exception_index_out_of_range ()); - return; - } + } else { + for (i = 0; i < ac->rank; i++) + if ((ind [i] < arr->bounds [i].lower_bound) || + (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) { + mono_set_pending_exception (mono_get_exception_index_out_of_range ()); + return; + } - pos = ind [0] - arr->bounds [0].lower_bound; - for (i = 1; i < ac->rank; i++) - pos = pos * arr->bounds [i].length + ind [i] - - arr->bounds [i].lower_bound; + pos = ind [0] - arr->bounds [0].lower_bound; + for (i = 1; i < ac->rank; i++) + pos = pos * arr->bounds [i].length + ind [i] - arr->bounds [i].lower_bound; - ves_icall_System_Array_SetValueImpl (arr, value, pos); + ves_icall_System_Array_SetValueImpl (arr, value, pos); + } } ICALL_EXPORT MonoArray * From 999d6a94f6168aa6f90365cc210f8e618cee53e2 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 11 Jan 2016 16:16:04 +0000 Subject: [PATCH 18/20] [sgen] Remove DISABLE_CRITICAL_REGION as it's never defined --- mono/metadata/sgen-client-mono.h | 4 ---- mono/metadata/sgen-mono.c | 6 ------ mono/sgen/sgen-alloc.c | 4 +--- mono/sgen/sgen-cardtable.c | 20 ++++---------------- 4 files changed, 5 insertions(+), 29 deletions(-) diff --git a/mono/metadata/sgen-client-mono.h b/mono/metadata/sgen-client-mono.h index 71906968539f..2c0445c4a11d 100644 --- a/mono/metadata/sgen-client-mono.h +++ b/mono/metadata/sgen-client-mono.h @@ -675,8 +675,6 @@ extern MonoNativeTlsKey thread_info_key; #define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region) #endif -#ifndef DISABLE_CRITICAL_REGION - #ifdef HAVE_KW_THREAD #define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region #else @@ -691,8 +689,6 @@ extern MonoNativeTlsKey thread_info_key; */ #define EXIT_CRITICAL_REGION do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0) -#endif - #define SGEN_TV_DECLARE(name) gint64 name #define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks () #define SGEN_TV_ELAPSED(start,end) ((long)(end-start)) diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index a6382b896244..6522a173d1f8 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -2997,7 +2997,6 @@ mono_handle_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_leng { MonoObject *obj; -#ifndef DISABLE_CRITICAL_REGION ENTER_CRITICAL_REGION; obj = sgen_try_alloc_obj_nolock (vtable, size); if (obj) { @@ -3009,7 +3008,6 @@ mono_handle_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_leng goto done; } EXIT_CRITICAL_REGION; -#endif LOCK_GC; @@ -3056,7 +3054,6 @@ mono_handle_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_lengt { MonoObject *obj; -#ifndef DISABLE_CRITICAL_REGION ENTER_CRITICAL_REGION; obj = sgen_try_alloc_obj_nolock (vtable, size); if (obj) { @@ -3071,7 +3068,6 @@ mono_handle_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_lengt goto done; } EXIT_CRITICAL_REGION; -#endif LOCK_GC; @@ -3121,7 +3117,6 @@ mono_handle_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len, MonoEr { MonoObject *obj; -#ifndef DISABLE_CRITICAL_REGION ENTER_CRITICAL_REGION; obj = sgen_try_alloc_obj_nolock (vtable, size); if (obj) { @@ -3133,7 +3128,6 @@ mono_handle_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len, MonoEr goto done; } EXIT_CRITICAL_REGION; -#endif LOCK_GC; diff --git a/mono/sgen/sgen-alloc.c b/mono/sgen/sgen-alloc.c index 2a9a3d014105..f11a3d7bfc08 100644 --- a/mono/sgen/sgen-alloc.c +++ b/mono/sgen/sgen-alloc.c @@ -430,8 +430,6 @@ sgen_alloc_obj (GCVTable vtable, size_t size, MonoError *error) if (!SGEN_CAN_ALIGN_UP (size)) return NULL; -#ifndef DISABLE_CRITICAL_REGION - if (G_UNLIKELY (has_per_allocation_action)) { static int alloc_count; int current_alloc = InterlockedIncrement (&alloc_count); @@ -456,7 +454,7 @@ sgen_alloc_obj (GCVTable vtable, size_t size, MonoError *error) return res; } EXIT_CRITICAL_REGION; -#endif + LOCK_GC; res = sgen_alloc_obj_nolock (vtable, size); UNLOCK_GC; diff --git a/mono/sgen/sgen-cardtable.c b/mono/sgen/sgen-cardtable.c index b6e9479f1479..f88b933a68e4 100644 --- a/mono/sgen/sgen-cardtable.c +++ b/mono/sgen/sgen-cardtable.c @@ -119,19 +119,13 @@ sgen_card_table_wbarrier_value_copy (gpointer dest, gpointer src, int count, siz { size_t size = count * element_size; -#ifdef DISABLE_CRITICAL_REGION - LOCK_GC; -#else TLAB_ACCESS_INIT; ENTER_CRITICAL_REGION; -#endif + mono_gc_memmove_atomic (dest, src, size); sgen_card_table_mark_range ((mword)dest, size); -#ifdef DISABLE_CRITICAL_REGION - UNLOCK_GC; -#else + EXIT_CRITICAL_REGION; -#endif } static void @@ -139,20 +133,14 @@ sgen_card_table_wbarrier_object_copy (GCObject* obj, GCObject *src) { size_t size = sgen_client_par_object_get_size (SGEN_LOAD_VTABLE_UNCHECKED (obj), obj); -#ifdef DISABLE_CRITICAL_REGION - LOCK_GC; -#else TLAB_ACCESS_INIT; ENTER_CRITICAL_REGION; -#endif + mono_gc_memmove_aligned ((char*)obj + SGEN_CLIENT_OBJECT_HEADER_SIZE, (char*)src + SGEN_CLIENT_OBJECT_HEADER_SIZE, size - SGEN_CLIENT_OBJECT_HEADER_SIZE); sgen_card_table_mark_range ((mword)obj, size); -#ifdef DISABLE_CRITICAL_REGION - UNLOCK_GC; -#else + EXIT_CRITICAL_REGION; -#endif } static void From b22fde14f6a982df782baf7d8bc10946bf0cace3 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 12 Jan 2016 12:10:54 +0000 Subject: [PATCH 19/20] fixup! [handle] Add GC alloc function --- mono/metadata/boehm-gc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 0cc91309ef5c..feb0de30f354 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -1873,29 +1873,29 @@ mono_gchandle_free_domain (MonoDomain *domain) MONO_HANDLE_TYPE (MonoObject) mono_handle_gc_alloc_obj (MonoVTable *vtable, size_t size, MonoError *error) { - mono_error_init (error); - return MONO_HANDLE_NEW (MonoObject, mono_gc_alloc_obj (vtable, size)); + /* FIXME: in case of OOM, an exception will be thown and we will unwind the native stack */ + g_error ("not implemented"); } MONO_HANDLE_TYPE (MonoArray) mono_handle_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length, MonoError *error) { - mono_error_init (error); - return MONO_HANDLE_NEW (MonoArray, mono_gc_alloc_vector (vtable, size, max_length)); + /* FIXME: in case of OOM, an exception will be thown and we will unwind the native stack */ + g_error ("not implemented"); } MONO_HANDLE_TYPE (MonoArray) mono_handle_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size, MonoError *error) { - mono_error_init (error); - return MONO_HANDLE_NEW (MonoArray, mono_gc_alloc_array (vtable, size, max_length, bounds_size)); + /* FIXME: in case of OOM, an exception will be thown and we will unwind the native stack */ + g_error ("not implemented"); } MONO_HANDLE_TYPE (MonoString) mono_handle_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len, MonoError *error) { - mono_error_init (error); - return MONO_HANDLE_NEW (MonoString, mono_gc_alloc_string (vtable, size, len)); + /* FIXME: in case of OOM, an exception will be thown and we will unwind the native stack */ + g_error ("not implemented"); } #endif /* no Boehm GC */ From 52eb4442f6e99af51ee74d2b248d94a0a707244b Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Tue, 12 Jan 2016 15:29:16 -0500 Subject: [PATCH 20/20] [handle] Implement mono_handle_array_nullable_init () --- mono/metadata/object.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 3d62f083e558..e6d3848013ae 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -7347,5 +7347,24 @@ mono_handle_array_nullable_box (MonoDomain *domain, MonoClass *element_class, MO void mono_handle_array_nullable_init (MonoDomain *domain, MonoClass *element_class, MONO_HANDLE_TYPE (MonoArray) arr_handle, gint32 pos, MONO_HANDLE_TYPE (MonoObject) value_handle, MonoError *error) { - g_error ("not implemented"); + MonoClass *param_class; + gsize element_size; + + mono_error_init (error); + + param_class = element_class->cast_class; + + mono_class_setup_fields_locking (element_class); + g_assert (element_class->fields_inited); + + g_assert (mono_class_from_mono_type (element_class->fields [0].type) == param_class); + g_assert (mono_class_from_mono_type (element_class->fields [1].type) == mono_defaults.boolean_class); + + element_size = mono_class_instance_size (element_class) - sizeof (MonoObject); + + MONO_PREPARE_GC_CRITICAL_REGION; + mono_nullable_init (mono_handle_array_addr_with_size (arr_handle, element_size, pos), + mono_handle_obj(value_handle), + element_class); + MONO_FINISH_GC_CRITICAL_REGION; }