[mono][interp] Fix arg alignment issues when mixing with compiled code (#85153)
authorVlad Brezae <brezaevlad@gmail.com>
Mon, 8 May 2023 10:39:51 +0000 (13:39 +0300)
committerGitHub <noreply@github.com>
Mon, 8 May 2023 10:39:51 +0000 (13:39 +0300)
* [mono][interp] Refactor arg offset computation to make code clearer

* [mono][interp] Remove redundant assign

* [mono][interp] Move mint_type out from header file

It makes no sense to inline this big method into callers.

* [mono][interp] Fix arg offset computation when doing pinvoke and aot/jit calls from interp

The previous code wasn't handling alignment of simd types.

* [mono][interp] Use the correct alignment for args when entering interp

We stop computing the arguments on the fly since it's getting too expensive doing the alignment checks. We directly use `imethod->arg_offsets` instead which is computed once during the first call, while also ensuring consistency with the calculation.

* [mono][interp] Fix arg offset computation when running clauses with interp

* [mono][interp] Remove dead code

* Temporaril disable jiterp for CI

* Update jiterpreter interp_entry wrapper generator and re-enable jiterp

* Revert options-def.h changes

---------

Co-authored-by: Katelyn Gadd <kg@luminance.org>
src/mono/mono/mini/interp/interp-internals.h
src/mono/mono/mini/interp/interp.c
src/mono/mono/mini/interp/jiterpreter.c
src/mono/mono/mini/interp/jiterpreter.h
src/mono/mono/mini/interp/transform-simd.c
src/mono/mono/mini/interp/transform.c
src/mono/wasm/runtime/cwraps.ts
src/mono/wasm/runtime/jiterpreter-interp-entry.ts
src/mono/wasm/runtime/jiterpreter-support.ts

index dc38222..fb8e9e3 100644 (file)
@@ -313,6 +313,12 @@ mono_interp_jit_call_supported (MonoMethod *method, MonoMethodSignature *sig);
 void
 mono_interp_error_cleanup (MonoError *error);
 
+int
+mono_mint_type (MonoType *type);
+
+int
+mono_interp_type_size (MonoType *type, int mt, int *align_p);
+
 #if HOST_BROWSER
 
 gboolean
@@ -333,12 +339,15 @@ mono_jiterp_overflow_check_u4 (guint32 lhs, guint32 rhs, int opcode);
 void
 mono_jiterp_ld_delegate_method_ptr (gpointer *destination, MonoDelegate **source);
 
-int
+void
 mono_jiterp_stackval_to_data (MonoType *type, stackval *val, void *data);
 
-int
+void
 mono_jiterp_stackval_from_data (MonoType *type, stackval *result, const void *data);
 
+int
+mono_jiterp_get_arg_offset (InterpMethod *imethod, MonoMethodSignature *sig, int index);
+
 gpointer
 mono_jiterp_frame_data_allocator_alloc (FrameDataAllocator *stack, InterpFrame *frame, int size);
 
@@ -350,62 +359,4 @@ mono_jiterp_get_simd_opcode (int arity, int index);
 
 #endif
 
-static inline int
-mint_type(MonoType *type)
-{
-       if (m_type_is_byref (type))
-               return MINT_TYPE_I;
-enum_type:
-       switch (type->type) {
-       case MONO_TYPE_I1:
-               return MINT_TYPE_I1;
-       case MONO_TYPE_U1:
-       case MONO_TYPE_BOOLEAN:
-               return MINT_TYPE_U1;
-       case MONO_TYPE_I2:
-               return MINT_TYPE_I2;
-       case MONO_TYPE_U2:
-       case MONO_TYPE_CHAR:
-               return MINT_TYPE_U2;
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
-               return MINT_TYPE_I4;
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-       case MONO_TYPE_PTR:
-       case MONO_TYPE_FNPTR:
-               return MINT_TYPE_I;
-       case MONO_TYPE_R4:
-               return MINT_TYPE_R4;
-       case MONO_TYPE_I8:
-       case MONO_TYPE_U8:
-               return MINT_TYPE_I8;
-       case MONO_TYPE_R8:
-               return MINT_TYPE_R8;
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_ARRAY:
-               return MINT_TYPE_O;
-       case MONO_TYPE_VALUETYPE:
-               if (m_class_is_enumtype (type->data.klass)) {
-                       type = mono_class_enum_basetype_internal (type->data.klass);
-                       goto enum_type;
-               } else
-                       return MINT_TYPE_VT;
-       case MONO_TYPE_TYPEDBYREF:
-               return MINT_TYPE_VT;
-       case MONO_TYPE_GENERICINST:
-               type = m_class_get_byval_arg (type->data.generic_class->container_class);
-               goto enum_type;
-       case MONO_TYPE_VOID:
-               return MINT_TYPE_VOID;
-       default:
-               g_warning ("got type 0x%02x", type->type);
-               g_assert_not_reached ();
-       }
-       return -1;
-}
-
 #endif /* __MONO_MINI_INTERPRETER_INTERNALS_H__ */
index 9e1e9e1..32b6c4b 100644 (file)
@@ -242,6 +242,7 @@ reinit_frame (InterpFrame *frame, InterpFrame *parent, InterpMethod *imethod, gp
        frame->state.ip = NULL;
 }
 
+#define STACK_ADD_ALIGNED_BYTES(sp,bytes) ((stackval*)((char*)(sp) + (bytes)))
 #define STACK_ADD_BYTES(sp,bytes) ((stackval*)((char*)(sp) + ALIGN_TO(bytes, MINT_STACK_SLOT_SIZE)))
 #define STACK_SUB_BYTES(sp,bytes) ((stackval*)((char*)(sp) - ALIGN_TO(bytes, MINT_STACK_SLOT_SIZE)))
 
@@ -770,129 +771,66 @@ get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset)
        }
 }
 
-// Returns the size it uses on the interpreter stack
-static int
-stackval_size (MonoType *type, gboolean pinvoke)
-{
-       if (m_type_is_byref (type))
-               return MINT_STACK_SLOT_SIZE;
-       switch (type->type) {
-       case MONO_TYPE_VOID:
-               return 0;
-       case MONO_TYPE_I1:
-       case MONO_TYPE_U1:
-       case MONO_TYPE_BOOLEAN:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_U2:
-       case MONO_TYPE_CHAR:
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U:
-       case MONO_TYPE_I:
-       case MONO_TYPE_PTR:
-       case MONO_TYPE_FNPTR:
-       case MONO_TYPE_U4:
-               return MINT_STACK_SLOT_SIZE;
-       case MONO_TYPE_R4:
-               return MINT_STACK_SLOT_SIZE;
-       case MONO_TYPE_I8:
-       case MONO_TYPE_U8:
-               return MINT_STACK_SLOT_SIZE;
-       case MONO_TYPE_R8:
-               return MINT_STACK_SLOT_SIZE;
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_ARRAY:
-               return MINT_STACK_SLOT_SIZE;
-       case MONO_TYPE_VALUETYPE:
-               if (m_class_is_enumtype (type->data.klass)) {
-                       return stackval_size (mono_class_enum_basetype_internal (type->data.klass), pinvoke);
-               } else {
-                       int size;
-                       if (pinvoke)
-                               size = mono_class_native_size (type->data.klass, NULL);
-                       else
-                               size = mono_class_value_size (type->data.klass, NULL);
-                       return ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
-               }
-       case MONO_TYPE_GENERICINST: {
-               if (mono_type_generic_inst_is_valuetype (type)) {
-                       MonoClass *klass = mono_class_from_mono_type_internal (type);
-                       int size;
-                       if (pinvoke)
-                               size = mono_class_native_size (klass, NULL);
-                       else
-                               size = mono_class_value_size (klass, NULL);
-                       return ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
-               }
-               return stackval_size (m_class_get_byval_arg (type->data.generic_class->container_class), pinvoke);
-       }
-       default:
-               g_error ("got type 0x%02x", type->type);
-       }
-}
-
-// Returns the size it uses on the interpreter stack
-static int
+static void
 stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean pinvoke)
 {
        if (m_type_is_byref (type)) {
                result->data.p = *(gpointer*)data;
-               return MINT_STACK_SLOT_SIZE;
+               return;
        }
        switch (type->type) {
        case MONO_TYPE_VOID:
-               return 0;
+               break;;
        case MONO_TYPE_I1:
                result->data.i = *(gint8*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_U1:
        case MONO_TYPE_BOOLEAN:
                result->data.i = *(guint8*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_I2:
                result->data.i = *(gint16*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_U2:
        case MONO_TYPE_CHAR:
                result->data.i = *(guint16*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_I4:
                result->data.i = *(gint32*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_U:
        case MONO_TYPE_I:
                result->data.nati = *(mono_i*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
                result->data.p = *(gpointer*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_U4:
                result->data.i = *(guint32*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_R4:
                /* memmove handles unaligned case */
                memmove (&result->data.f_r4, data, sizeof (float));
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
                memmove (&result->data.l, data, sizeof (gint64));
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_R8:
                memmove (&result->data.f, data, sizeof (double));
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_STRING:
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_CLASS:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_ARRAY:
                result->data.p = *(gpointer*)data;
-               return MINT_STACK_SLOT_SIZE;
+               break;
        case MONO_TYPE_VALUETYPE:
                if (m_class_is_enumtype (type->data.klass)) {
-                       return stackval_from_data (mono_class_enum_basetype_internal (type->data.klass), result, data, pinvoke);
+                       stackval_from_data (mono_class_enum_basetype_internal (type->data.klass), result, data, pinvoke);
+                       break;
                } else {
                        int size;
                        if (pinvoke)
@@ -900,7 +838,7 @@ stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean
                        else
                                size = mono_class_value_size (type->data.klass, NULL);
                        memcpy (result, data, size);
-                       return ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
+                       break;
                }
        case MONO_TYPE_GENERICINST: {
                if (mono_type_generic_inst_is_valuetype (type)) {
@@ -911,9 +849,10 @@ stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean
                        else
                                size = mono_class_value_size (klass, NULL);
                        memcpy (result, data, size);
-                       return ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
+                       break;
                }
-               return stackval_from_data (m_class_get_byval_arg (type->data.generic_class->container_class), result, data, pinvoke);
+               stackval_from_data (m_class_get_byval_arg (type->data.generic_class->container_class), result, data, pinvoke);
+               break;
        }
        default:
                g_error ("got type 0x%02x", type->type);
@@ -1311,26 +1250,26 @@ ves_array_element_address (InterpFrame *frame, MonoClass *required_type, MonoArr
 
 /* Does not handle `this` argument */
 static guint32
-compute_arg_offset (MonoMethodSignature *sig, int index, int prev_offset)
+compute_arg_offset (MonoMethodSignature *sig, int index)
 {
        if (index == 0)
                return 0;
 
-       if (prev_offset == -1) {
-               guint32 offset = 0;
-               for (int i = 0; i < index; i++) {
-                       int size, align;
-                       MonoType *type = sig->params [i];
-                       size = mono_type_size (type, &align);
-                       offset += ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
-               }
-               return offset;
-       } else {
-               int size, align;
-               MonoType *type = sig->params [index - 1];
-               size = mono_type_size (type, &align);
-               return prev_offset + ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
+       guint32 offset = 0;
+       int size, align;
+       MonoType *type;
+       for (int i = 0; i < index; i++) {
+               type = sig->params [i];
+               size = mono_interp_type_size (type, mono_mint_type (type), &align);
+
+               offset = ALIGN_TO (offset, align);
+               offset += size;
        }
+       type = sig->params [index];
+       mono_interp_type_size (type, mono_mint_type (type), &align);
+
+       offset = ALIGN_TO (offset, align);
+       return offset;
 }
 
 static guint32*
@@ -1345,19 +1284,26 @@ initialize_arg_offsets (InterpMethod *imethod, MonoMethodSignature *csig)
        if (!sig)
                sig = mono_method_signature_internal (imethod->method);
        int arg_count = sig->hasthis + sig->param_count;
-       g_assert (arg_count);
-       guint32 *arg_offsets = (guint32*) g_malloc ((sig->hasthis + sig->param_count) * sizeof (int));
-       int index = 0, offset_addend = 0, prev_offset = 0;
+       guint32 *arg_offsets = (guint32*) g_malloc ((arg_count + 1) * sizeof (int));
+       int index = 0, offset = 0;
 
        if (sig->hasthis) {
                arg_offsets [index++] = 0;
-               offset_addend = MINT_STACK_SLOT_SIZE;
+               offset = MINT_STACK_SLOT_SIZE;
        }
 
        for (int i = 0; i < sig->param_count; i++) {
-               prev_offset = compute_arg_offset (sig, i, prev_offset);
-               arg_offsets [index++] = prev_offset + offset_addend;
+               MonoType *type = sig->params [i];
+               int size, align;
+               size = mono_interp_type_size (type, mono_mint_type (type), &align);
+
+               offset = ALIGN_TO (offset, align);
+               arg_offsets [index++] = offset;
+               offset += size;
        }
+       // This index is not associated with an actual argument, we just store the offset
+       // for convenience in order to easily determine the size of the param area used
+       arg_offsets [index] = ALIGN_TO (offset, MINT_STACK_SLOT_SIZE);
 
        mono_memory_write_barrier ();
        if (mono_atomic_cas_ptr ((gpointer*)&imethod->arg_offsets, arg_offsets, NULL) != NULL)
@@ -1384,7 +1330,7 @@ get_arg_offset (InterpMethod *imethod, MonoMethodSignature *sig, int index)
                return get_arg_offset_fast (imethod, sig, index);
        } else {
                g_assert (!sig->hasthis);
-               return compute_arg_offset (sig, index, -1);
+               return compute_arg_offset (sig, index);
        }
 }
 
@@ -2175,7 +2121,8 @@ interp_entry (InterpEntryData *data)
 {
        InterpMethod *rmethod;
        ThreadContext *context;
-       stackval *sp, *sp_args;
+       stackval *sp;
+       int stack_index = 0;
        MonoMethod *method;
        MonoMethodSignature *sig;
        MonoType *type;
@@ -2193,7 +2140,7 @@ interp_entry (InterpEntryData *data)
                orig_domain = mono_threads_attach_coop (mono_domain_get (), &attach_cookie);
 
        context = get_context ();
-       sp_args = sp = (stackval*)context->stack_pointer;
+       sp = (stackval*)context->stack_pointer;
 
        method = rmethod->method;
 
@@ -2213,8 +2160,8 @@ interp_entry (InterpEntryData *data)
        // FIXME: Optimize this
 
        if (sig->hasthis) {
-               sp_args->data.p = data->this_arg;
-               sp_args++;
+               sp->data.p = data->this_arg;
+               stack_index = 1;
        }
 
        gpointer *params;
@@ -2223,22 +2170,22 @@ interp_entry (InterpEntryData *data)
        else
                params = data->args;
        for (i = 0; i < sig->param_count; ++i) {
-               if (m_type_is_byref (sig->params [i])) {
-                       sp_args->data.p = params [i];
-                       sp_args++;
-               } else {
-                       int size = stackval_from_data (sig->params [i], sp_args, params [i], FALSE);
-                       sp_args = STACK_ADD_BYTES (sp_args, size);
-               }
+               int arg_offset = get_arg_offset_fast (rmethod, NULL, stack_index + i);
+               stackval *sval = STACK_ADD_ALIGNED_BYTES (sp, arg_offset);
+
+               if (m_type_is_byref (sig->params [i]))
+                       sval->data.p = params [i];
+               else
+                       stackval_from_data (sig->params [i], sval, params [i], FALSE);
        }
-       sp_args = (stackval*)ALIGN_TO (sp_args, MINT_STACK_ALIGNMENT);
 
        InterpFrame frame = {0};
        frame.imethod = data->rmethod;
        frame.stack = sp;
        frame.retval = sp;
 
-       context->stack_pointer = (guchar*)sp_args;
+       int params_size = get_arg_offset_fast (rmethod, NULL, stack_index + sig->param_count);
+       context->stack_pointer = (guchar*)ALIGN_TO ((guchar*)sp + params_size, MINT_STACK_ALIGNMENT);
        g_assert (context->stack_pointer < context->stack_end);
 
        MONO_ENTER_GC_UNSAFE;
@@ -2597,7 +2544,7 @@ init_jit_call_info (InterpMethod *rmethod, MonoError *error)
        cinfo->wrapper = jit_wrapper;
 
        if (sig->ret->type != MONO_TYPE_VOID) {
-               int mt = mint_type (sig->ret);
+               int mt = mono_mint_type (sig->ret);
                if (mt == MINT_TYPE_VT) {
                        MonoClass *klass = mono_class_from_mono_type_internal (sig->ret);
                        /*
@@ -2620,7 +2567,7 @@ init_jit_call_info (InterpMethod *rmethod, MonoError *error)
 
                for (guint i = 0; i < rmethod->param_count; ++i) {
                        MonoType *t = rmethod->param_types [i];
-                       int mt = mint_type (t);
+                       int mt = mono_mint_type (t);
                        if (m_type_is_byref (sig->params [i])) {
                                cinfo->arginfo [i] = JIT_ARG_BYVAL;
                        } else if (mt == MINT_TYPE_O) {
@@ -2735,7 +2682,7 @@ do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame
        if (cinfo->ret_mt != -1)
                args [pindex ++] = ret_sp;
        for (guint i = 0; i < rmethod->param_count; ++i) {
-               stackval *sval = STACK_ADD_BYTES (sp, get_arg_offset_fast (rmethod, NULL, stack_index + i));
+               stackval *sval = STACK_ADD_ALIGNED_BYTES (sp, get_arg_offset_fast (rmethod, NULL, stack_index + i));
                if (cinfo->arginfo [i] == JIT_ARG_BYVAL)
                        args [pindex ++] = sval->data.p;
                else
@@ -8099,8 +8046,7 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb
        MonoMethodILState *il_state = (MonoMethodILState*)il_state_ptr;
        MonoMethodSignature *sig;
        ThreadContext *context = get_context ();
-       stackval *orig_sp;
-       stackval *sp, *sp_args;
+       stackval *sp;
        InterpMethod *imethod;
        FrameClauseArgs clause_args;
        ERROR_DECL (error);
@@ -8115,7 +8061,7 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb
                mono_error_assert_ok (error);
        }
 
-       orig_sp = sp_args = sp = (stackval*)context->stack_pointer;
+       sp = (stackval*)context->stack_pointer;
 
        gpointer ret_addr = NULL;
 
@@ -8124,24 +8070,23 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb
                ret_addr = il_state->data [findex];
                findex ++;
        }
+       int first_param_index = 0;
        if (sig->hasthis) {
                if (il_state->data [findex])
-                       sp_args->data.p = *(gpointer*)il_state->data [findex];
-               sp_args++;
+                       sp->data.p = *(gpointer*)il_state->data [findex];
+               first_param_index = 1;
                findex ++;
        }
 
        for (int i = 0; i < sig->param_count; ++i) {
                if (il_state->data [findex]) {
-                       int size = stackval_from_data (sig->params [i], sp_args, il_state->data [findex], FALSE);
-                       sp_args = STACK_ADD_BYTES (sp_args, size);
-               } else {
-                       int size = stackval_size (sig->params [i], FALSE);
-                       sp_args = STACK_ADD_BYTES (sp_args, size);
+                       int arg_offset = get_arg_offset_fast (imethod, NULL, first_param_index + i);
+                       stackval *sval = STACK_ADD_ALIGNED_BYTES (sp, arg_offset);
+
+                       stackval_from_data (sig->params [i], sval, il_state->data [findex], FALSE);
                }
                findex ++;
        }
-       sp_args = (stackval*)ALIGN_TO (sp_args, MINT_STACK_ALIGNMENT);
 
        /* Allocate frame */
        InterpFrame frame = {0};
@@ -8149,7 +8094,8 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb
        frame.stack = sp;
        frame.retval = sp;
 
-       context->stack_pointer = (guchar*)sp_args;
+       int params_size = get_arg_offset_fast (imethod, NULL, first_param_index + sig->param_count);
+       context->stack_pointer = (guchar*)ALIGN_TO ((guchar*)sp + params_size, MINT_STACK_ALIGNMENT);
        context->stack_pointer += imethod->alloca_size;
        g_assert (context->stack_pointer < context->stack_end);
 
@@ -8198,22 +8144,19 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb
        mono_interp_exec_method (&frame, context, &clause_args);
 
        /* Write back args */
-       sp_args = sp;
        findex = 0;
        if (sig->ret->type != MONO_TYPE_VOID)
                findex ++;
        if (sig->hasthis) {
                // FIXME: This
-               sp_args++;
                findex ++;
        }
        for (int i = 0; i < sig->param_count; ++i) {
                if (il_state->data [findex]) {
-                       int size = stackval_to_data (sig->params [i], sp_args, il_state->data [findex], FALSE);
-                       sp_args = STACK_ADD_BYTES (sp_args, size);
-               } else {
-                       int size = stackval_size (sig->params [i], FALSE);
-                       sp_args = STACK_ADD_BYTES (sp_args, size);
+                       int arg_offset = get_arg_offset_fast (imethod, NULL, first_param_index + i);
+                       stackval *sval = STACK_ADD_ALIGNED_BYTES (sp, arg_offset);
+
+                       stackval_to_data (sig->params [i], sval, il_state->data [findex], FALSE);
                }
                findex ++;
        }
@@ -8231,8 +8174,8 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb
                *filtered = frame.retval->data.i;
        }
 
-       memset (orig_sp, 0, (guint8*)context->stack_pointer - (guint8*)orig_sp);
-       context->stack_pointer = (guchar*)orig_sp;
+       memset (sp, 0, (guint8*)context->stack_pointer - (guint8*)sp);
+       context->stack_pointer = (guchar*)sp;
 
        check_pending_unwind (context);
 
@@ -8744,16 +8687,22 @@ mono_ee_interp_init (const char *opts)
 }
 
 #ifdef HOST_BROWSER
-EMSCRIPTEN_KEEPALIVE int
+EMSCRIPTEN_KEEPALIVE void
 mono_jiterp_stackval_to_data (MonoType *type, stackval *val, void *data)
 {
-       return stackval_to_data (type, val, data, FALSE);
+       stackval_to_data (type, val, data, FALSE);
 }
 
-EMSCRIPTEN_KEEPALIVE int
+EMSCRIPTEN_KEEPALIVE void
 mono_jiterp_stackval_from_data (MonoType *type, stackval *result, const void *data)
 {
-       return stackval_from_data (type, result, data, FALSE);
+       stackval_from_data (type, result, data, FALSE);
+}
+
+EMSCRIPTEN_KEEPALIVE int
+mono_jiterp_get_arg_offset (InterpMethod *imethod, MonoMethodSignature *sig, int index)
+{
+       return get_arg_offset_fast (imethod, sig, index);
 }
 
 EMSCRIPTEN_KEEPALIVE int
@@ -8833,7 +8782,7 @@ mono_jiterp_isinst (MonoObject* object, MonoClass* klass)
 //  in the correct place and compute the stack offset, then it passes that in to this
 //  function in order to actually enter the interpreter and process the return value
 EMSCRIPTEN_KEEPALIVE void
-mono_jiterp_interp_entry (JiterpEntryData *_data, stackval *sp_args, void *res)
+mono_jiterp_interp_entry (JiterpEntryData *_data, void *res)
 {
        JiterpEntryDataHeader header;
        MonoType *type;
@@ -8846,7 +8795,6 @@ mono_jiterp_interp_entry (JiterpEntryData *_data, stackval *sp_args, void *res)
 
        g_assert(header.rmethod);
        g_assert(header.rmethod->method);
-       g_assert(sp_args);
 
        stackval *sp = (stackval*)header.context->stack_pointer;
 
@@ -8855,8 +8803,11 @@ mono_jiterp_interp_entry (JiterpEntryData *_data, stackval *sp_args, void *res)
        frame.stack = sp;
        frame.retval = sp;
 
-       header.context->stack_pointer = (guchar*)sp_args;
-       g_assert ((guchar*)sp_args < header.context->stack_end);
+       int params_size = get_arg_offset_fast (header.rmethod, NULL, header.params_count);
+       // g_printf ("jiterp_interp_entry: rmethod=%d, params_count=%d, params_size=%d\n", header.rmethod, header.params_count, params_size);
+       header.context->stack_pointer = (guchar*)ALIGN_TO ((guchar*)sp + params_size, MINT_STACK_ALIGNMENT);
+;
+       g_assert (header.context->stack_pointer < header.context->stack_end);
 
        MONO_ENTER_GC_UNSAFE;
        mono_interp_exec_method (&frame, header.context, NULL);
index d61e78e..5133210 100644 (file)
@@ -1169,6 +1169,7 @@ mono_jiterp_trace_transfer (
 #define JITERP_MEMBER_BACKWARD_BRANCH_OFFSETS 10
 #define JITERP_MEMBER_BACKWARD_BRANCH_OFFSETS_COUNT 11
 #define JITERP_MEMBER_CLAUSE_DATA_OFFSETS 12
+#define JITERP_MEMBER_PARAMS_COUNT 13
 
 // we use these helpers at JIT time to figure out where to do memory loads and stores
 EMSCRIPTEN_KEEPALIVE size_t
@@ -1196,6 +1197,8 @@ mono_jiterp_get_member_offset (int member) {
                        return offsetof (InterpMethod, clause_data_offsets);
                case JITERP_MEMBER_RMETHOD:
                        return offsetof (JiterpEntryDataHeader, rmethod);
+               case JITERP_MEMBER_PARAMS_COUNT:
+                       return offsetof (JiterpEntryDataHeader, params_count);
                case JITERP_MEMBER_SPAN_LENGTH:
                        return offsetof (MonoSpanOfVoid, _length);
                case JITERP_MEMBER_SPAN_DATA:
index 896387b..8573072 100644 (file)
@@ -106,6 +106,7 @@ typedef struct {
        ThreadContext *context;
        gpointer orig_domain;
        gpointer attach_cookie;
+       int params_count;
 } JiterpEntryDataHeader;
 
 // we optimize delegate calls by attempting to cache the delegate invoke
@@ -136,7 +137,7 @@ void
 mono_jiterp_do_safepoint (InterpFrame *frame, guint16 *ip);
 
 void
-mono_jiterp_interp_entry (JiterpEntryData *_data, stackval *sp_args, void *res);
+mono_jiterp_interp_entry (JiterpEntryData *_data, void *res);
 
 gpointer
 mono_jiterp_imethod_to_ftnptr (InterpMethod *imethod);
index bb7c269..b259d3f 100644 (file)
@@ -316,7 +316,7 @@ opcode_added:
                td->last_ins->sregs [i] = td->sp [i].local;
 
        g_assert (csignature->ret->type != MONO_TYPE_VOID);
-       int ret_mt = mint_type (csignature->ret);
+       int ret_mt = mono_mint_type (csignature->ret);
        if (ret_mt == MINT_TYPE_VT) {
                // For these intrinsics, if we return a VT then it is a V128
                push_type_vt (td, vector_klass, vector_size);
@@ -504,7 +504,7 @@ opcode_added:
                td->last_ins->sregs [i] = td->sp [i].local;
 
        g_assert (csignature->ret->type != MONO_TYPE_VOID);
-       int ret_mt = mint_type (csignature->ret);
+       int ret_mt = mono_mint_type (csignature->ret);
        if (ret_mt == MINT_TYPE_VT) {
                // For these intrinsics, if we return a VT then it is a V128
                push_type_vt (td, vector_klass, vector_size);
@@ -680,7 +680,7 @@ opcode_added:
                td->last_ins->sregs [i] = td->sp [i].local;
 
        g_assert (csignature->ret->type != MONO_TYPE_VOID);
-       int ret_mt = mint_type (csignature->ret);
+       int ret_mt = mono_mint_type (csignature->ret);
        if (ret_mt == MINT_TYPE_VT) {
                // For these intrinsics, if we return a VT then it is a V128
                push_type_vt (td, vector_klass, vector_size);
index 1eda837..5f4e223 100644 (file)
@@ -307,6 +307,65 @@ get_type_from_stack (int type, MonoClass *klass)
        }
 }
 
+int
+mono_mint_type (MonoType *type)
+{
+       if (m_type_is_byref (type))
+               return MINT_TYPE_I;
+enum_type:
+       switch (type->type) {
+       case MONO_TYPE_I1:
+               return MINT_TYPE_I1;
+       case MONO_TYPE_U1:
+       case MONO_TYPE_BOOLEAN:
+               return MINT_TYPE_U1;
+       case MONO_TYPE_I2:
+               return MINT_TYPE_I2;
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
+               return MINT_TYPE_U2;
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+               return MINT_TYPE_I4;
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+       case MONO_TYPE_PTR:
+       case MONO_TYPE_FNPTR:
+               return MINT_TYPE_I;
+       case MONO_TYPE_R4:
+               return MINT_TYPE_R4;
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+               return MINT_TYPE_I8;
+       case MONO_TYPE_R8:
+               return MINT_TYPE_R8;
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_ARRAY:
+               return MINT_TYPE_O;
+       case MONO_TYPE_VALUETYPE:
+               if (m_class_is_enumtype (type->data.klass)) {
+                       type = mono_class_enum_basetype_internal (type->data.klass);
+                       goto enum_type;
+               } else
+                       return MINT_TYPE_VT;
+       case MONO_TYPE_TYPEDBYREF:
+               return MINT_TYPE_VT;
+       case MONO_TYPE_GENERICINST:
+               type = m_class_get_byval_arg (type->data.generic_class->container_class);
+               goto enum_type;
+       case MONO_TYPE_VOID:
+               return MINT_TYPE_VOID;
+       default:
+               g_warning ("got type 0x%02x", type->type);
+               g_assert_not_reached ();
+       }
+       return -1;
+}
+
+
 /*
  * These are additional locals that can be allocated as we transform the code.
  * They are allocated past the method locals so they are accessed in the same
@@ -321,7 +380,7 @@ create_interp_local_explicit (TransformData *td, MonoType *type, int size)
                        td->locals_capacity = 2;
                td->locals = (InterpLocal*) g_realloc (td->locals, td->locals_capacity * sizeof (InterpLocal));
        }
-       int mt = mint_type (type);
+       int mt = mono_mint_type (type);
        InterpLocal *local = &td->locals [td->locals_size];
 
        local->type = type;
@@ -925,7 +984,7 @@ get_arg_type_exact (TransformData *td, int n, int *mt)
                type = mono_method_signature_internal (td->method)->params [n - !!hasthis];
 
        if (mt)
-               *mt = mint_type (type);
+               *mt = mono_mint_type (type);
 
        return type;
 }
@@ -1768,7 +1827,7 @@ interp_get_stind_for_mt (int mt)
 static void
 interp_emit_ldobj (TransformData *td, MonoClass *klass)
 {
-       int mt = mint_type (m_class_get_byval_arg (klass));
+       int mt = mono_mint_type (m_class_get_byval_arg (klass));
        gint32 size = 0;
        td->sp--;
 
@@ -1792,7 +1851,7 @@ interp_emit_ldobj (TransformData *td, MonoClass *klass)
 static void
 interp_emit_stobj (TransformData *td, MonoClass *klass, gboolean reverse_order)
 {
-       int mt = mint_type (m_class_get_byval_arg (klass));
+       int mt = mono_mint_type (m_class_get_byval_arg (klass));
 
        if (mt == MINT_TYPE_VT) {
                if (m_class_has_references (klass)) {
@@ -2188,7 +2247,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
                        interp_add_ins (td, MINT_CLT_UN_P);
                        td->sp -= 2;
                        interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local);
-                       push_type (td, stack_type [mint_type (m_class_get_byval_arg (k))], k);
+                       push_type (td, stack_type [mono_mint_type (m_class_get_byval_arg (k))], k);
                        interp_ins_set_dreg (td->last_ins, td->sp [-1].local);
                        td->ip += 5;
                        return TRUE;
@@ -2399,8 +2458,8 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
                        base_klass = mono_class_from_mono_type_internal (base_type);
 
                        // Remove the boxing of valuetypes, by replacing them with moves
-                       prev_prev_ins->opcode = GINT_TO_OPCODE (get_mov_for_type (mint_type (base_type), FALSE));
-                       td->last_ins->opcode = GINT_TO_OPCODE (get_mov_for_type (mint_type (base_type), FALSE));
+                       prev_prev_ins->opcode = GINT_TO_OPCODE (get_mov_for_type (mono_mint_type (base_type), FALSE));
+                       td->last_ins->opcode = GINT_TO_OPCODE (get_mov_for_type (mono_mint_type (base_type), FALSE));
 
                        intrinsify = TRUE;
                } else if (td->last_ins && td->last_ins->opcode == MINT_BOX &&
@@ -2411,7 +2470,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
                        g_assert (m_class_is_enumtype (constrained_class));
                        MonoType *base_type = mono_type_get_underlying_type (m_class_get_byval_arg (constrained_class));
                        base_klass = mono_class_from_mono_type_internal (base_type);
-                       int mt = mint_type (m_class_get_byval_arg (base_klass));
+                       int mt = mono_mint_type (m_class_get_byval_arg (base_klass));
 
                        // Remove boxing and load the value of this
                        td->last_ins->opcode = GINT_TO_OPCODE (get_mov_for_type (mt, FALSE));
@@ -3107,7 +3166,7 @@ fail:
 static void
 interp_constrained_box (TransformData *td, MonoClass *constrained_class, MonoMethodSignature *csignature, MonoError *error)
 {
-       int mt = mint_type (m_class_get_byval_arg (constrained_class));
+       int mt = mono_mint_type (m_class_get_byval_arg (constrained_class));
        StackInfo *sp = td->sp - 1 - csignature->param_count;
        if (mono_class_is_nullable (constrained_class)) {
                g_assert (mt == MINT_TYPE_VT);
@@ -3533,7 +3592,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
 
        /* need to handle typedbyref ... */
        if (csignature->ret->type != MONO_TYPE_VOID) {
-               int mt = mint_type(csignature->ret);
+               int mt = mono_mint_type(csignature->ret);
                MonoClass *klass = mono_class_from_mono_type_internal (csignature->ret);
 
                if (mt == MINT_TYPE_VT) {
@@ -4113,8 +4172,8 @@ interp_emit_memory_barrier (TransformData *td, int kind)
                        goto exit; \
        } while (0)
 
-static int
-interp_type_size (MonoType *type, int mt, int *align_p)
+int
+mono_interp_type_size (MonoType *type, int mt, int *align_p)
 {
        int size, align;
        if (mt == MINT_TYPE_VT) {
@@ -4158,13 +4217,13 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet
                        type = m_class_is_valuetype (td->method->klass) ? m_class_get_this_arg (td->method->klass) : m_class_get_byval_arg (td->method->klass);
                else
                        type = mono_method_signature_internal (td->method)->params [i - sig->hasthis];
-               int mt = mint_type (type);
+               int mt = mono_mint_type (type);
                td->locals [i].type = type;
                td->locals [i].flags = INTERP_LOCAL_FLAG_GLOBAL;
                td->locals [i].indirects = 0;
                td->locals [i].mt = mt;
                td->locals [i].def = NULL;
-               size = interp_type_size (type, mt, &align);
+               size = mono_interp_type_size (type, mt, &align);
                td->locals [i].size = size;
                offset = ALIGN_TO (offset, align);
                td->locals [i].offset = offset;
@@ -4175,22 +4234,21 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet
        td->il_locals_offset = offset;
        for (int i = 0; i < num_il_locals; ++i) {
                int index = num_args + i;
-               size = mono_type_size (header->locals [i], &align);
+               int mt = mono_mint_type (header->locals [i]);
+               size = mono_interp_type_size (header->locals [i], mt, &align);
                if (header->locals [i]->type == MONO_TYPE_VALUETYPE) {
                        if (mono_class_has_failure (header->locals [i]->data.klass)) {
                                mono_error_set_for_class_failure (error, header->locals [i]->data.klass);
                                return;
                        }
                }
-               int mt = mint_type (header->locals [i]);
-               size = interp_type_size (header->locals [i], mt, &align);
                offset = ALIGN_TO (offset, align);
                imethod->local_offsets [i] = offset;
                td->locals [index].type = header->locals [i];
                td->locals [index].offset = offset;
                td->locals [index].flags = INTERP_LOCAL_FLAG_GLOBAL;
                td->locals [index].indirects = 0;
-               td->locals [index].mt = mint_type (header->locals [i]);
+               td->locals [index].mt = mono_mint_type (header->locals [i]);
                td->locals [index].def = NULL;
                td->locals [index].size = size;
                // Every local takes a MINT_STACK_SLOT_SIZE so IL locals have same behavior as execution locals
@@ -5180,7 +5238,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                case CEE_RET: {
                        link_bblocks = FALSE;
                        MonoType *ult = mini_type_get_underlying_type (signature->ret);
-                       mt = mint_type (ult);
+                       mt = mono_mint_type (ult);
                        if (mt != MINT_TYPE_VOID) {
                                // Convert stack contents to return type if necessary
                                CHECK_STACK (td, 1);
@@ -5869,7 +5927,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        goto_if_nok (error, exit);
 
                        if (m_class_is_valuetype (klass)) {
-                               mt = mint_type (m_class_get_byval_arg (klass));
+                               mt = mono_mint_type (m_class_get_byval_arg (klass));
                                td->sp -= 2;
                                if (mt == MINT_TYPE_VT && !m_class_has_references (klass)) {
                                        interp_add_ins (td, MINT_CPOBJ_VT_NOREF);
@@ -5960,7 +6018,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                                goto_if_nok (error, exit);
                        }
 
-                       int ret_mt = mint_type (m_class_get_byval_arg (klass));
+                       int ret_mt = mono_mint_type (m_class_get_byval_arg (klass));
                        if (klass == mono_defaults.int_class && csignature->param_count == 1) {
 #if SIZEOF_VOID_P == 8
                                if (td->sp [-1].type == STACK_TYPE_I4)
@@ -6233,7 +6291,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        if ((td->last_ins->opcode == MINT_BOX || td->last_ins->opcode == MINT_BOX_VT) &&
                                        (td->sp - 1)->klass == klass && td->last_ins == td->cbb->last_ins) {
                                interp_clear_ins (td->last_ins);
-                               mt = mint_type (m_class_get_byval_arg (klass));
+                               mt = mono_mint_type (m_class_get_byval_arg (klass));
                                td->sp--;
                                // Push back the original value that was boxed. We should handle this in CEE_BOX instead
                                if (mt == MINT_TYPE_VT)
@@ -6341,7 +6399,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        mono_class_setup_fields (klass);
 
                        MonoClass *field_klass = mono_class_from_mono_type_internal (ftype);
-                       mt = mint_type (ftype);
+                       mt = mono_mint_type (ftype);
                        int field_size = mono_class_value_size (field_klass, NULL);
 
                        {
@@ -6424,7 +6482,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        MonoClass *field_klass = mono_class_from_mono_type_internal (ftype);
                        mono_class_init_internal (klass);
                        mono_class_setup_fields (klass);
-                       mt = mint_type (ftype);
+                       mt = mono_mint_type (ftype);
 
                        BARRIER_IF_VOLATILE (td, MONO_MEMORY_BARRIER_REL);
 
@@ -6493,7 +6551,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        field = interp_field_from_token (method, token, &klass, generic_context, error);
                        goto_if_nok (error, exit);
                        MonoType *ftype = mono_field_get_type_internal (field);
-                       mt = mint_type (ftype);
+                       mt = mono_mint_type (ftype);
                        klass = mono_class_from_mono_type_internal (ftype);
                        gboolean in_corlib = m_class_get_image (m_field_get_parent (field)) == mono_defaults.corlib;
 
@@ -6520,7 +6578,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        field = interp_field_from_token (method, token, &klass, generic_context, error);
                        goto_if_nok (error, exit);
                        MonoType *ftype = mono_field_get_type_internal (field);
-                       mt = mint_type (ftype);
+                       mt = mono_mint_type (ftype);
 
                        emit_convert (td, td->sp - 1, ftype);
 
@@ -6622,7 +6680,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                                        goto exit;
                                }
 
-                               const gboolean vt = mint_type (m_class_get_byval_arg (klass)) == MINT_TYPE_VT;
+                               const gboolean vt = mono_mint_type (m_class_get_byval_arg (klass)) == MINT_TYPE_VT;
 
                                if (td->sp [-1].type == STACK_TYPE_R8 && m_class_get_byval_arg (klass)->type == MONO_TYPE_R4)
                                        interp_add_conv (td, td->sp - 1, NULL, STACK_TYPE_R4, MINT_CONV_R4_R8);
@@ -6767,7 +6825,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        token = read32 (td->ip + 1);
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
-                       switch (mint_type (m_class_get_byval_arg (klass))) {
+                       switch (mono_mint_type (m_class_get_byval_arg (klass))) {
                                case MINT_TYPE_I1:
                                        handle_ldelem (td, MINT_LDELEM_I1, STACK_TYPE_I4);
                                        break;
@@ -6813,7 +6871,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                                default: {
                                        GString *res = g_string_new ("");
                                        mono_type_get_desc (res, m_class_get_byval_arg (klass), TRUE);
-                                       g_print ("LDELEM: %s -> %d (%s)\n", m_class_get_name (klass), mint_type (m_class_get_byval_arg (klass)), res->str);
+                                       g_print ("LDELEM: %s -> %d (%s)\n", m_class_get_name (klass), mono_mint_type (m_class_get_byval_arg (klass)), res->str);
                                        g_string_free (res, TRUE);
                                        g_assert (0);
                                        break;
@@ -6849,7 +6907,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                        token = read32 (td->ip + 1);
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
-                       switch (mint_type (m_class_get_byval_arg (klass))) {
+                       switch (mono_mint_type (m_class_get_byval_arg (klass))) {
                                case MINT_TYPE_I1:
                                        handle_stelem (td, MINT_STELEM_I1);
                                        break;
@@ -6889,7 +6947,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                                default: {
                                        GString *res = g_string_new ("");
                                        mono_type_get_desc (res, m_class_get_byval_arg (klass), TRUE);
-                                       g_print ("STELEM: %s -> %d (%s)\n", m_class_get_name (klass), mint_type (m_class_get_byval_arg (klass)), res->str);
+                                       g_print ("STELEM: %s -> %d (%s)\n", m_class_get_name (klass), mono_mint_type (m_class_get_byval_arg (klass)), res->str);
                                        g_string_free (res, TRUE);
                                        g_assert (0);
                                        break;
@@ -7156,7 +7214,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                                goto_if_nok (error, exit);
                        }
                        mono_class_init_internal (klass);
-                       mt = mint_type (m_class_get_byval_arg (klass));
+                       mt = mono_mint_type (m_class_get_byval_arg (klass));
                        g_assert (mt == MINT_TYPE_VT);
                        size = mono_class_value_size (klass, NULL);
                        g_assert (size == sizeof(gpointer));
@@ -7354,7 +7412,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
                                        int param_offset = get_tos_offset (td);
 
                                        if (!MONO_TYPE_IS_VOID (info->sig->ret)) {
-                                               mt = mint_type (info->sig->ret);
+                                               mt = mono_mint_type (info->sig->ret);
                                                push_simple_type (td, stack_type [mt]);
                                                dreg = td->sp [-1].local;
                                        }
@@ -10593,7 +10651,7 @@ interp_alloc_offsets (TransformData *td)
                                                        td->locals [new_var].call = ins;
                                                        td->locals [new_var].flags |= INTERP_LOCAL_FLAG_CALL_ARGS;
 
-                                                       int mt = mint_type (td->locals [var].type);
+                                                       int mt = mono_mint_type (td->locals [var].type);
                                                        if (mt != MINT_TYPE_VT && num_pairs < MINT_MOV_PAIRS_MAX && var <= G_MAXUINT16 && new_var <= G_MAXUINT16) {
                                                                // We store these in the instruction data slots so we do this optimizations only if they fit
                                                                pair_sregs [num_pairs] = (guint16)var;
@@ -10629,7 +10687,7 @@ interp_alloc_offsets (TransformData *td)
                                                        set_var_live_range (td, pair_dregs [i], ins_index);
                                                }
                                                if (num_pairs == 1) {
-                                                       int mt = mint_type (td->locals [pair_sregs [0]].type);
+                                                       int mt = mono_mint_type (td->locals [pair_sregs [0]].type);
                                                        int opcode = get_mov_for_type (mt, FALSE);
                                                        InterpInst *new_inst = interp_insert_ins_bb (td, bb, ins->prev, opcode);
                                                        interp_ins_set_dreg (new_inst, pair_dregs [0]);
index 3b0a982..d13d10c 100644 (file)
@@ -127,6 +127,7 @@ const fn_signatures: SigLine[] = [
     [true, "mono_jiterp_get_opcode_value_table_entry", "number", ["number"]],
     [true, "mono_jiterp_get_simd_intrinsic", "number", ["number", "number"]],
     [true, "mono_jiterp_get_simd_opcode", "number", ["number", "number"]],
+    [true, "mono_jiterp_get_arg_offset", "number", ["number", "number", "number"]],
     ...legacy_interop_cwraps
 ];
 
@@ -250,6 +251,7 @@ export interface t_Cwraps {
     mono_jiterp_get_opcode_value_table_entry(opcode: number): number;
     mono_jiterp_get_simd_intrinsic(arity: number, index: number): VoidPtr;
     mono_jiterp_get_simd_opcode(arity: number, index: number): number;
+    mono_jiterp_get_arg_offset (imethod: number, sig: number, index: number): number;
 }
 
 const wrapped_c_functions: t_Cwraps = <any>{};
index 14651ad..ed94dc0 100644 (file)
@@ -5,7 +5,7 @@ import { mono_assert, MonoMethod, MonoType } from "./types";
 import { NativePointer } from "./types/emscripten";
 import { Module } from "./globals";
 import {
-    getU32_unaligned, _zero_region
+    setI32, getU32_unaligned, _zero_region
 } from "./memory";
 import { WasmOpcode } from "./jiterpreter-opcodes";
 import cwraps from "./cwraps";
@@ -36,6 +36,7 @@ typedef struct {
     ThreadContext *context; // 4
     gpointer orig_domain; // 8
     gpointer attach_cookie; // 12
+    int params_count; // 16
 } JiterpEntryDataHeader;
 */
 
@@ -231,7 +232,6 @@ function flush_wasm_entry_trampoline_jit_queue() {
             "interp_entry",
             {
                 "pData": WasmValtype.i32,
-                "sp_args": WasmValtype.i32,
                 "res": WasmValtype.i32,
             },
             WasmValtype.void, true
@@ -243,7 +243,7 @@ function flush_wasm_entry_trampoline_jit_queue() {
                 "result": WasmValtype.i32,
                 "value": WasmValtype.i32
             },
-            WasmValtype.i32, true
+            WasmValtype.void, true
         );
     } else
         builder.clear(constantSlots);
@@ -411,10 +411,10 @@ function flush_wasm_entry_trampoline_jit_queue() {
 }
 
 function append_stackval_from_data(
-    builder: WasmBuilder, type: MonoType, valueName: string
+    builder: WasmBuilder, imethod: number, type: MonoType, valueName: string, argIndex: number
 ) {
-    const stackvalSize = cwraps.mono_jiterp_get_size_of_stackval();
     const rawSize = cwraps.mono_jiterp_type_get_raw_value_size(type);
+    const offset = cwraps.mono_jiterp_get_arg_offset(imethod, 0, argIndex);
 
     switch (rawSize) {
         case 256: {
@@ -423,10 +423,7 @@ function append_stackval_from_data(
             builder.local(valueName);
 
             builder.appendU8(WasmOpcode.i32_store);
-            builder.appendMemarg(0, 2);
-
-            // Fixed stackval size
-            builder.i32_const(stackvalSize);
+            builder.appendMemarg(offset, 2);
             break;
         }
 
@@ -465,18 +462,18 @@ function append_stackval_from_data(
             }
 
             builder.appendU8(WasmOpcode.i32_store);
-            builder.appendMemarg(0, 2);
-
-            // Fixed stackval size
-            builder.i32_const(stackvalSize);
+            builder.appendMemarg(offset, 2);
             break;
         }
 
         default: {
-            // Call stackval_from_data to copy the value and get its size
+            // Call stackval_from_data to copy the value
             builder.ptr_const(type);
             // result
             builder.local("sp_args");
+            // apply offset
+            builder.i32_const(offset);
+            builder.appendU8(WasmOpcode.i32_add);
             // value
             builder.local(valueName);
 
@@ -484,11 +481,6 @@ function append_stackval_from_data(
             break;
         }
     }
-
-    // Value size is on the stack, add it to sp_args and update it
-    builder.local("sp_args");
-    builder.appendU8(WasmOpcode.i32_add);
-    builder.local("sp_args", WasmOpcode.set_local);
 }
 
 function generate_wasm_body(
@@ -505,6 +497,13 @@ function generate_wasm_body(
     const scratchBuffer = <any>Module._malloc(sizeOfJiterpEntryData);
     _zero_region(scratchBuffer, sizeOfJiterpEntryData);
 
+    // Initialize the parameter count in the data blob. This is used to calculate the new value of sp
+    //  before entering the interpreter
+    setI32(
+        scratchBuffer + getMemberOffset(JiterpMember.ParamsCount),
+        info.paramTypes.length + (info.hasThisReference ? 1 : 0)
+    );
+
     // the this-reference may be a boxed struct that needs to be unboxed, for example calling
     //  methods like object.ToString on structs will end up with the unbox flag set
     // instead of passing an extra 'unbox' argument to every wrapper, though, the flag is hidden
@@ -559,7 +558,7 @@ function generate_wasm_body(
 
     if (info.hasThisReference) {
         // null type for raw ptr copy
-        append_stackval_from_data(builder, <any>0, "this_arg");
+        append_stackval_from_data(builder, info.imethod, <any>0, "this_arg", 0);
     }
 
     /*
@@ -576,11 +575,10 @@ function generate_wasm_body(
 
     for (let i = 0; i < info.paramTypes.length; i++) {
         const type = <any>info.paramTypes[i];
-        append_stackval_from_data(builder, type, `arg${i}`);
+        append_stackval_from_data(builder, info.imethod, type, `arg${i}`, i + (info.hasThisReference ? 1 : 0));
     }
 
     builder.local("scratchBuffer");
-    builder.local("sp_args");
     if (info.hasReturnValue)
         builder.local("res");
     else
index 3067575..bc4df33 100644 (file)
@@ -1666,6 +1666,7 @@ export const enum JiterpMember {
     BackwardBranchOffsets = 10,
     BackwardBranchOffsetsCount = 11,
     ClauseDataOffsets = 12,
+    ParamsCount = 13,
 }
 
 const memberOffsets: { [index: number]: number } = {};