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/boehm-gc.c b/mono/metadata/boehm-gc.c index 0bd92412414f..feb0de30f354 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) +{ + /* 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) +{ + /* 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) +{ + /* 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) +{ + /* 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 */ 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/handle-arena.h b/mono/metadata/handle-arena.h new file mode 100644 index 000000000000..99337f7c91dd --- /dev/null +++ b/mono/metadata/handle-arena.h @@ -0,0 +1,55 @@ +#ifndef __MONO_HANDLE_PRIVATE_H__ +#define __MONO_HANDLE_PRIVATE_H__ + +#include + +typedef struct _MonoHandleArena MonoHandleArena; + +gsize +mono_handle_arena_size (void); + +MonoHandle +mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj); + +MonoHandle +mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle); + +void +mono_handle_arena_stack_push (MonoHandleArena **arena_stack, MonoHandleArena *arena); + +void +mono_handle_arena_stack_pop (MonoHandleArena **arena_stack, MonoHandleArena *arena); + +void +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); + +#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)->__private_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__*/ diff --git a/mono/metadata/handle-private.h b/mono/metadata/handle-private.h deleted file mode 100644 index a991b9b47b09..000000000000 --- a/mono/metadata/handle-private.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __MONO_HANDLE_PRIVATE_H__ -#define __MONO_HANDLE_PRIVATE_H__ - -#include - -typedef struct _MonoHandleArena MonoHandleArena; - -gsize -mono_handle_arena_size (void); - -MonoHandle -mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj); - -MonoHandle -mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle); - -void -mono_handle_arena_stack_push (MonoHandleArena **arena_stack, MonoHandleArena *arena); - -void -mono_handle_arena_stack_pop (MonoHandleArena **arena_stack, MonoHandleArena *arena); - -void -mono_handle_arena_initialize (MonoHandleArena **arena_stack); - -void -mono_handle_arena_deinitialize (MonoHandleArena **arena_stack); - -#endif/*__MONO_HANDLE_PRIVATE_H__*/ diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index 885c723be733..e6a4899f50b7 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -11,11 +11,12 @@ #include #include -#include +#include #include #include #include #include +#include #define HANDLES_PER_CHUNK (16 - 2) @@ -34,9 +35,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; @@ -82,7 +81,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]; @@ -90,7 +89,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; @@ -105,16 +104,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 */ @@ -125,17 +114,7 @@ mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle) g_assert (arena); g_assert (arena->prev); - 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); + return handle_new (arena->prev, handle->__private_obj); } gsize @@ -190,8 +169,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); } } } @@ -200,25 +179,30 @@ 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* +mono_handle_arena_current (void) +{ + return (MonoHandleArena*) mono_thread_info_current ()->handle_arena; +} + +MonoHandleArena** +mono_handle_arena_current_addr (void) +{ + return (MonoHandleArena**) &mono_thread_info_current ()->handle_arena; +} diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 82fee80a0fb4..d911a967d792 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -13,17 +13,10 @@ #include #include -#include "object.h" -#include "class.h" -#include "class-internals.h" -#include "threads-types.h" - -#include "mono/utils/mono-threads-coop.h" - -G_BEGIN_DECLS - -typedef struct _MonoHandleStorage MonoHandleStorage; -typedef MonoHandleStorage* MonoHandle; +#include +#include +#include +#include /* * DO NOT ACCESS DIRECTLY @@ -32,47 +25,67 @@ 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 { - MonoObject *obj; -}; +typedef struct { + MonoObject *__private_obj; +} MonoHandleStorage; + +typedef MonoHandleStorage* MonoHandle; + +#include "handle-arena.h" + +G_BEGIN_DECLS + +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) +#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 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)->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 handle->obj->vtable->klass; + return mono_object_get_class (handle->__private_obj); } static inline MonoDomain* mono_handle_domain (MonoHandle handle) { - return handle->obj->vtable->domain; + return mono_object_get_domain (handle->__private_obj); } -#define MONO_HANDLE_TYPE_DECL(type) typedef struct { type *obj; } type ## HandleStorage ; \ +#define mono_handle_obj_is_null(handle) ((handle)->__private_obj == NULL) + +#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 { \ @@ -87,6 +100,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; \ @@ -102,26 +123,83 @@ 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; \ - 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) -/* handle arena specific functions */ +/* Some common handle types */ + +MONO_HANDLE_TYPE_DECL (MonoObject); -MonoHandle -mono_handle_new (MonoObject *rawptr); +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new (MonoDomain *domain, MonoClass *klass, MonoError *error); -MonoHandle -mono_handle_elevate (MonoHandle handle); +MONO_HANDLE_TYPE (MonoObject) +mono_handle_object_new_specific (MonoVTable *vtable, MonoError *error); -/* Some common handle types */ +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) +mono_handle_array_new (MonoDomain *domain, MonoClass *element_class, uintptr_t size, MonoError *error); + +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 (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/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/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 * 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/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/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; diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 5a5c31b3e6cb..e6d3848013ae 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. @@ -4920,14 +4950,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 (); - MonoClass *ac; + MONO_HANDLE_TYPE (MonoArray) arr_handle = mono_handle_array_new (domain, eclass, n, &error); - ac = mono_array_class_get (eclass, 1); - g_assert (ac); + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (arr_handle, arr); - return mono_array_new_specific (mono_class_vtable_full (domain, ac, TRUE), n); + 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 arr; } /** @@ -4941,25 +4984,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 +5018,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 +5087,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 +5149,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; + MONO_HANDLE_ARENA_POP_RETURN_UNSAFE (str_handle, str); - len = g_utf8_strlen (text, -1); - o = mono_string_new_size (domain, len); - str = mono_string_chars (o); - - 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 +6975,396 @@ mono_glist_to_array (GList *list, MonoClass *eclass) return res; } +/* 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 + * + * 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) +{ + 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; +} 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 8d3b7c137eb4..6522a173d1f8 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -34,8 +34,11 @@ #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" +#include "utils/mono-error-internals.h" #ifdef HEAVY_STATISTICS static guint64 stat_wbarrier_set_arrayref = 0; @@ -933,10 +936,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 +956,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 +976,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 +1736,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; -#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; + MONO_HANDLE_ARENA_PUSH (); - 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; } @@ -2276,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 (); } @@ -2291,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 @@ -2704,12 +2663,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 +2952,207 @@ 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; + + 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; + + 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; + + 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; + + 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; + + 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; + + 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..f11a3d7bfc08 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,16 +420,16 @@ 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; -#ifndef DISABLE_CRITICAL_REGION - if (G_UNLIKELY (has_per_allocation_action)) { static int alloc_count; int current_alloc = InterlockedIncrement (&alloc_count); @@ -452,12 +454,12 @@ sgen_alloc_obj (GCVTable vtable, size_t size) return res; } EXIT_CRITICAL_REGION; -#endif + LOCK_GC; 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 +468,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 +496,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-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 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 */ 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 () diff --git a/mono/utils/checked-build.c b/mono/utils/checked-build.c index 5c4fd4249e9a..35dc1773016d 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,20 +245,26 @@ 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) { - 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)); + if (state->in_gc_critical_region > 0) { + 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 83efd67c0548..b2e90d0469f0 100644 --- a/mono/utils/checked-build.h +++ b/mono/utils/checked-build.h @@ -83,12 +83,12 @@ 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() #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() 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 {