Merge pull request #4555 from alexanderkyte/finished_mangler
[mono.git] / mono / mini / interp / interp.c
index 0f0223b421c1aa79f876df137cde9ca6adf4ed6f..be96452e8e577658999871b4186947c971439dce 100644 (file)
@@ -36,7 +36,7 @@
 
 /* trim excessive headers */
 #include <mono/metadata/image.h>
-#include <mono/metadata/assembly.h>
+#include <mono/metadata/assembly-internals.h>
 #include <mono/metadata/cil-coff.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/tabledefs.h>
@@ -325,6 +325,11 @@ get_virtual_method (MonoDomain *domain, RuntimeMethod *runtime_method, MonoObjec
                virtual_method = mono_class_inflate_generic_method_checked (virtual_method, &context, &error);
                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
        }
+
+       if (virtual_method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
+               virtual_method = mono_marshal_get_synchronized_wrapper (virtual_method);
+       }
+
        RuntimeMethod *virtual_runtime_method = mono_interp_get_runtime_method (domain, virtual_method, &error);
        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
        return virtual_runtime_method;
@@ -691,8 +696,6 @@ interp_walk_stack_with_ctx (MonoInternalStackWalk func, MonoContext *ctx, MonoUn
                        return;
                frame = frame->parent;
        }
-
-       g_assert (0);
 }
 
 static MonoPIFunc mono_interp_enter_icall_trampoline = NULL;
@@ -935,6 +938,15 @@ ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
 
        mono_class_init (method->klass);
 
+       if (method->klass == mono_defaults.array_class) {
+               if (!strcmp (method->name, "UnsafeMov")) {
+                       /* TODO: layout checks */
+                       MonoType *mt = mono_method_signature (method)->ret;
+                       stackval_from_data (mt, frame->retval, (char *) frame->stack_args, FALSE);
+                       return;
+               }
+       }
+
        isinst_obj = mono_object_isinst_checked (obj, mono_defaults.array_class, &error);
        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
        if (obj && isinst_obj) {
@@ -1225,6 +1237,8 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
        jmp_buf env;
 
        error_init (error);
+       if (exc)
+               *exc = NULL;
 
        frame.ex = NULL;
 
@@ -1267,13 +1281,32 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
                break;
        case MONO_TYPE_VALUETYPE:
                retval = mono_object_new_checked (context->domain, klass, error);
-               ret = ((char*)retval) + sizeof (MonoObject);
+               ret = mono_object_unbox (retval);
                if (!sig->ret->data.klass->enumtype)
                        result.data.vt = ret;
+               else
+                       result.data.vt = alloca (mono_class_instance_size (klass));
+               break;
+       case MONO_TYPE_GENERICINST:
+               if (!MONO_TYPE_IS_REFERENCE (sig->ret)) {
+                       retval = mono_object_new_checked (context->domain, klass, error);
+                       ret = mono_object_unbox (retval);
+                       if (!sig->ret->data.klass->enumtype)
+                               result.data.vt = ret;
+                       else
+                               result.data.vt = alloca (mono_class_instance_size (klass));
+               } else {
+                       isobject = 1;
+               }
+               break;
+
+       case MONO_TYPE_PTR:
+               retval = mono_object_new_checked (context->domain, mono_defaults.int_class, error);
+               ret = mono_object_unbox (retval);
                break;
        default:
                retval = mono_object_new_checked (context->domain, klass, error);
-               ret = ((char*)retval) + sizeof (MonoObject);
+               ret = mono_object_unbox (retval);
                break;
        }
 
@@ -1324,10 +1357,12 @@ handle_enum:
                        }
                        break;
                case MONO_TYPE_STRING:
+               case MONO_TYPE_PTR:
                case MONO_TYPE_CLASS:
                case MONO_TYPE_ARRAY:
                case MONO_TYPE_SZARRAY:
                case MONO_TYPE_OBJECT:
+               case MONO_TYPE_GENERICINST:
                        args [a_index].data.p = params [i];
                        break;
                default:
@@ -1460,27 +1495,35 @@ static mono_mutex_t create_method_pointer_mutex;
 
 static GHashTable *method_pointer_hash = NULL;
 
-static MonoMethod *method_pointers [2] = {0};
+#define TRAMPS_USED 8
 
-static MonoObject *
-mp_tramp_0 (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) {
-       MonoError error;
-       void *params_real[] = {this_obj, &params, &exc, &compiled_method};
-       MonoObject *ret = mono_interp_runtime_invoke (method_pointers [0], NULL, params_real, NULL, &error);
-       mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-       return ret;
-}
+static MonoMethod *method_pointers [TRAMPS_USED] = {0};
+
+#define GEN_METHOD_PTR_TRAMP(num) \
+               static MonoObject * mp_tramp_ ## num (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) { \
+                       MonoError error; \
+                       void *params_real[] = {this_obj, &params, &exc, &compiled_method}; \
+                       MonoObject *ret = mono_interp_runtime_invoke (method_pointers [num], NULL, params_real, NULL, &error); \
+                       mono_error_cleanup (&error); \
+                       return ret; \
+               }
 
-static MonoObject *
-mp_tramp_1 (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) {
-       MonoError error;
-       void *params_real[] = {this_obj, &params, &exc, &compiled_method};
-       MonoObject *ret = mono_interp_runtime_invoke (method_pointers [1], NULL, params_real, NULL, &error);
-       mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-       return ret;
-}
 
-gpointer *mp_tramps[] = {(gpointer) mp_tramp_0, (gpointer) mp_tramp_1};
+GEN_METHOD_PTR_TRAMP (0);
+GEN_METHOD_PTR_TRAMP (1);
+GEN_METHOD_PTR_TRAMP (2);
+GEN_METHOD_PTR_TRAMP (3);
+GEN_METHOD_PTR_TRAMP (4);
+GEN_METHOD_PTR_TRAMP (5);
+GEN_METHOD_PTR_TRAMP (6);
+GEN_METHOD_PTR_TRAMP (7);
+
+#undef GEN_METHOD_PTR_TRAMP
+
+gpointer *mp_tramps[TRAMPS_USED] = {
+       (gpointer) mp_tramp_0, (gpointer) mp_tramp_1, (gpointer) mp_tramp_2, (gpointer) mp_tramp_3,
+       (gpointer) mp_tramp_4, (gpointer) mp_tramp_5, (gpointer) mp_tramp_6, (gpointer) mp_tramp_7
+};
 
 static int tramps_used = 0;
 
@@ -1516,7 +1559,7 @@ mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
        }               
        else {
                g_assert (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE);
-               g_assert (tramps_used < 2);
+               g_assert (tramps_used < TRAMPS_USED);
 
                /* FIXME: needs locking */
                method_pointers [tramps_used] = method;
@@ -1579,23 +1622,13 @@ static int opcode_counts[512];
 #define MINT_IN_DEFAULT default:
 #endif
 
-/* 
- * Defining this causes register allocation errors in some versions of gcc:
- * error: unable to find a register to spill in class `SIREG'
- */
-/* #define MINT_USE_DEDICATED_IP_REG */
-
 static void 
 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
 {
        MonoInvocation child_frame;
        GSList *finally_ips = NULL;
        const unsigned short *endfinally_ip = NULL;
-#if defined(__GNUC__) && defined (i386) && defined (MINT_USE_DEDICATED_IP_REG)
-       register const unsigned short *ip asm ("%esi");
-#else
-       register const unsigned short *ip;
-#endif
+       const unsigned short *ip = NULL;
        register stackval *sp;
        RuntimeMethod *rtm;
 #if DEBUG_INTERP
@@ -3777,13 +3810,6 @@ array_constructed:
                        MINT_IN_BREAK;
                }
 
-               MINT_IN_CASE(MINT_LDTHISA)
-                       g_error ("should not happen");
-                       // sp->data.p = &frame->obj;
-                       ++ip;
-                       ++sp; 
-                       MINT_IN_BREAK;
-
 #define LDARG(datamem, argtype) \
        sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
        ip += 2; \
@@ -4070,8 +4096,9 @@ array_constructed:
                }
 die_on_ex:
                ex_obj = (MonoObject*)frame->ex;
-               mono_unhandled_exception (ex_obj);
-               exit (1);
+               MonoJitTlsData *jit_tls = (MonoJitTlsData *) mono_tls_get_jit_tls ();
+               jit_tls->abort_func (ex_obj);
+               g_assert_not_reached ();
        }
        handle_finally:
        {
@@ -4526,7 +4553,7 @@ mono_interp_regression_list (int verbose, int count, char *images [])
        
        total_run = total = 0;
        for (i = 0; i < count; ++i) {
-               MonoAssembly *ass = mono_assembly_open (images [i], NULL);
+               MonoAssembly *ass = mono_assembly_open_predicate (images [i], FALSE, FALSE, NULL, NULL, NULL);
                if (!ass) {
                        g_warning ("failed to load assembly: %s", images [i]);
                        continue;