Merge pull request #3199 from lambdageek/dev/proxy-setter
[mono.git] / mono / mini / aot-runtime.c
index 88069414ca2422a94f3bc54face7107727666dd7..2f818c6821cef511e12f349739f013f8de8e7116 100644 (file)
@@ -56,6 +56,7 @@
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-digest.h>
+#include <mono/utils/mono-threads-coop.h>
 
 #include "mini.h"
 #include "seq-points.h"
@@ -921,17 +922,14 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        }
                        break;
                }
-               case MONO_WRAPPER_LDFLD_REMOTE:
-                       ref->method = mono_marshal_get_ldfld_remote_wrapper (NULL);
-                       break;
-               case MONO_WRAPPER_STFLD_REMOTE:
-                       ref->method = mono_marshal_get_stfld_remote_wrapper (NULL);
-                       break;
 #endif
                case MONO_WRAPPER_ALLOC: {
                        int atype = decode_value (p, &p);
+                       ManagedAllocatorVariant variant =
+                               mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS ?
+                               MANAGED_ALLOCATOR_SLOW_PATH : MANAGED_ALLOCATOR_REGULAR;
 
-                       ref->method = mono_gc_get_managed_allocator_by_type (atype, !!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS));
+                       ref->method = mono_gc_get_managed_allocator_by_type (atype, variant);
                        if (!ref->method) {
                                mono_error_set_bad_image_name (error, module->aot_name, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
                                return FALSE;
@@ -1781,17 +1779,6 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, guint8 *blob, char
                msg = g_strdup_printf ("not compiled with --aot=llvmonly");
                usable = FALSE;
        }
-#ifdef TARGET_ARM
-       /* mono_arch_find_imt_method () requires this */
-       if ((info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
-               msg = g_strdup_printf ("compiled against LLVM");
-               usable = FALSE;
-       }
-       if (!(info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && mono_use_llvm) {
-               msg = g_strdup_printf ("not compiled against LLVM");
-               usable = FALSE;
-       }
-#endif
        if (mini_get_debug_options ()->mdb_optimizations && !(info->flags & MONO_AOT_FILE_FLAG_DEBUG) && !full_aot) {
                msg = g_strdup_printf ("not compiled for debugging");
                usable = FALSE;
@@ -2012,6 +1999,9 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                find_symbol (sofile, globals, "mono_aot_file_info", (gpointer*)&info);
        }
 
+       // Copy aotid to MonoImage
+       memcpy(&assembly->image->aotid, info->aotid, 16);
+
        if (version_symbol) {
                /* Old file format */
                version = atoi (version_symbol);
@@ -2400,9 +2390,8 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin
 }      
 
 gpointer
-mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot, MonoError *error)
 {
-       MonoError error;
        int i;
        MonoClass *klass = vtable->klass;
        MonoAotModule *amodule = (MonoAotModule *)klass->image->aot_module;
@@ -2411,6 +2400,10 @@ mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int sl
        gboolean err;
        MethodRef ref;
        gboolean res;
+       gpointer addr;
+       MonoError inner_error;
+
+       mono_error_init (error);
 
        if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !amodule)
                return NULL;
@@ -2423,12 +2416,12 @@ mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int sl
                return NULL;
 
        for (i = 0; i < slot; ++i) {
-               decode_method_ref (amodule, &ref, p, &p, &error);
-               mono_error_cleanup (&error); /* FIXME don't swallow the error */
+               decode_method_ref (amodule, &ref, p, &p, &inner_error);
+               mono_error_cleanup (&inner_error); /* FIXME don't swallow the error */
        }
 
-       res = decode_method_ref (amodule, &ref, p, &p, &error);
-       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+       res = decode_method_ref (amodule, &ref, p, &p, &inner_error);
+       mono_error_cleanup (&inner_error); /* FIXME don't swallow the error */
        if (!res)
                return NULL;
        if (ref.no_aot_trampoline)
@@ -2437,7 +2430,8 @@ mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int sl
        if (mono_metadata_token_index (ref.token) == 0 || mono_metadata_token_table (ref.token) != MONO_TABLE_METHOD)
                return NULL;
 
-       return mono_aot_get_method_from_token (domain, ref.image, ref.token);
+       addr = mono_aot_get_method_from_token (domain, ref.image, ref.token, error);
+       return addr;
 }
 
 gboolean
@@ -4254,28 +4248,36 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        return FALSE;
 }
 
+static void
+init_llvmonly_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context)
+{
+       gboolean res;
+       MonoError error;
+
+       res = init_method (amodule, method_index, method, init_class, context, &error);
+       if (!is_ok (&error)) {
+               MonoException *ex = mono_error_convert_to_exception (&error);
+               /* Its okay to raise in llvmonly mode */
+               if (ex)
+                       mono_llvm_throw_exception ((MonoObject*)ex);
+       }
+}
+
 void
 mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
 {
        MonoAotModule *amodule = (MonoAotModule *)aot_module;
-       gboolean res;
-       MonoError error;
 
-       res = init_method (amodule, method_index, NULL, NULL, NULL, &error);
-       // FIXME: Pass the exception up to the caller ?
-       /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       init_llvmonly_method (amodule, method_index, NULL, NULL, NULL);
 }
 
 void
 mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this_obj)
 {
        MonoAotModule *amodule = (MonoAotModule *)aot_module;
-       gboolean res;
        MonoClass *klass;
        MonoGenericContext *context;
        MonoMethod *method;
-       MonoError error;
 
        // FIXME:
        g_assert (this_obj);
@@ -4289,19 +4291,15 @@ mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, Mo
        context = mono_method_get_context (method);
        g_assert (context);
 
-       res = init_method (amodule, method_index, NULL, klass, context, &error);
-       /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       init_llvmonly_method (amodule, method_index, NULL, klass, context);
 }
 
 void
 mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
 {
        MonoAotModule *amodule = (MonoAotModule *)aot_module;
-       gboolean res;
        MonoGenericContext context = { NULL, NULL };
        MonoClass *klass = rgctx->class_vtable->klass;
-       MonoError error;
 
        if (klass->generic_class)
                context.class_inst = klass->generic_class->context.class_inst;
@@ -4309,20 +4307,16 @@ mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index,
                context.class_inst = klass->generic_container->context.class_inst;
        context.method_inst = rgctx->method_inst;
 
-       res = init_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context, &error);
-       /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       init_llvmonly_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context);
 }
 
 void
 mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable)
 {
        MonoAotModule *amodule = (MonoAotModule *)aot_module;
-       gboolean res;
        MonoClass *klass;
        MonoGenericContext *context;
        MonoMethod *method;
-       MonoError error;
 
        klass = vtable->klass;
 
@@ -4334,9 +4328,7 @@ mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index,
        context = mono_method_get_context (method);
        g_assert (context);
 
-       res = init_method (amodule, method_index, NULL, klass, context, &error);
-       /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       init_llvmonly_method (amodule, method_index, NULL, klass, context);
 }
 
 /*
@@ -4355,8 +4347,9 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
        MonoAotModule *amodule = (MonoAotModule *)klass->image->aot_module;
        guint8 *code;
        gboolean cache_result = FALSE;
+       MonoError inner_error;
 
-       mono_error_ok (error);
+       mono_error_init (error);
 
        if (domain != mono_get_root_domain ())
                /* Non shared AOT code can't be used in other appdomains */
@@ -4389,7 +4382,7 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
         * remoting.
         */
        if (mono_aot_only && method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
-               return mono_aot_get_method (domain, mono_marshal_method_from_wrapper (method));
+               return mono_aot_get_method_checked (domain, mono_marshal_method_from_wrapper (method), error);
 
        g_assert (klass->inited);
 
@@ -4429,7 +4422,8 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && method->klass->rank && strstr (method->name, "System.Collections.Generic")) {
                        MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
 
-                       code = (guint8 *)mono_aot_get_method (domain, m);
+                       code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+                       mono_error_cleanup (&inner_error);
                        if (code)
                                return code;
                }
@@ -4440,7 +4434,6 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                 * an out parameter, so the managed-to-native wrappers can share the same code.
                 */
                if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass == mono_defaults.array_class && !strcmp (method->name, "GetGenericValueImpl")) {
-                       MonoError error;
                        MonoMethod *m;
                        MonoGenericContext ctx;
                        MonoType *args [16];
@@ -4456,15 +4449,16 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                        args [0] = &mono_defaults.object_class->byval_arg;
                        ctx.method_inst = mono_metadata_get_generic_inst (1, args);
 
-                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, error), TRUE, TRUE);
                        if (!m)
-                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (error)); /* FIXME don't swallow the error */
 
                        /* 
                         * Get the code for the <object> instantiation which should be emitted into
                         * the mscorlib aot image by the AOT compiler.
                         */
-                       code = (guint8 *)mono_aot_get_method (domain, m);
+                       code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+                       mono_error_cleanup (&inner_error);
                        if (code)
                                return code;
                }
@@ -4475,7 +4469,6 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                        ((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1]))) ||
                         (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->ret)))) ||
                         (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1])))))) {
-                       MonoError error;
                        MonoMethod *m;
                        MonoGenericContext ctx;
                        MonoType *args [16];
@@ -4491,9 +4484,9 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                        args [0] = &mono_defaults.object_class->byval_arg;
                        ctx.method_inst = mono_metadata_get_generic_inst (1, args);
 
-                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, error), TRUE, TRUE);
                        if (!m)
-                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (error)); /* FIXME don't swallow the error */
 
                        /* Avoid recursion */
                        if (method == m)
@@ -4503,7 +4496,8 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                         * Get the code for the <object> instantiation which should be emitted into
                         * the mscorlib aot image by the AOT compiler.
                         */
-                       code = (guint8 *)mono_aot_get_method (domain, m);
+                       code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+                       mono_error_cleanup (&inner_error);
                        if (code)
                                return code;
                }
@@ -4515,13 +4509,22 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                        if (info->subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR) {
                                MonoMethod *array_method = info->d.array_accessor.method;
                                if (MONO_TYPE_IS_REFERENCE (&array_method->klass->element_class->byval_arg)) {
-                                       MonoClass *obj_array_class = mono_array_class_get (mono_defaults.object_class, 1);
+                                       int rank;
+
+                                       if (!strcmp (array_method->name, "Set"))
+                                               rank = mono_method_signature (array_method)->param_count - 1;
+                                       else if (!strcmp (array_method->name, "Get") || !strcmp (array_method->name, "Address"))
+                                               rank = mono_method_signature (array_method)->param_count;
+                                       else
+                                               g_assert_not_reached ();
+                                       MonoClass *obj_array_class = mono_array_class_get (mono_defaults.object_class, rank);
                                        MonoMethod *m = mono_class_get_method_from_name (obj_array_class, array_method->name, mono_method_signature (array_method)->param_count);
                                        g_assert (m);
 
                                        m = mono_marshal_get_array_accessor_wrapper (m);
                                        if (m != method) {
-                                               code = (guint8 *)mono_aot_get_method (domain, m);
+                                               code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+                                               mono_error_cleanup (&inner_error);
                                                if (code)
                                                        return code;
                                        }
@@ -4596,7 +4599,8 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
        MonoError error;
 
        gpointer res = mono_aot_get_method_checked (domain, method, &error);
-       mono_error_raise_exception (&error);
+       /* This is external only, so its ok to raise here */
+       mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
        return res;
 }
 
@@ -4605,20 +4609,20 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
  * method.
  */
 gpointer
-mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
+mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token, MonoError *error)
 {
        MonoAotModule *aot_module = (MonoAotModule *)image->aot_module;
        int method_index;
-       MonoError error;
        gpointer res;
 
+       mono_error_init (error);
+
        if (!aot_module)
                return NULL;
 
        method_index = mono_metadata_token_index (token) - 1;
 
-       res = load_method (domain, aot_module, image, NULL, token, method_index, &error);
-       mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+       res = load_method (domain, aot_module, image, NULL, token, method_index, error);
        return res;
 }
 
@@ -5825,6 +5829,14 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
        return NULL;
 }
 
+gpointer
+mono_aot_get_method_checked (MonoDomain *domain,
+                                                        MonoMethod *method, MonoError *error)
+{
+       mono_error_init (error);
+       return NULL;
+}
+
 gboolean
 mono_aot_is_got_entry (guint8 *code, guint8 *addr)
 {
@@ -5850,8 +5862,9 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 }
 
 gpointer
-mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
+mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token, MonoError *error)
 {
+       mono_error_init (error);
        return NULL;
 }
 
@@ -5873,8 +5886,10 @@ mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_
 }
 
 gpointer
-mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot, MonoError *error)
 {
+       mono_error_init (error);
+
        return NULL;
 }