X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Finterpreter%2Ftransform.c;h=149b45278501a1c8431a2004038564f7dc895383;hb=bdc40b7009ae83f1c43eb109a5c0cfd4a3dcd0d1;hp=a698aa50ab7a1b8b8aa133707b3f5f0f4537d5d6;hpb=1ac870838ebc90caf89e4027d63982324bba019b;p=mono.git diff --git a/mono/mini/interpreter/transform.c b/mono/mini/interpreter/transform.c index a698aa50ab7..149b4527850 100644 --- a/mono/mini/interpreter/transform.c +++ b/mono/mini/interpreter/transform.c @@ -18,6 +18,7 @@ #include #include "mintops.h" +#include "interp-internals.h" #include "interp.h" // TODO: export from marshal.c @@ -435,30 +436,40 @@ load_arg(TransformData *td, int n) { int mt; MonoClass *klass = NULL; - if (n == 0 && mono_method_signature (td->method)->hasthis) { - if (td->method->klass->valuetype) + MonoType *type; + + gboolean hasthis = mono_method_signature (td->method)->hasthis; + if (hasthis && n == 0) + type = &td->method->klass->byval_arg; + else + type = mono_method_signature (td->method)->params [hasthis ? n - 1 : n]; + + mt = mint_type (type); + if (mt == MINT_TYPE_VT) { + gint32 size; + klass = mono_class_from_mono_type (type); + if (mono_method_signature (td->method)->pinvoke) + size = mono_class_native_size (klass, NULL); + else + size = mono_class_value_size (klass, NULL); + + if (hasthis && n == 0) { mt = MINT_TYPE_P; - else { - mt = MINT_TYPE_O; - klass = td->method->klass; + ADD_CODE (td, MINT_LDARG_P); + ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */ + klass = NULL; + } else { + PUSH_VT (td, size); + ADD_CODE (td, MINT_LDARG_VT); + ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */ + WRITE32 (td, &size); } - ADD_CODE(td, MINT_LDTHIS); } else { - MonoType *type; - 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; - klass = mono_class_from_mono_type (type); - if (mono_method_signature (td->method)->pinvoke) - size = mono_class_native_size (klass, NULL); - else - size = mono_class_value_size (klass, NULL); - PUSH_VT(td, size); - ADD_CODE(td, MINT_LDARG_VT); - ADD_CODE(td, td->rtm->arg_offsets [n]); /* FIX for large offset */ - WRITE32(td, &size); + if (hasthis && n == 0) { + mt = MINT_TYPE_P; + ADD_CODE (td, MINT_LDARG_P); + ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */ + klass = NULL; } else { ADD_CODE(td, MINT_LDARG_I1 + (mt - MINT_TYPE_I1)); ADD_CODE(td, td->rtm->arg_offsets [n]); /* FIX for large offset */ @@ -474,29 +485,30 @@ store_arg(TransformData *td, int n) { int mt; CHECK_STACK (td, 1); - if (n == 0 && mono_method_signature (td->method)->hasthis) - ADD_CODE(td, MINT_STTHIS); - else { - MonoType *type; - 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; - g_error ("data.klass"); - 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); - ADD_CODE(td, MINT_STARG_VT); - ADD_CODE(td, n); - WRITE32(td, &size); - if (td->sp [-1].type == STACK_TYPE_VT) - POP_VT(td, size); - } else { - ADD_CODE(td, MINT_STARG_I1 + (mt - MINT_TYPE_I1)); - ADD_CODE(td, td->rtm->arg_offsets [n]); - } + MonoType *type; + + gboolean hasthis = mono_method_signature (td->method)->hasthis; + if (hasthis && n == 0) + type = &td->method->klass->byval_arg; + else + type = mono_method_signature (td->method)->params [n - !!hasthis]; + + mt = mint_type (type); + if (mt == MINT_TYPE_VT) { + gint32 size; + g_error ("data.klass"); + 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); + ADD_CODE(td, MINT_STARG_VT); + ADD_CODE(td, n); + WRITE32(td, &size); + if (td->sp [-1].type == STACK_TYPE_VT) + POP_VT(td, size); + } else { + ADD_CODE(td, MINT_STARG_I1 + (mt - MINT_TYPE_I1)); + ADD_CODE(td, td->rtm->arg_offsets [n]); } --td->sp; } @@ -504,11 +516,22 @@ store_arg(TransformData *td, int n) static void store_inarg(TransformData *td, int n) { - MonoType *type = mono_method_signature (td->method)->params [n]; + MonoType *type; + gboolean hasthis = mono_method_signature (td->method)->hasthis; + if (hasthis && n == 0) + type = &td->method->klass->byval_arg; + else + type = mono_method_signature (td->method)->params [n - !!hasthis]; + int mt = mint_type (type); + if (hasthis && n == 0) { + ADD_CODE (td, MINT_STINARG_P); + ADD_CODE (td, n); + return; + } if (mt == MINT_TYPE_VT) { - gint32 size; MonoClass *klass = mono_class_from_mono_type (type); + gint32 size; if (mono_method_signature (td->method)->pinvoke) size = mono_class_native_size (klass, NULL); else @@ -613,7 +636,7 @@ get_data_item_index (TransformData *td, void *ptr) } static void -interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoDomain *domain, MonoGenericContext *generic_context, unsigned char *is_bb_start, int body_start_offset) +interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoDomain *domain, MonoGenericContext *generic_context, unsigned char *is_bb_start, int body_start_offset, MonoClass *constrained_class) { MonoImage *image = method->klass->image; MonoMethodSignature *csignature; @@ -663,6 +686,46 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target csignature = mono_method_signature (target_method); } + if (constrained_class) { + if (constrained_class->enumtype && !strcmp (target_method->name, "GetHashCode")) { + /* Use the corresponding method from the base type to avoid boxing */ + MonoType *base_type = mono_class_enum_basetype (constrained_class); + g_assert (base_type); + constrained_class = mono_class_from_mono_type (base_type); + target_method = mono_class_get_method_from_name (constrained_class, target_method->name, 0); + g_assert (target_method); + } + } + + if (constrained_class) { + mono_class_setup_vtable (constrained_class); +#if DEBUG_INTERP + g_print ("CONSTRAINED.CALLVIRT: %s::%s. %s (%p) ->\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method); +#endif + target_method = mono_get_method_constrained_with_method (image, target_method, constrained_class, generic_context, &error); +#if DEBUG_INTERP + g_print (" : %s::%s. %s (%p)\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method); +#endif + mono_error_cleanup (&error); /* FIXME: don't swallow the error */ + mono_class_setup_vtable (target_method->klass); + + if (constrained_class->valuetype && (target_method->klass == mono_defaults.object_class || target_method->klass == mono_defaults.enum_class->parent || target_method->klass == mono_defaults.enum_class)) { + ADD_CODE (td, MINT_BOX); + ADD_CODE (td, get_data_item_index (td, constrained_class)); + ADD_CODE (td, csignature->param_count); + } else if (!constrained_class->valuetype) { + /* managed pointer on the stack, we need to deref that puppy */ + ADD_CODE (td, MINT_LDIND_I); + ADD_CODE (td, csignature->param_count); + } else { + g_assert (target_method->klass->valuetype); + virtual = FALSE; + } + } + + if (target_method) + mono_class_init (target_method->klass); + CHECK_STACK (td, csignature->param_count + csignature->hasthis); if (!calli && (!virtual || (target_method->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) && (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && @@ -678,7 +741,8 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target store_arg (td, i + csignature->hasthis); if (csignature->hasthis) { - ADD_CODE(td, MINT_STTHIS); + g_error ("STTHIS removal"); + // ADD_CODE(td, MINT_STTHIS); --td->sp; } ADD_CODE(td, MINT_BR_S); @@ -713,9 +777,9 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target target_method = mono_marshal_get_synchronized_wrapper (target_method); } g_assert (csignature->call_convention == MONO_CALL_DEFAULT || csignature->call_convention == MONO_CALL_C); - td->sp -= csignature->param_count + csignature->hasthis; + td->sp -= csignature->param_count + !!csignature->hasthis; for (i = 0; i < csignature->param_count; ++i) { - if (td->sp [i + csignature->hasthis].type == STACK_TYPE_VT) { + if (td->sp [i + !!csignature->hasthis].type == STACK_TYPE_VT) { gint32 size; MonoClass *klass = mono_class_from_mono_type (csignature->params [i]); if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE) @@ -780,6 +844,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) MonoImage *image = method->klass->image; MonoDomain *domain = mono_domain_get (); MonoGenericContext *generic_context = NULL; + MonoClass *constrained_class = NULL; MonoError error; int offset, mt; int i; @@ -853,8 +918,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) g_free (name); } + if (signature->hasthis) + store_inarg (&td, 0); for (i = 0; i < signature->param_count; i++) - store_inarg(&td, i); + store_inarg (&td, i + !!signature->hasthis); body_start_offset = td.new_ip - td.new_code; @@ -963,12 +1030,15 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) td.ip += 2; break; case CEE_LDARGA_S: { + /* NOTE: n includes this */ int n = ((guint8 *)td.ip)[1]; - if (n == 0 && signature->hasthis) + if (n == 0 && signature->hasthis) { + g_error ("LDTHISA: NOPE"); ADD_CODE(&td, MINT_LDTHISA); + } else { ADD_CODE(&td, MINT_LDARGA); - ADD_CODE(&td, td.rtm->arg_offsets [n - signature->hasthis]); + ADD_CODE(&td, td.rtm->arg_offsets [n]); } PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP); td.ip += 2; @@ -1111,7 +1181,8 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) case CEE_CALLVIRT: /* Fall through */ case CEE_CALLI: /* Fall through */ case CEE_CALL: { - interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset); + interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, constrained_class); + constrained_class = NULL; break; } case CEE_RET: { @@ -1127,7 +1198,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) if (td.sp > td.stack) g_warning ("%s.%s: CEE_RET: more values on stack: %d", td.method->klass->name, td.method->name, td.sp - td.stack); if (td.vt_sp != vt_size) - g_warning ("%s.%s: CEE_RET: value type stack: %d vs. %d", td.method->klass->name, td.method->name, td.vt_sp, vt_size); + g_error ("%s.%s: CEE_RET: value type stack: %d vs. %d", td.method->klass->name, td.method->name, td.vt_sp, vt_size); if (vt_size == 0) SIMPLE_OP(td, signature->ret->type == MONO_TYPE_VOID ? MINT_RET_VOID : MINT_RET); else { @@ -1313,6 +1384,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) case CEE_LDIND_I: CHECK_STACK (&td, 1); SIMPLE_OP (td, MINT_LDIND_I); + ADD_CODE (&td, 0); SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I); break; case CEE_LDIND_R4: @@ -1707,8 +1779,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) ADD_CODE(&td, MINT_LDOBJ); ADD_CODE(&td, get_data_item_index(&td, klass)); - g_error ("data.klass"); - if (klass->byval_arg.type == MONO_TYPE_VALUETYPE && !klass->byval_arg.data.klass->enumtype) { + if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) { size = mono_class_value_size (klass, NULL); PUSH_VT(&td, size); } @@ -1838,11 +1909,16 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) } else if (mono_class_is_nullable (klass)) { MonoMethod *target_method = mono_class_get_method_from_name (klass, "Unbox", 1); /* td.ip is incremented by interp_transform_call */ - interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset); + interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL); } else { - ADD_CODE(&td, MINT_UNBOX); - ADD_CODE(&td, get_data_item_index (&td, klass)); - SET_SIMPLE_TYPE (td.sp - 1, stack_type [mint_type (&klass->byval_arg)]); + int mt = mint_type (&klass->byval_arg); + ADD_CODE (&td, MINT_UNBOX); + ADD_CODE (&td, get_data_item_index (&td, klass)); + SET_TYPE (td.sp - 1, stack_type [mt], klass); + if (mt == MINT_TYPE_VT) { + int size = mono_class_value_size (klass, NULL); + PUSH_VT (&td, size); + } td.ip += 5; } @@ -1869,7 +1945,9 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) token = read32 (td.ip + 1); field = mono_field_from_token (image, token, &klass, generic_context); mono_class_init (klass); - mt = mint_type(field->type); + + MonoClass *field_klass = mono_class_from_mono_type (field->type); + mt = mint_type (&field_klass->byval_arg); if (klass->marshalbyref) { ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_LDRMFLD_VT : MINT_LDRMFLD); ADD_CODE(&td, get_data_item_index (&td, field)); @@ -1877,17 +1955,21 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) ADD_CODE(&td, MINT_LDFLD_I1 + mt - MINT_TYPE_I1); ADD_CODE(&td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset); } - klass = NULL; if (mt == MINT_TYPE_VT) { - g_error ("data.klass"); - int size = mono_class_value_size (field->type->data.klass, NULL); + int size = mono_class_value_size (field_klass, NULL); PUSH_VT(&td, size); WRITE32(&td, &size); - klass = field->type->data.klass; - } else if (mt == MINT_TYPE_O) - klass = mono_class_from_mono_type (field->type); + } + if (td.sp [-1].type == STACK_TYPE_VT) { + int size = mono_class_value_size (klass, NULL); + size = (size + 7) & ~7; + td.vt_sp -= size; + ADD_CODE (&td, MINT_VTRESULT); + ADD_CODE (&td, 0); + WRITE32 (&td, &size); + } td.ip += 5; - SET_TYPE(td.sp - 1, stack_type [mt], klass); + SET_TYPE(td.sp - 1, stack_type [mt], field_klass); break; } case CEE_STFLD: @@ -1904,8 +1986,8 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) ADD_CODE(&td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset); } if (mt == MINT_TYPE_VT) { - g_error ("data.klass"); - int size = mono_class_value_size (field->type->data.klass, NULL); + MonoClass *klass = mono_class_from_mono_type (field->type); + int size = mono_class_value_size (klass, NULL); POP_VT(&td, size); WRITE32(&td, &size); } @@ -1928,21 +2010,14 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) ADD_CODE(&td, get_data_item_index (&td, field)); klass = NULL; if (mt == MINT_TYPE_VT) { - g_error ("data.klass"); - int size = mono_class_value_size (field->type->data.klass, NULL); + MonoClass *klass = mono_class_from_mono_type (field->type); + int size = mono_class_value_size (klass, NULL); PUSH_VT(&td, size); WRITE32(&td, &size); klass = field->type->data.klass; } else { if (mt == MINT_TYPE_O) klass = mono_class_from_mono_type (field->type); - if (!domain->special_static_fields || !g_hash_table_lookup (domain->special_static_fields, field)) { - if (mt == MINT_TYPE_O) - td.new_ip [-2] = MINT_LDSFLD_O; - else if (mt == MINT_TYPE_I4) - td.new_ip [-2] = MINT_LDSFLD_I4; - } - ADD_CODE(&td, get_data_item_index (&td, mono_class_vtable (domain, field->parent))); } td.ip += 5; PUSH_TYPE(&td, stack_type [mt], klass); @@ -1955,10 +2030,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_STSFLD_VT : MINT_STSFLD); ADD_CODE(&td, get_data_item_index (&td, field)); if (mt == MINT_TYPE_VT) { - g_error ("data.klass"); - int size = mono_class_value_size (field->type->data.klass, NULL); - POP_VT(&td, size); - WRITE32(&td, &size); + MonoClass *klass = mono_class_from_mono_type (field->type); + int size = mono_class_value_size (klass, NULL); + POP_VT (&td, size); + WRITE32 (&td, &size); } td.ip += 5; --td.sp; @@ -2034,20 +2109,23 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) klass = (MonoClass *)mono_method_get_wrapper_data (method, token); else klass = mono_class_get_full (image, token, generic_context); - g_assert (klass->valuetype); if (mono_class_is_nullable (klass)) { MonoMethod *target_method = mono_class_get_method_from_name (klass, "Box", 1); /* td.ip is incremented by interp_transform_call */ - interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset); + interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL); + } else if (!klass->valuetype) { + /* already boxed, do nothing. */ + td.ip += 5; } else { - if (klass->byval_arg.type == MONO_TYPE_VALUETYPE && !klass->enumtype) { + if (mint_type (&klass->byval_arg) == MINT_TYPE_VT && !klass->enumtype) { size = mono_class_value_size (klass, NULL); size = (size + 7) & ~7; td.vt_sp -= size; } ADD_CODE(&td, MINT_BOX); ADD_CODE(&td, get_data_item_index (&td, klass)); + ADD_CODE (&td, 0); SET_TYPE(td.sp - 1, STACK_TYPE_O, klass); td.ip += 5; } @@ -2166,6 +2244,39 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) --td.sp; SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_O); break; + case CEE_LDELEM: + CHECK_STACK (&td, 2); + token = read32 (td.ip + 1); + klass = mono_class_get_full (image, token, generic_context); + switch (mint_type (&klass->byval_arg)) { + case MINT_TYPE_I4: + ENSURE_I4 (&td, 1); + SIMPLE_OP (td, MINT_LDELEM_I4); + --td.sp; + SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4); + break; + case MINT_TYPE_VT: { + int size = mono_class_value_size (klass, NULL); + ENSURE_I4 (&td, 1); + SIMPLE_OP (td, MINT_LDELEM_VT); + ADD_CODE (&td, get_data_item_index (&td, klass)); + WRITE32 (&td, &size); + --td.sp; + SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_VT); + PUSH_VT (&td, size); + break; + } + default: { + GString *res = g_string_new (""); + mono_type_get_desc (res, &klass->byval_arg, TRUE); + g_print ("LDELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str); + g_string_free (res, TRUE); + g_assert (0); + break; + } + } + td.ip += 4; + break; case CEE_STELEM_I: CHECK_STACK (&td, 3); ENSURE_I4 (&td, 2); @@ -2214,10 +2325,39 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) SIMPLE_OP (td, MINT_STELEM_REF); td.sp -= 3; break; + case CEE_STELEM: + CHECK_STACK (&td, 3); + ENSURE_I4 (&td, 2); + token = read32 (td.ip + 1); + klass = mono_class_get_full (image, token, generic_context); + switch (mint_type (&klass->byval_arg)) { + case MINT_TYPE_I4: + SIMPLE_OP (td, MINT_STELEM_I4); + break; + case MINT_TYPE_O: + SIMPLE_OP (td, MINT_STELEM_REF); + break; + case MINT_TYPE_VT: { + int size = mono_class_value_size (klass, NULL); + SIMPLE_OP (td, MINT_STELEM_VT); + ADD_CODE (&td, get_data_item_index (&td, klass)); + WRITE32 (&td, &size); + POP_VT (&td, size); + break; + } + default: { + GString *res = g_string_new (""); + mono_type_get_desc (res, &klass->byval_arg, TRUE); + g_print ("STELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str); + g_string_free (res, TRUE); + g_assert (0); + break; + } + } + td.ip += 4; + td.sp -= 3; + break; #if 0 - case CEE_LDELEM: - case CEE_STELEM: - case CEE_CONV_OVF_U1: case CEE_CONV_OVF_I8: @@ -2454,7 +2594,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) switch (*td.ip) { case CEE_MONO_CALLI_EXTRA_ARG: /* Same as CEE_CALLI, llvm specific */ - interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset); + interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, NULL); break; case CEE_MONO_ICALL: { guint32 token; @@ -2692,11 +2832,13 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) break; case CEE_LDARGA: { int n = read16 (td.ip + 1); - if (n == 0 && signature->hasthis) + if (n == 0 && signature->hasthis) { + g_error ("LDTHISA: NOPE"); ADD_CODE(&td, MINT_LDTHISA); + } else { ADD_CODE(&td, MINT_LDARGA); - ADD_CODE(&td, td.rtm->arg_offsets [n - signature->hasthis]); /* FIX for large offsets */ + ADD_CODE(&td, td.rtm->arg_offsets [n]); /* FIX for large offsets */ } PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP); td.ip += 3; @@ -2765,16 +2907,12 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start) td.sp -= 3; ++td.ip; break; -#if 0 - case CEE_CONSTRAINED_: { - guint32 token; - /* FIXME: implement */ - ++ip; - token = read32 (ip); - ip += 4; + case CEE_CONSTRAINED_: + token = read32 (td.ip + 1); + constrained_class = mono_class_get_full (image, token, generic_context); + mono_class_init (constrained_class); + td.ip += 5; break; - } -#endif case CEE_INITBLK: CHECK_STACK(&td, 3); ADD_CODE(&td, MINT_INITBLK); @@ -2939,6 +3077,7 @@ 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 && (! mono_method_signature (method)->hasthis || method->klass->rank == 0)) { nm = mono_marshal_get_native_wrapper (method, TRUE, FALSE); + signature = mono_method_signature (nm); } else { const char *name = method->name; if (method->klass->parent == mono_defaults.multicastdelegate_class) { @@ -3104,7 +3243,17 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont runtime_method->locals_size = offset; g_assert (runtime_method->locals_size < 65536); offset = 0; - runtime_method->arg_offsets = g_malloc(signature->param_count * sizeof(guint32)); + runtime_method->arg_offsets = g_malloc ((!!signature->hasthis + signature->param_count) * sizeof(guint32)); + + if (signature->hasthis) { + g_assert (!signature->pinvoke); + size = mono_type_stack_size (&method->klass->byval_arg, &align); + offset += align - 1; + offset &= ~(align - 1); + runtime_method->arg_offsets [0] = offset; + offset += size; + } + for (i = 0; i < signature->param_count; ++i) { if (signature->pinvoke) { guint32 dummy; @@ -3115,7 +3264,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont size = mono_type_stack_size (signature->params [i], &align); offset += align - 1; offset &= ~(align - 1); - runtime_method->arg_offsets [i] = offset; + runtime_method->arg_offsets [i + !!signature->hasthis] = offset; offset += size; } offset = (offset + 7) & ~7;