Add LinkerDescriptor
[mono.git] / mono / metadata / marshal.c
index 51b2e470b1fd5f50839e70158a33bf4bb06b1a05..214b81f1adff43d7ec83d935284c40bc8a9d94bd 100644 (file)
@@ -215,6 +215,9 @@ mono_icall_start (HandleStackMark *stackmark, MonoError *error);
 static void
 mono_icall_end (MonoThreadInfo *info, HandleStackMark *stackmark, MonoError *error);
 
+static MonoObjectHandle
+mono_icall_handle_new_full (gpointer rawobj, MonoBoolean interior);
+
 /* Lazy class loading functions */
 static GENERATE_GET_CLASS_WITH_CACHE (string_builder, "System.Text", "StringBuilder");
 static GENERATE_GET_CLASS_WITH_CACHE (date_time, "System", "DateTime");
@@ -297,6 +300,19 @@ ves_icall_mono_string_to_utf8 (MonoString *str)
        return result;
 }
 
+static MonoString*
+ves_icall_string_new_wrapper (const char *text)
+{
+       if (text) {
+               MonoError error;
+               MonoString *res = mono_string_new_checked (mono_domain_get (), text, &error);
+               mono_error_set_pending_exception (&error);
+               return res;
+       }
+
+       return NULL;
+}
+
 void
 mono_marshal_init (void)
 {
@@ -315,6 +331,7 @@ mono_marshal_init (void)
                register_icall (mono_string_from_byvalstr, "mono_string_from_byvalstr", "obj ptr int", FALSE);
                register_icall (mono_string_from_byvalwstr, "mono_string_from_byvalwstr", "obj ptr int", FALSE);
                register_icall (mono_string_new_wrapper, "mono_string_new_wrapper", "obj ptr", FALSE);
+               register_icall (ves_icall_string_new_wrapper, "ves_icall_string_new_wrapper", "obj ptr", FALSE);
                register_icall (mono_string_new_len_wrapper, "mono_string_new_len_wrapper", "obj ptr int", FALSE);
                register_icall (ves_icall_mono_string_to_utf8, "ves_icall_mono_string_to_utf8", "ptr obj", FALSE);
                register_icall (mono_string_to_utf8str, "mono_string_to_utf8str", "ptr obj", FALSE);
@@ -348,8 +365,6 @@ mono_marshal_init (void)
                register_icall (mono_struct_delete_old, "mono_struct_delete_old", "void ptr ptr", FALSE);
                register_icall (mono_delegate_begin_invoke, "mono_delegate_begin_invoke", "object object ptr", FALSE);
                register_icall (mono_delegate_end_invoke, "mono_delegate_end_invoke", "object object ptr", FALSE);
-               register_icall (mono_context_get, "mono_context_get", "object", FALSE);
-               register_icall (mono_context_set, "mono_context_set", "void object", FALSE);
                register_icall (mono_gc_wbarrier_generic_nostore, "wb_generic", "void ptr", FALSE);
                register_icall (mono_gchandle_get_target, "mono_gchandle_get_target", "object int32", TRUE);
                register_icall (mono_gchandle_new, "mono_gchandle_new", "uint32 object bool", TRUE);
@@ -361,7 +376,7 @@ mono_marshal_init (void)
                register_icall (mono_threads_detach_coop, "mono_threads_detach_coop", "void ptr ptr", TRUE);
                register_icall (mono_icall_start, "mono_icall_start", "ptr ptr ptr", TRUE);
                register_icall (mono_icall_end, "mono_icall_end", "void ptr ptr ptr", TRUE);
-               register_icall (mono_handle_new_full, "mono_handle_new_full", "ptr ptr bool", TRUE);
+               register_icall (mono_icall_handle_new_full, "mono_icall_handle_new_full", "ptr ptr bool", TRUE);
 
                mono_cominterop_init ();
                mono_remoting_init ();
@@ -1463,7 +1478,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
                } else {
                        mono_mb_emit_ldloc (mb, 1);
                        mono_mb_emit_ldloc (mb, 0);
-                       mono_mb_emit_icall (mb, mono_string_new_wrapper);
+                       mono_mb_emit_icall (mb, ves_icall_string_new_wrapper);
                }
                mono_mb_emit_byte (mb, CEE_STIND_REF);          
                break;
@@ -1487,7 +1502,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
 #ifdef TARGET_WIN32
                mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
 #else
-               mono_mb_emit_icall (mb, mono_string_new_wrapper);
+               mono_mb_emit_icall (mb, ves_icall_string_new_wrapper);
 #endif
                mono_mb_emit_byte (mb, CEE_STIND_REF);  
                break;
@@ -1498,7 +1513,7 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
                mono_mb_emit_ldloc (mb, 1);
                mono_mb_emit_ldloc (mb, 0);
                mono_mb_emit_byte (mb, CEE_LDIND_I);
-               mono_mb_emit_icall (mb, mono_string_new_wrapper);
+               mono_mb_emit_icall (mb, ves_icall_string_new_wrapper);
                mono_mb_emit_byte (mb, CEE_STIND_REF);          
                break;
        case MONO_MARSHAL_CONV_STR_LPWSTR:
@@ -1621,11 +1636,11 @@ conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
                return ves_icall_mono_string_from_utf16;
        case MONO_MARSHAL_CONV_LPTSTR_STR:
                *ind_store_type = CEE_STIND_REF;
-               return mono_string_new_wrapper;
+               return ves_icall_string_new_wrapper;
        case MONO_MARSHAL_CONV_UTF8STR_STR:
        case MONO_MARSHAL_CONV_LPSTR_STR:
                *ind_store_type = CEE_STIND_REF;
-               return mono_string_new_wrapper;
+               return ves_icall_string_new_wrapper;
        case MONO_MARSHAL_CONV_STR_LPTSTR:
 #ifdef TARGET_WIN32
                return mono_marshal_string_to_utf16;
@@ -3241,10 +3256,13 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
                        if (is_ok (&inner_error)) {
                                char  *tmp;
                                tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
-                               g_free (strace);        
-                               MONO_OBJECT_SETREF (((MonoException*)exc), stack_trace, mono_string_new (domain, tmp));
+                               g_free (strace);
+                               MonoString *tmp_str = mono_string_new_checked (domain, tmp, &inner_error);
                                g_free (tmp);
-                       } else
+                               if (is_ok (&inner_error))
+                                       MONO_OBJECT_SETREF (((MonoException*)exc), stack_trace, tmp_str);
+                       };
+                       if (!is_ok (&inner_error))
                                mono_error_cleanup (&inner_error); /* no stack trace, but at least throw the original exception */
                }
                mono_set_pending_exception ((MonoException*)exc);
@@ -8090,7 +8108,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                                /* TODO support adding wrappers to non-static struct methods */
                                g_assert (!mono_class_is_valuetype(mono_method_get_class (method)));
                                mono_mb_emit_byte (mb, CEE_LDC_I4_0);
-                               mono_mb_emit_icall (mb, mono_handle_new_full);
+                               mono_mb_emit_icall (mb, mono_icall_handle_new_full);
                        }
                        for (i = 0; i < sig->param_count; i++) {
                                /* load each argument. references into the managed heap get wrapped in handles */
@@ -8103,13 +8121,13 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                                        /* argI = mono_handle_new_full (argI_raw, FALSE) */
                                        mono_mb_emit_ldarg (mb, j);
                                        mono_mb_emit_byte (mb, CEE_LDC_I4_0);
-                                       mono_mb_emit_icall (mb, mono_handle_new_full);
+                                       mono_mb_emit_icall (mb, mono_icall_handle_new_full);
                                        break;
                                case ICALL_HANDLES_WRAP_OBJ_INOUT:
                                        /* handleI = argI = mono_handle_new_full (NULL, FALSE) */
                                        mono_mb_emit_byte (mb, CEE_LDNULL);
                                        mono_mb_emit_byte (mb, CEE_LDC_I4_0);
-                                       mono_mb_emit_icall (mb, mono_handle_new_full);
+                                       mono_mb_emit_icall (mb, mono_icall_handle_new_full);
                                        /* tmp = argI */
                                        mono_mb_emit_byte (mb, CEE_DUP);
                                        /* handleI = tmp */
@@ -8120,7 +8138,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
                                        mono_mb_emit_ldarg (mb, j);
                                        mono_mb_emit_byte (mb, CEE_DUP);
                                        mono_mb_emit_byte (mb, CEE_LDC_I4_1);
-                                       mono_mb_emit_icall (mb, mono_handle_new_full);
+                                       mono_mb_emit_icall (mb, mono_icall_handle_new_full);
                                        mono_mb_emit_byte (mb, CEE_POP);
 #if 0
                                        fprintf (stderr, " Method %s.%s.%s has byref valuetype argument %d\n", method->klass->name_space, method->klass->name, method->name, i);
@@ -9662,13 +9680,14 @@ enum {
        STELEMREF_OBJECT, /*no check at all*/
        STELEMREF_SEALED_CLASS, /*check vtable->klass->element_type */
        STELEMREF_CLASS, /*only the klass->parents check*/
+       STELEMREF_CLASS_SMALL_IDEPTH, /* like STELEMREF_CLASS bit without the idepth check */
        STELEMREF_INTERFACE, /*interfaces without variant generic arguments. */
        STELEMREF_COMPLEX, /*arrays, MBR or types with variant generic args - go straight to icalls*/
        STELEMREF_KIND_COUNT
 };
 
 static const char *strelemref_wrapper_name[] = {
-       "object", "sealed_class", "class", "interface", "complex"
+       "object", "sealed_class", "class", "class_small_idepth", "interface", "complex"
 };
 
 static gboolean
@@ -9701,6 +9720,9 @@ get_virtual_stelemref_kind (MonoClass *element_class)
                return STELEMREF_COMPLEX;
        if (mono_class_is_sealed (element_class))
                return STELEMREF_SEALED_CLASS;
+       if (element_class->idepth <= MONO_DEFAULT_SUPERTABLE_SIZE)
+               return STELEMREF_CLASS_SMALL_IDEPTH;
+
        return STELEMREF_CLASS;
 }
 
@@ -10015,6 +10037,76 @@ get_virtual_stelemref_wrapper (int kind)
                mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL);
                break;
        }
+
+       case STELEMREF_CLASS_SMALL_IDEPTH:
+               /*
+               the method:
+               <ldelema (bound check)>
+               if (!value)
+                       goto do_store;
+
+               aklass = array->vtable->klass->element_class;
+               vklass = value->vtable->klass;
+
+               if (vklass->supertypes [aklass->idepth - 1] != aklass)
+                       goto do_exception;
+
+               do_store:
+                       *array_slot_addr = value;
+                       return;
+
+               long:
+                       throw new ArrayTypeMismatchException ();
+               */
+               aklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+               vklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+               array_slot_addr = mono_mb_add_local (mb, &mono_defaults.object_class->this_arg);
+
+               /* ldelema (implicit bound check) */
+               load_array_element_address (mb);
+               mono_mb_emit_stloc (mb, array_slot_addr);
+
+               /* if (!value) goto do_store */
+               mono_mb_emit_ldarg (mb, 2);
+               b1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+               /* aklass = array->vtable->klass->element_class */
+               load_array_class (mb, aklass);
+
+               /* vklass = value->vtable->klass */
+               load_value_class (mb, vklass);
+
+               /* if (vklass->supertypes [aklass->idepth - 1] != aklass) goto failure */
+               mono_mb_emit_ldloc (mb, vklass);
+               mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoClass, supertypes));
+               mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+               mono_mb_emit_ldloc (mb, aklass);
+               mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoClass, idepth));
+               mono_mb_emit_byte (mb, CEE_LDIND_U2);
+               mono_mb_emit_icon (mb, 1);
+               mono_mb_emit_byte (mb, CEE_SUB);
+               mono_mb_emit_icon (mb, sizeof (void*));
+               mono_mb_emit_byte (mb, CEE_MUL);
+               mono_mb_emit_byte (mb, CEE_ADD);
+               mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+               mono_mb_emit_ldloc (mb, aklass);
+               b4 = mono_mb_emit_branch (mb, CEE_BNE_UN);
+
+               /* do_store: */
+               mono_mb_patch_branch (mb, b1);
+               mono_mb_emit_ldloc (mb, array_slot_addr);
+               mono_mb_emit_ldarg (mb, 2);
+               mono_mb_emit_byte (mb, CEE_STIND_REF);
+               mono_mb_emit_byte (mb, CEE_RET);
+
+               /* do_exception: */
+               mono_mb_patch_branch (mb, b4);
+
+               mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL);
+               break;
+
        case STELEMREF_INTERFACE:
                /*Mono *klass;
                MonoVTable *vt;
@@ -10841,13 +10933,14 @@ ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer s
        memcpy (dest_addr, src, length * element_size);
 }
 
-MonoString *
-ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
+MonoStringHandle
+ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr, MonoError *error)
 {
+       error_init (error);
        if (ptr == NULL)
-               return NULL;
+               return MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
        else
-               return mono_string_new (mono_domain_get (), ptr);
+               return mono_string_new_handle (mono_domain_get (), ptr, error);
 }
 
 MonoString *
@@ -12222,3 +12315,13 @@ mono_icall_end (MonoThreadInfo *info, HandleStackMark *stackmark, MonoError *err
        if (G_UNLIKELY (!is_ok (error)))
                mono_error_set_pending_exception (error);
 }
+
+static MonoObjectHandle
+mono_icall_handle_new_full (gpointer rawobj, MonoBoolean interior)
+{
+#ifdef MONO_HANDLE_TRACK_OWNER
+       return mono_handle_new_full (rawobj, interior, "<marshal args>");
+#else
+       return mono_handle_new_full (rawobj, interior);
+#endif
+}