Merge pull request #2003 from esdrubal/seq_test_fix2
[mono.git] / mono / mini / mini-s390x.c
index 22e488ae8106d6aa53e23879b737e640ce40b791..657ee174d981764341c44fed9e5612b6304fc8df 100644 (file)
@@ -267,6 +267,7 @@ if (ins->inst_target_bb->native_offset) {                                   \
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-hwcap-s390x.h>
+#include <mono/utils/mono-threads.h>
 
 #include "mini-s390x.h"
 #include "cpu-s390x.h"
@@ -483,7 +484,7 @@ mono_arch_fregname (int reg) {
 /*------------------------------------------------------------------*/
 
 int
-mono_arch_get_argument_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *csig, 
+mono_arch_get_argument_info (MonoMethodSignature *csig, 
                             int param_count, 
                             MonoJitArgumentInfo *arg_info)
 {
@@ -510,7 +511,7 @@ mono_arch_get_argument_info (MonoGenericSharingContext *gsctx, MonoMethodSignatu
                if (csig->pinvoke)
                        size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
                else
-                       size = mini_type_stack_size (NULL, csig->params [k], &align);
+                       size = mini_type_stack_size (csig->params [k], &align);
 
                frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); 
                arg_info [k].pad = pad;
@@ -741,7 +742,7 @@ decodeParm(MonoType *type, void *curParm, int size)
        if (type->byref) {
                printf("[BYREF:%p], ", *((char **) curParm));
        } else {
-               simpleType = mono_type_get_underlying_type(type)->type;
+               simpleType = mini_get_underlying_type(type)->type;
 enum_parmtype:
                switch (simpleType) {
                        case MONO_TYPE_I :
@@ -790,20 +791,20 @@ enum_parmtype:
                        case MONO_TYPE_CLASS :
                        case MONO_TYPE_OBJECT : {
                                MonoObject *obj = *((MonoObject **) curParm);
-                               MonoClass *class;
+                               MonoClass *klass;
                                if ((obj) && (obj->vtable)) {
                                        printf("[CLASS/OBJ:");
-                                       class = obj->vtable->klass;
+                                       klass = obj->vtable->klass;
                                        printf("%p [%p] ",obj,curParm);
-                                       if (class == mono_defaults.string_class) {
+                                       if (klass == mono_defaults.string_class) {
                                                printf("[STRING:%p:%s]", 
                                                       obj, mono_string_to_utf8 ((MonoString *) obj));
-                                       } else if (class == mono_defaults.int32_class) { 
+                                       } else if (klass == mono_defaults.int32_class) { 
                                                printf("[INT32:%p:%d]", 
                                                        obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
                                        } else
                                                printf("[%s.%s:%p]", 
-                                                      class->name_space, class->name, obj);
+                                                      klass->name_space, klass->name, obj);
                                        printf("], ");
                                } else {
                                        printf("[OBJECT:null], ");
@@ -892,7 +893,7 @@ static void
 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
 {
        int i, oParm = 0, iParm = 0;
-       MonoClass *class;
+       MonoClass *klass;
        MonoObject *obj;
        MonoMethodSignature *sig;
        char *fname;
@@ -922,26 +923,26 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp)
        }
 
        if (sig->hasthis) {
-               gpointer *this = (gpointer *) rParm->gr[iParm];
-               obj = (MonoObject *) this;
+               gpointer *this_arg = (gpointer *) rParm->gr[iParm];
+               obj = (MonoObject *) this_arg;
                switch(method->klass->this_arg.type) {
                case MONO_TYPE_VALUETYPE:
                        if (obj) {
-                               guint64 *value = (guint64 *) ((uintptr_t)this + sizeof(MonoObject));
-                               printf("this:[value:%p:%016lx], ", this, *value);
+                               guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
+                               printf("this:[value:%p:%016lx], ", this_arg, *value);
                        } else 
                                printf ("this:[NULL], ");
                        break;
                case MONO_TYPE_STRING:
                        if (obj) {
                                if (obj->vtable) {
-                                       class = obj->vtable->klass;
-                                       if (class == mono_defaults.string_class) {
+                                       klass = obj->vtable->klass;
+                                       if (klass == mono_defaults.string_class) {
                                                printf ("this:[STRING:%p:%s], ", 
                                                        obj, mono_string_to_utf8 ((MonoString *)obj));
                                        } else {
                                                printf ("this:%p[%s.%s], ", 
-                                                       obj, class->name_space, class->name);
+                                                       obj, klass->name_space, klass->name);
                                        }
                                } else 
                                        printf("vtable:[NULL], ");
@@ -949,7 +950,7 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp)
                                printf ("this:[NULL], ");
                        break;
                default :
-                       printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this);
+                       printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
                }
                oParm++;
        }
@@ -1220,6 +1221,26 @@ handle_enum:
                }
        }
                break;
+       case MONO_TYPE_GENERICINST: {
+               printf("[GENERICINST]\n");
+       }
+               break;
+       case MONO_TYPE_MVAR: {
+               printf("[MVAR]\n");
+       }
+               break;
+       case MONO_TYPE_CMOD_REQD: {
+               printf("[CMOD_REQD]\n");
+       }
+               break;
+       case MONO_TYPE_CMOD_OPT: {
+               printf("[CMOD_OPT]\n");
+       }
+               break;
+       case MONO_TYPE_INTERNAL: {
+               printf("[INTERNAL]\n");
+       }
+               break;
        default:
                printf ("(unknown return type %x)", 
                        mono_method_signature (method)->ret->type);
@@ -1536,7 +1557,6 @@ get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
        gboolean is_pinvoke = sig->pinvoke;
        CallInfo *cinfo;
        size_data *sz;
-       MonoGenericSharingContext *gsctx = cfg ? cfg->generic_sharing_context : NULL;
 
        if (mp)
                cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
@@ -1564,8 +1584,7 @@ get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
        /* area that the callee will use.                           */
        /*----------------------------------------------------------*/
 
-       ret_type = mini_type_get_underlying_type (gsctx, sig->ret);
-       ret_type = mini_get_basic_type_from_generic (gsctx, ret_type);
+       ret_type = mini_get_underlying_type (sig->ret);
        simpleType = ret_type->type;
 enum_retvalue:
        switch (simpleType) {
@@ -1612,7 +1631,7 @@ enum_retvalue:
                                simpleType = mono_class_enum_basetype (klass)->type;
                                goto enum_retvalue;
                        }
-                       size = mini_type_stack_size_full (gsctx, &klass->byval_arg, NULL, sig->pinvoke);
+                       size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
        
                        cinfo->struct_ret = 1;
                        cinfo->ret.size   = size;
@@ -1643,7 +1662,7 @@ enum_retvalue:
        if (cinfo->struct_ret && !is_pinvoke && 
            (sig->hasthis || 
              (sig->param_count > 0 && 
-             MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (gsctx, sig->params [0]))))) {
+             MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
                if (sig->hasthis) {
                        cinfo->args[nParm].size = sizeof (gpointer);
                        add_general (&gr, sz, cinfo->args + nParm);
@@ -1705,7 +1724,7 @@ enum_retvalue:
                        continue;
                }
 
-               ptype = mini_type_get_underlying_type (gsctx, sig->params [i]);
+               ptype = mini_get_underlying_type (sig->params [i]);
                simpleType = ptype->type;
                cinfo->args[nParm].type = simpleType;
                switch (simpleType) {
@@ -1943,14 +1962,17 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        cfg->arch.bkchain_reg = -1;
 
        if (frame_reg != STK_BASE) 
-               cfg->used_int_regs |= 1 << frame_reg;           
+               cfg->used_int_regs |= (1 << frame_reg);         
+
+       if (cfg->uses_rgctx_reg)
+               cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
 
        sig     = mono_method_signature (cfg->method);
        
        cinfo   = get_call_info (cfg, cfg->mempool, sig);
 
        if (!cinfo->struct_ret) {
-               switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) {
+               switch (mini_get_underlying_type (sig->ret)->type) {
                case MONO_TYPE_VOID:
                        break;
                default:
@@ -2323,7 +2345,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                        t = sig->params [i - sig->hasthis];
                else
                        t = &mono_defaults.int_class->byval_arg;
-               t = mini_type_get_underlying_type (cfg->generic_sharing_context, t);
+               t = mini_get_underlying_type (t);
 
                in = call->args [i];
 
@@ -2539,8 +2561,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
 void
 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
 {
-       MonoType *ret = mini_type_get_underlying_type (cfg->generic_sharing_context,
-                               mono_method_signature (method)->ret);
+       MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
 
        if (!ret->byref) {
                if (ret->type == MONO_TYPE_R4) {
@@ -2639,8 +2660,7 @@ mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolea
                   saveOffset,
                   offset;
        MonoMethod *method = cfg->method;
-       int rtype = mini_type_get_underlying_type (cfg->generic_sharing_context,
-                       mono_method_signature (method)->ret)->type;
+       int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
 
        offset = code - cfg->native_code;
        /*-----------------------------------------*/
@@ -2834,15 +2854,20 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size,
        if (is_signed) {
                s390_cgdbr (code, dreg, 5, sreg);
                switch (size) {
-                       case 1:
-                               s390_lghi (code, s390_r0, 0);
-                               s390_lghi (code, s390_r13, 0xff);
-                               s390_ltgr (code, dreg, dreg);
-                               s390_jnl  (code, 4);
-                               s390_lghi (code, s390_r0, 0x80);
-                               s390_ngr  (code, dreg, s390_r13);
-                               s390_ogr  (code, dreg, s390_r0);
-                               break;
+               case 1:
+                       s390_ltgr (code, dreg, dreg);
+                       s390_jnl  (code, 4);
+                       s390_oill (code, dreg, 0x80);
+                       s390_lghi (code, s390_r0, 0xff);
+                       s390_ngr  (code, dreg, s390_r0);
+                       break;
+               case 2:
+                       s390_ltgr (code, dreg, dreg);
+                       s390_jnl  (code, 4);
+                       s390_oill (code, dreg, 0x8000);
+                       s390_llill(code, s390_r0, 0xffff);
+                       s390_ngr  (code, dreg, s390_r0);
+                       break;
                }
        } else {
                short *o[1];
@@ -2859,15 +2884,14 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size,
                PTRSLOT (code, o[0]);
                s390_cfdbr  (code, dreg, 5, sreg);
                switch (size) {
-                       case 1: 
-                               s390_lghi (code, s390_r0, 0xff);
-                               s390_ngr  (code, dreg, s390_r0);
-                               break;
-                       case 2:
-                               s390_lghi (code, s390_r0, -1);
-                               s390_srlg (code, s390_r0, s390_r0, 0, 16);
-                               s390_ngr  (code, dreg, s390_r0);
-                               break;
+               case 1: 
+                       s390_lghi (code, s390_r0, 0xff);
+                       s390_ngr  (code, dreg, s390_r0);
+                       break;
+               case 2:
+                       s390_llill(code, s390_r0, 0xffff);
+                       s390_ngr  (code, dreg, s390_r0);
+                       break;
                }
        }
        return code;
@@ -2926,24 +2950,20 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
        guint offset;
        guint8 *code = cfg->native_code + cfg->code_len;
        guint last_offset = 0;
-       int max_len, cpos, src2;
+       int max_len, src2;
 
        /* we don't align basic blocks of loops on s390 */
 
        if (cfg->verbose_level > 2)
                g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
 
-       cpos = bb->max_offset;
-
-       if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
-               //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
-               //g_assert (!mono_compile_aot);
-               //cpos += 6;
-               //if (bb->cil_code)
-               //      cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
-               /* this is not thread save, but good enough */
-               /* fixme: howto handle overflows? */
-               //x86_inc_mem (code, &cov->data [bb->dfn].count); 
+       if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
+               MonoProfileCoverageInfo *cov = cfg->coverage_info;
+               g_assert (!mono_compile_aot);
+               cov->data [bb->dfn].cil_code = bb->cil_code;
+               /* This is not thread save, but good enough */
+               S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
+               s390_alsi (code, 0, s390_r1, 1);
        }
 
        MONO_BB_FOR_EACH_INS (bb, ins) {
@@ -3827,20 +3847,30 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
                        s390_lgfr (code, ins->dreg, ins->sreg1);
                        break;
-               case OP_FMOVE: {
+               case OP_FMOVE:
                        if (ins->dreg != ins->sreg1) {
                                s390_ldr   (code, ins->dreg, ins->sreg1);
                        }
-               }
                        break;
-               case OP_FCONV_TO_R4: {
+               case OP_MOVE_F_TO_I8: 
+                       s390_lgdr (code, ins->dreg, ins->sreg1);
+                       break;
+               case OP_MOVE_I8_TO_F: 
+                       s390_ldgr (code, ins->dreg, ins->sreg1);
+                       break;
+               case OP_MOVE_F_TO_I4:
+                       s390_lgdr (code, ins->dreg, ins->sreg1);
+                       break;
+               case OP_MOVE_I4_TO_F: 
+                       s390_lgfr (code, s390_r0, ins->sreg1);
+                       s390_ldgr (code, ins->dreg, s390_r0);
+                       break;
+               case OP_FCONV_TO_R4:
                        s390_ledbr (code, ins->dreg, ins->sreg1);
                        s390_ldebr (code, ins->dreg, ins->dreg);
-               }
                        break;
-               case OP_S390_SETF4RET: {
+               case OP_S390_SETF4RET:
                        s390_ledbr (code, ins->dreg, ins->sreg1);
-               }
                        break;
                case OP_TLS_GET: {
                        if (s390_is_imm16 (ins->inst_offset)) {
@@ -4110,7 +4140,29 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
                        break;
                }
-       
+               case OP_GENERIC_CLASS_INIT: {
+                       static int byte_offset = -1;
+                       static guint8 bitmask;
+                       short int *jump;
+
+                       g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
+
+                       if (byte_offset < 0)
+                               mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
+
+                       s390_tm (code, ins->sreg1, byte_offset, bitmask);
+                       s390_jo (code, 0); CODEPTR(code, jump);
+
+                       mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+                                               "mono_generic_class_init");
+                       S390_CALL_TEMPLATE(code, s390_r14);
+
+                       PTRSLOT (code, jump);
+
+                       ins->flags |= MONO_INST_GC_CALLSITE;
+                       ins->backend.pc_offset = code - cfg->native_code;
+                       break;
+               }
                case OP_BR: 
                        EMIT_UNCOND_BRANCH(ins);
                        break;
@@ -4281,21 +4333,30 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                }
                        break;
                case OP_ICONV_TO_R_UN: {
-                       s390_cdfbr (code, ins->dreg, ins->sreg1);
-                       s390_ltr   (code, ins->sreg1, ins->sreg1);
-                       s390_jnl   (code, 8);
-                       S390_SET   (code, s390_r13, 0x41f0000000000000llu);
-                       s390_ldgr  (code, s390_f15, s390_r13);
-                       s390_adbr  (code, ins->dreg, s390_f15);
+                       if (facs.fpe) {
+                               s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
+                       } else {
+                               s390_llgfr (code, s390_r0, ins->sreg1);
+                               s390_cdgbr (code, ins->dreg, s390_r0);
+                       }
                }
                        break;
                case OP_LCONV_TO_R_UN: {
-                       s390_cdgbr (code, ins->dreg, ins->sreg1);
-                       s390_ltgr  (code, ins->sreg1, ins->sreg1);
-                       s390_jnl   (code, 8);
-                       S390_SET   (code, s390_r13, 0x41f0000000000000llu);
-                       s390_ldgr  (code, s390_f15, s390_r13);
-                       s390_adbr  (code, ins->dreg, s390_f15);
+                       if (facs.fpe) {
+                               s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
+                       } else {
+                               short int *jump;
+                               s390_cxgbr (code, s390_f12, ins->sreg1);
+                               s390_ltgr  (code, ins->sreg1, ins->sreg1);
+                               s390_jnl   (code, 0); CODEPTR(code, jump);
+                               S390_SET   (code, s390_r13, 0x403f000000000000llu);
+                               s390_lgdr  (code, s390_f13, s390_r13);
+                               s390_lzdr  (code, s390_f15);
+                               s390_axbr  (code, s390_f12, s390_f13);
+                               PTRSLOT(code, jump);
+                               s390_ldxbr (code, s390_f13, s390_f12);
+                               s390_ldr   (code, ins->dreg, s390_f13);
+                       }
                }
                        break;
                case OP_LCONV_TO_R4:
@@ -4310,28 +4371,61 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                }
                        break;
                case OP_FCONV_TO_I1:
-                       code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, TRUE);
+                       s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
+                       s390_ltgr  (code, ins->dreg, ins->dreg);
+                       s390_jnl   (code, 4);
+                       s390_oill  (code, ins->dreg, 0x80);
+                       s390_lghi  (code, s390_r0, 0xff);
+                       s390_ngr   (code, ins->dreg, s390_r0);
                        break;
                case OP_FCONV_TO_U1:
-                       code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
+                       if (facs.fpe) {
+                               s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
+                               s390_lghi  (code, s390_r0, 0xff);
+                               s390_ngr   (code, ins->dreg, s390_r0);
+                       } else {
+                               code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
+                       }
                        break;
                case OP_FCONV_TO_I2:
-                       code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, TRUE);
+                       s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
+                       s390_ltgr  (code, ins->dreg, ins->dreg);
+                       s390_jnl   (code, 4);
+                       s390_oill  (code, ins->dreg, 0x8000);
+                       s390_llill (code, s390_r0, 0xffff);
+                       s390_ngr   (code, ins->dreg, s390_r0);
                        break;
                case OP_FCONV_TO_U2:
-                       code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
+                       if (facs.fpe) {
+                               s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
+                               s390_llill  (code, s390_r0, 0xffff);
+                               s390_ngr    (code, ins->dreg, s390_r0);
+                       } else {
+                               code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
+                       }
                        break;
                case OP_FCONV_TO_I4:
                case OP_FCONV_TO_I:
-                       code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, TRUE);
+                       s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
                        break;
                case OP_FCONV_TO_U4:
                case OP_FCONV_TO_U:
-                       code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
+                       if (facs.fpe) {
+                               s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
+                       } else {
+                               code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
+                       }
                        break;
                case OP_FCONV_TO_I8:
                        s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
                        break;
+               case OP_FCONV_TO_U8:
+                       if (facs.fpe) {
+                               s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
+                       } else {
+                               code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
+                       }
+                       break;
                case OP_LCONV_TO_OVF_I: {
                        /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
                        short int *o[5];
@@ -4580,9 +4674,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
                }
                        break;  
-               case OP_MEMORY_BARRIER: {
-               }
+               case OP_MEMORY_BARRIER:
+                       s390_mem (code);
                        break;
+#if USE_COOP_GC
+               case OP_GC_SAFE_POINT: {
+                       guint8 *br;
+
+                       s390_chi (code, ins->sreg1, 1); 
+                       s390_je  (code, 0); CODEPTR(code, br);
+                       mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
+                                            mono_threads_state_poll);
+                       S390_CALL_TEMPLATE (code, s390_r14);
+                       PTRSLOT (code, br);
+                       break;
+               }
+#endif
                case OP_GC_LIVENESS_DEF:
                case OP_GC_LIVENESS_USE:
                case OP_GC_PARAM_SLOT_LIVENESS_DEF:
@@ -4603,8 +4710,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        g_assert_not_reached ();
                }
               
-               cpos += max_len;
-
                last_offset = offset;
        }
 
@@ -4639,8 +4744,8 @@ mono_arch_register_lowlevel_calls (void)
 /*------------------------------------------------------------------*/
 
 void
-mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, 
-                     guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors)
+mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, 
+                     guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
 {
        MonoJumpInfo *patch_info;
 
@@ -4662,9 +4767,10 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain,
                        case MONO_PATCH_INFO_METHOD:
                        case MONO_PATCH_INFO_INTERNAL_METHOD:
                        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
-                       case MONO_PATCH_INFO_CLASS_INIT:
-                       case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
                        case MONO_PATCH_INFO_RGCTX_FETCH:
+                       case MONO_PATCH_INFO_MONITOR_ENTER:
+                       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
+                       case MONO_PATCH_INFO_MONITOR_EXIT:
                        case MONO_PATCH_INFO_ABS: {
                                S390_EMIT_CALL (ip, target);
                                continue;
@@ -5555,9 +5661,7 @@ mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
 gpointer
 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
 {
-       MonoLMF *lmf = (MonoLMF *) ((gchar *) regs - sizeof(MonoLMF));
-
-       return (gpointer) lmf->gregs [s390_r2];
+       return (gpointer) regs [s390_r2];
 }
 
 /*========================= End of Function ========================*/
@@ -5604,7 +5708,7 @@ mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *cl
 /*------------------------------------------------------------------*/
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *code_len, gboolean aot)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
 {
        guint8 *code, *start;
 
@@ -5640,8 +5744,13 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
 
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
 
-       if (code_len)
-               *code_len = code - start;
+       if (has_target) {
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
+       } else {
+               char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
+               g_free (name);
+       }
 
        return start;
 }
@@ -5660,19 +5769,15 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
-       char *tramp_name;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len, TRUE);
-       res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
+       res = g_slist_prepend (res, info);
 
-       for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &code_len, TRUE);
-               tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i);
-               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
-               g_free (tramp_name);
+       for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
+               get_delegate_invoke_impl (&info, FALSE, i, TRUE);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -5703,10 +5808,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                if (cached)
                        return cached;
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL, FALSE);
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
+                       mono_tramp_info_register (info, NULL);
+               }
 
                mono_memory_barrier ();
 
@@ -5731,7 +5839,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL, FALSE);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
+                       mono_tramp_info_register (info, NULL);
                }
 
                mono_memory_barrier ();
@@ -5755,32 +5865,35 @@ gpointer
 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, 
                                            int offset, gboolean load_imt_reg)
 {
-       guint8 *code, *start;
-       int size = 20;
-
-       start = code = mono_global_codeman_reserve (size);
-
-       /*
-        * Replace the "this" argument with the target
-        */
-       s390_lgr  (code, s390_r1, s390_r2);
-       s390_lg   (code, s390_r2, s390_r1, 0, MONO_STRUCT_OFFSET(MonoDelegate, target));        
-       
-       /*
-        * Load the IMT register, if needed
-        */
-       if (load_imt_reg) {
-               s390_lg  (code, MONO_ARCH_IMT_REG, s390_r2, 0, MONO_STRUCT_OFFSET(MonoDelegate, method));
-       }
-
-       /*
-        * Load the vTable
-        */
-       s390_lg  (code, s390_r1, s390_r2, 0, MONO_STRUCT_OFFSET(MonoObject, vtable));
-       s390_agfi(code, s390_r1, offset);
-       s390_br  (code, s390_r1);
-
-       return(start);
+       guint8 *code, *start;
+       int size = 40;
+
+       start = code = mono_global_codeman_reserve (size);
+
+       /*
+       * Replace the "this" argument with the target
+       */
+       s390_lgr  (code, s390_r1, s390_r2);
+       s390_lg   (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));        
+
+       /*
+       * Load the IMT register, if needed
+       */
+       if (load_imt_reg) {
+               s390_lg  (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
+       }
+
+       /*
+       * Load the vTable
+       */
+       s390_lg  (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
+       if (offset != 0) {
+               s390_agfi(code, s390_r1, offset);
+       }
+       s390_lg  (code, s390_r1, 0, s390_r1, 0);
+       s390_br  (code, s390_r1);
+
+       return(start);
 }
 
 /*========================= End of Function ========================*/
@@ -5921,6 +6034,8 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
 
        g_assert (code - start <= size);
 
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return (start);
 }
 
@@ -5938,9 +6053,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
 MonoMethod*
 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
 {
-       MonoLMF *lmf = (MonoLMF *) ((gchar *) regs - sizeof(MonoLMF));
-
-       return ((MonoMethod *) lmf->gregs [MONO_ARCH_IMT_REG]);
+       return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
 }
 
 /*========================= End of Function ========================*/