Add full-aot support for runtime invokes to array Get/Set methods.
[mono.git] / mono / interpreter / transform.c
index c09275e55effb0dc00c1eeff456fafbb6938a292..b47e594ef4959764748f33a6cc370aaaae7b55a9 100644 (file)
@@ -436,7 +436,7 @@ load_arg(TransformData *td, int n)
 {
        int mt;
        MonoClass *klass = NULL;
-       if (n == 0 && td->method->signature->hasthis) {
+       if (n == 0 && mono_method_signature (td->method)->hasthis) {
                if (td->method->klass->valuetype)
                        mt = MINT_TYPE_P;
                else {
@@ -446,12 +446,12 @@ load_arg(TransformData *td, int n)
                ADD_CODE(td, MINT_LDTHIS);
        } else {
                MonoType *type;
-               n -= td->method->signature->hasthis;
-               type = td->method->signature->params [n];
+               n -= mono_method_signature (td->method)->hasthis;
+               type = mono_method_signature (td->method)->params [n];
                mt = mint_type (type);
                if (mt == MINT_TYPE_VT) {
                        gint32 size;
-                       if (td->method->signature->pinvoke)
+                       if (mono_method_signature (td->method)->pinvoke)
                                size = mono_class_native_size (type->data.klass, NULL);
                        else
                                size = mono_class_value_size (type->data.klass, NULL);
@@ -475,16 +475,16 @@ store_arg(TransformData *td, int n)
 {
        int mt;
        CHECK_STACK (td, 1);
-       if (n == 0 && td->method->signature->hasthis)
+       if (n == 0 && mono_method_signature (td->method)->hasthis)
                ADD_CODE(td, MINT_STTHIS);
        else {
                MonoType *type;
-               n -= td->method->signature->hasthis;
-               type = td->method->signature->params [n];
+               n -= mono_method_signature (td->method)->hasthis;
+               type = mono_method_signature (td->method)->params [n];
                mt = mint_type (type);
                if (mt == MINT_TYPE_VT) {
                        gint32 size;
-                       if (td->method->signature->pinvoke)
+                       if (mono_method_signature (td->method)->pinvoke)
                                size = mono_class_native_size (type->data.klass, NULL);
                        else
                                size = mono_class_value_size (type->data.klass, NULL);
@@ -504,11 +504,11 @@ store_arg(TransformData *td, int n)
 static void 
 store_inarg(TransformData *td, int n)
 {
-       MonoType *type = td->method->signature->params [n];
+       MonoType *type = mono_method_signature (td->method)->params [n];
        int mt = mint_type (type);
        if (mt == MINT_TYPE_VT) {
                gint32 size;
-               if (td->method->signature->pinvoke)
+               if (mono_method_signature (td->method)->pinvoke)
                        size = mono_class_native_size (type->data.klass, NULL);
                else
                        size = mono_class_value_size (type->data.klass, NULL);
@@ -611,8 +611,8 @@ get_data_item_index (TransformData *td, void *ptr)
 static void
 generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
 {
-       MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
-       MonoMethodSignature *signature = method->signature;
+       MonoMethodHeader *header = mono_method_get_header (method);
+       MonoMethodSignature *signature = mono_method_signature (method);
        MonoImage *image = method->klass->image;
        MonoDomain *domain = mono_domain_get ();
        MonoGenericContext *generic_context = NULL;
@@ -629,7 +629,7 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
        TransformData td;
        int generating_code = 1;
 
-       if (method->signature->is_inflated)
+       if (mono_method_signature (method)->is_inflated)
                generic_context = ((MonoMethodInflated *) method)->context;
 
        memset(&td, 0, sizeof(td));
@@ -759,7 +759,7 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                td.is_bb_start [td.ip - td.il_code] == 3 ? "<>" :
                                td.is_bb_start [td.ip - td.il_code] == 2 ? "< " :
                                td.is_bb_start [td.ip - td.il_code] == 1 ? " >" : "  ",
-                               mono_opcode_names [*td.ip], td.new_ip - td.new_code, td.sp - td.stack, 
+                               mono_opcode_name (*td.ip), td.new_ip - td.new_code, td.sp - td.stack, 
                                td.sp > td.stack ? stack_type_string [td.sp [-1].type] : "  ",
                                (td.sp > td.stack && (td.sp [-1].type == STACK_TYPE_O || td.sp [-1].type == STACK_TYPE_VT)) ? (td.sp [-1].klass == NULL ? "?" : td.sp [-1].klass->name) : "",
                                td.vt_sp, td.max_vt_sp);
@@ -907,9 +907,14 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                case CEE_DUP: {
                        int type = td.sp [-1].type;
                        MonoClass *klass = td.sp [-1].klass;
-                       if (td.sp [-1].type == STACK_TYPE_VT)
-                               g_warning ("dup of value type not implemented");
-                       SIMPLE_OP(td, MINT_DUP);
+                       if (td.sp [-1].type == STACK_TYPE_VT) {
+                               gint32 size = mono_class_value_size (klass, NULL);
+                               PUSH_VT(&td, size);
+                               ADD_CODE(&td, MINT_DUP_VT);
+                               WRITE32(&td, &size);
+                               td.ip ++;
+                       } else 
+                               SIMPLE_OP(td, MINT_DUP);
                        PUSH_TYPE(&td, type, klass);
                        break;
                }
@@ -966,7 +971,7 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                        m = mono_get_method_full (image, token, NULL, generic_context);
                                else
                                        m = (MonoMethod *)mono_method_get_wrapper_data (method, token);
-                               csignature = m->signature;
+                               csignature = mono_method_signature (m);
                                if (m->klass == mono_defaults.string_class) {
                                        if (m->name [0] == 'g') {
                                                if (strcmp (m->name, "get_Chars") == 0)
@@ -986,7 +991,7 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && 
                                (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0) {
                                int called_inited = mono_class_vtable (domain, m->klass)->initialized;
-                               MonoMethodHeader *mheader = ((MonoMethodNormal*)m)->header;
+                               MonoMethodHeader *mheader = mono_method_get_header (m);
 
                                if (/*mono_metadata_signature_equal (method->signature, m->signature) */ method == m && *(td.ip + 5) == CEE_RET) {
                                        int offset;
@@ -1007,8 +1012,8 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                        td.ip += 5;
                                        break;
                                } else {
-
-                                       if (*mheader->code == CEE_RET && called_inited) {
+                                       /* mheader might not exist if this is a delegate invoc, etc */
+                                       if (mheader && *mheader->code == CEE_RET && called_inited) {
                                                if (mono_interp_traceopt)
                                                        g_print ("Inline (empty) call of %s.%s\n", m->klass->name, m->name);
                                                for (i = 0; i < csignature->param_count; i++)
@@ -1713,7 +1718,7 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        else 
                                m = mono_get_method_full (image, token, NULL, generic_context);
 
-                       csignature = m->signature;
+                       csignature = mono_method_signature (m);
                        klass = m->klass;
                        td.sp -= csignature->param_count;
                        ADD_CODE(&td, MINT_NEWOBJ);
@@ -2380,26 +2385,65 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                case CEE_UNUSED41:
                        ++td.ip;
                        switch (*td.ip) {
-                       case CEE_MONO_FUNC1:
-                               ADD_CODE(&td, MINT_MONO_CONV1);
-                               ADD_CODE(&td, *(td.ip + 1));
-                               td.ip += 2;
-                               SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
-                               break;
-                       case CEE_MONO_PROC2:
-                               CHECK_STACK (&td, 2);
-                               ADD_CODE(&td, MINT_MONO_CONV2);
-                               ADD_CODE(&td, *(td.ip + 1));
-                               td.ip += 2;
-                               td.sp -= 2;
-                               break;
-                       case CEE_MONO_PROC3:
-                               CHECK_STACK (&td, 3);
-                               ADD_CODE(&td, MINT_MONO_CONV3);
-                               ADD_CODE(&td, *(td.ip + 1));
-                               td.ip += 2;
-                               td.sp -= 3;
-                               break;
+                               case CEE_MONO_ICALL: {
+                                       guint32 token;
+                                       gpointer func;
+                                       MonoJitICallInfo *info;
+
+                                       token = read32 (td.ip + 1);
+                                       td.ip += 5;
+                                       func = mono_method_get_wrapper_data (method, token);
+                                       info = mono_find_jit_icall_by_addr (func);
+                                       g_assert (info);
+
+                                       CHECK_STACK (&td, info->sig->param_count);
+                                       switch (info->sig->param_count) {
+                                       case 0:
+                                               if (MONO_TYPE_IS_VOID (info->sig->ret))
+                                                       ADD_CODE (&td,MINT_ICALL_V_V);
+                                               else
+                                                       g_assert_not_reached();
+                                               break;
+                                       case 1:
+                                               if (MONO_TYPE_IS_VOID (info->sig->ret))
+                                                       ADD_CODE (&td,MINT_ICALL_P_V);
+                                               else
+                                                       ADD_CODE (&td,MINT_ICALL_P_P);
+                                               break;
+                                       case 2:
+                                               if (MONO_TYPE_IS_VOID (info->sig->ret)) {
+                                                       if (info->sig->params [1]->type == MONO_TYPE_I4)
+                                                               ADD_CODE (&td,MINT_ICALL_PI_V);
+                                                       else
+                                                               ADD_CODE (&td,MINT_ICALL_PP_V);
+                                               } else {
+                                                       if (info->sig->params [1]->type == MONO_TYPE_I4)
+                                                               ADD_CODE (&td,MINT_ICALL_PI_P);
+                                                       else
+                                                               ADD_CODE (&td,MINT_ICALL_PP_P);
+                                               }
+                                               break;
+                                       case 3:
+                                               g_assert (MONO_TYPE_IS_VOID (info->sig->ret));
+                                               if (info->sig->params [2]->type == MONO_TYPE_I4)
+                                                       ADD_CODE (&td,MINT_ICALL_PPI_V);
+                                               else
+                                                       ADD_CODE (&td,MINT_ICALL_PPP_V);
+                                               break;
+                                       default:
+                                               g_assert_not_reached ();
+                                       }
+                                       if (func == mono_ftnptr_to_delegate)
+                                               func = mono_interp_ftnptr_to_delegate;
+                                       ADD_CODE(&td, get_data_item_index (&td, func));
+                                       td.sp -= info->sig->param_count;
+
+                                       if (!MONO_TYPE_IS_VOID (info->sig->ret)) {
+                                               td.sp ++;
+                                               SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
+                                       }
+                                       break;
+                               }
                        case CEE_MONO_VTADDR: {
                                int size;
                                CHECK_STACK (&td, 1);
@@ -2417,6 +2461,7 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                break;
                        }
                        case CEE_MONO_LDPTR:
+                       case CEE_MONO_CLASSCONST:
                                token = read32 (td.ip + 1);
                                td.ip += 5;
                                ADD_CODE(&td, MINT_MONO_LDPTR);
@@ -2424,12 +2469,6 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                td.sp [0].type = STACK_TYPE_I;
                                ++td.sp;
                                break;
-                       case CEE_MONO_FREE:
-                               CHECK_STACK (&td, 1);
-                               ADD_CODE(&td, MINT_MONO_FREE);
-                               ++td.ip;
-                               --td.sp;
-                               break;
                        case CEE_MONO_OBJADDR:
                                CHECK_STACK (&td, 1);
                                ++td.ip;
@@ -2467,6 +2506,7 @@ generate(MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                break;
                        case CEE_MONO_SAVE_LMF:
                        case CEE_MONO_RESTORE_LMF:
+                       case CEE_MONO_NOT_TAKEN:
                                ++td.ip;
                                break;
                        default:
@@ -2765,8 +2805,8 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
        int i, align, size, offset;
        MonoMethod *method = runtime_method->method;
        MonoImage *image = method->klass->image;
-       MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
-       MonoMethodSignature *signature = method->signature;
+       MonoMethodHeader *header = mono_method_get_header (method);
+       MonoMethodSignature *signature = mono_method_signature (method);
        register const unsigned char *ip, *end;
        const MonoOpcode *opcode;
        MonoMethod *m;
@@ -2800,7 +2840,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
 
        mono_profiler_method_jit (method); /* sort of... */
 
-       if (method->signature->is_inflated)
+       if (mono_method_signature (method)->is_inflated)
                generic_context = ((MonoMethodInflated *) method)->context;
 
        if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
@@ -2814,12 +2854,12 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
 
                /* assumes all internal calls with an array this are built in... */
                if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL &&
-                       (!method->signature->hasthis || method->klass->rank == 0)) {
+                       (! mono_method_signature (method)->hasthis || method->klass->rank == 0)) {
                        runtime_method->code = g_malloc(sizeof(short));
                        runtime_method->code[0] = MINT_CALLINT;
-                       if (method->addr == NULL)
-                               method->addr = mono_lookup_internal_call (method);
-                       runtime_method->func = mono_arch_create_trampoline (method->signature, method->string_ctor);
+                       if (((MonoMethodPInvoke*) method)->addr == NULL)
+                               ((MonoMethodPInvoke*) method)->addr = mono_lookup_internal_call (method);
+                       runtime_method->func = mono_arch_create_trampoline (mono_method_signature (method), method->string_ctor);
                } else {
                        const char *name = method->name;
                        if (method->klass->parent == mono_defaults.multicastdelegate_class) {
@@ -2845,7 +2885,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                        return NULL;
                }
                method = nm;
-               header = ((MonoMethodNormal *)nm)->header;
+               header = mono_method_get_header (nm);
                LeaveCriticalSection(&calc_section);
        }
        g_assert ((signature->param_count + signature->hasthis) < 1000);
@@ -2864,7 +2904,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                }
                else if (in == 0xf0) {
                        ip++;
-                       in = *ip + MONO_CEE_MONO_FUNC1;
+                       in = *ip + MONO_CEE_MONO_ICALL;
                }
                opcode = &mono_opcodes [in];
                switch (opcode->argument) {
@@ -2880,7 +2920,8 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                        if (method->wrapper_type == MONO_WRAPPER_NONE) {
                                class = mono_class_get_full (image, read32 (ip + 1), generic_context);
                                mono_class_init (class);
-                               if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE))
+                               /* quick fix to not do this for the fake ptr classes - probably should not be getting the vtable at all here */
+                               if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE) && class->interface_offsets != NULL)
                                        mono_class_vtable (domain, class);
                        }
                        ip += 5;