Wed Aug 20 13:04:53 CEST 2003 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / mini.c
index a30e352718965c4ddc9d4984a9cb151a02054784..fec74a8337a9c1b90b13616b8e8f52e4b103baf3 100644 (file)
@@ -94,8 +94,6 @@ gboolean mono_jit_trace_calls = FALSE;
 gboolean mono_break_on_exc = FALSE;
 gboolean mono_compile_aot = FALSE;
 
-CRITICAL_SECTION *metadata_section = NULL;
-
 static int mini_verbose = 0;
 
 #ifdef MONO_USE_EXC_TABLES
@@ -780,6 +778,10 @@ handle_enum:
                return CEE_LDOBJ;
        case MONO_TYPE_TYPEDBYREF:
                return CEE_LDOBJ;
+       case MONO_TYPE_GENERICINST:
+               if (type->data.generic_inst->generic_type->type == MONO_TYPE_VALUETYPE)
+                       return CEE_LDOBJ;
+               return CEE_LDIND_REF;
        default:
                g_error ("unknown type 0x%02x in type_to_ldind", type->type);
        }
@@ -833,6 +835,10 @@ handle_enum:
                return CEE_STOBJ;
        case MONO_TYPE_TYPEDBYREF:
                return CEE_STOBJ;
+       case MONO_TYPE_GENERICINST:
+               if (type->data.generic_inst->generic_type->type == MONO_TYPE_VALUETYPE)
+                       return CEE_STOBJ;
+               return CEE_STIND_REF;
        default:
                g_error ("unknown type 0x%02x in type_to_stind", type->type);
        }
@@ -898,6 +904,14 @@ handle_enum:
                inst->klass = mono_defaults.typed_reference_class;
                inst->type = STACK_VTYPE;
                return;
+       case MONO_TYPE_GENERICINST:
+               if (type->data.generic_inst->generic_type->type == MONO_TYPE_VALUETYPE) {
+                       inst->klass = mono_class_from_mono_type (type);
+                       inst->type = STACK_VTYPE;
+               } else {
+                       inst->type = STACK_OBJ;
+               }
+               return;
        default:
                g_error ("unknown type 0x%02x in eval stack type", type->type);
        }
@@ -1287,6 +1301,7 @@ mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
                cfg->vars = (MonoMethodVar **)g_realloc (cfg->vars, sizeof (MonoMethodVar*) * cfg->varinfo_count);      
        }
 
+       /*g_print ("created temp %d of type 0x%x\n", num, type->type);*/
        mono_jit_stats.allocate_var++;
 
        MONO_INST_NEW (cfg, inst, opcode);
@@ -1780,6 +1795,7 @@ mono_emit_call_args (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethodSignatu
                     MonoInst **args, int calli, int virtual, const guint8 *ip, gboolean to_end)
 {
        MonoCallInst *call;
+       MonoInst *arg;
        int i;
 
        MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (sig->ret, calli, virtual));
@@ -1789,15 +1805,16 @@ mono_emit_call_args (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethodSignatu
        call->signature = sig;
        call = mono_arch_call_opcode (cfg, bblock, call, virtual);
 
-       for (i = 0; i < (sig->param_count + sig->hasthis); ++i) {
-               if (call->args [i]) {
-                       if (!call->args [i]->cil_code)
-                               call->args [i]->cil_code = ip;
-                       if (to_end)
-                               mono_add_ins_to_end (bblock, call->args [i]);
-                       else
-                               MONO_ADD_INS (bblock, call->args [i]);
-               }
+       for (arg = call->out_args; arg;) {
+               MonoInst *narg = arg->next;
+               arg->next = NULL;
+               if (!arg->cil_code)
+                       arg->cil_code = ip;
+               if (to_end)
+                       mono_add_ins_to_end (bblock, arg);
+               else
+                       MONO_ADD_INS (bblock, arg);
+               arg = narg;
        }
        return call;
 }
@@ -1874,6 +1891,7 @@ static void
 mono_emulate_opcode (MonoCompile *cfg, MonoInst *tree, MonoInst **iargs, MonoJitICallInfo *info)
 {
        MonoInst *ins, *temp = NULL, *store, *load;
+       MonoInst *last_arg = NULL;
        int i, nargs;
        MonoCallInst *call;
 
@@ -1899,23 +1917,21 @@ mono_emulate_opcode (MonoCompile *cfg, MonoInst *tree, MonoInst **iargs, MonoJit
 
        nargs = info->sig->param_count + info->sig->hasthis;
 
-       for (i = 1; i < nargs; i++) {
-               call->args [i - 1]->next = call->args [i];
-       }
+       for (last_arg = call->out_args; last_arg && last_arg->next; last_arg = last_arg->next) ;
 
        if (nargs)
-               call->args [nargs - 1]->next = store;
+               last_arg->next = store;
 
        if (cfg->prev_ins) {
                store->next = cfg->prev_ins->next;
                if (nargs)
-                       cfg->prev_ins->next =  call->args [0];
+                       cfg->prev_ins->next = call->out_args;
                else
                        cfg->prev_ins->next = store;
        } else {
                store->next = cfg->cbb->code;
                if (nargs)              
-                       cfg->cbb->code = call->args [0];
+                       cfg->cbb->code = call->out_args;
                else
                        cfg->cbb->code = store;
        }
@@ -2020,6 +2036,13 @@ handle_initobj (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *dest, const
                MONO_ADD_INS (bblock, ins);
                break;
        default:
+               if (n <= sizeof (gpointer) * 5) {
+                       ins->opcode = OP_MEMSET;
+                       ins->inst_imm = 0;
+                       ins->unused = n;
+                       MONO_ADD_INS (bblock, ins);
+                       break;
+               }
                handle_loaded_temps (cfg, bblock, stack_start, sp);
                NEW_ICONST (cfg, ins, n);
                iargs [0] = dest;
@@ -2325,6 +2348,9 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
 #define CHECK_STACK(num) if ((sp - stack_start) < (num)) goto unverified
 #define CHECK_STACK_OVF(num) if (((sp - stack_start) + (num)) > header->max_stack) goto unverified
 
+#define TYPE_PARAM_TO_TYPE(num) (method->klass->generic_inst->data.generic_inst->type_argv [(num)])
+#define TYPE_PARAM_TO_CLASS(num) (mono_class_from_mono_type (TYPE_PARAM_TO_TYPE ((num))))
+
 /* offset from br.s -> br like opcodes */
 #define BIG_BRANCH_OFFSET 13
 
@@ -2401,6 +2427,19 @@ unverified:
        return 1;
 }
 
+static MonoClassField *
+get_generic_field_inst (MonoClassField *field, MonoClass *klass, MonoClass **retclass)
+{
+       int i;
+       for (i = 0; i < field->parent->field.count; ++i) {
+               if (field == &field->parent->fields [i]) {
+                       *retclass = klass;
+                       return &klass->fields [i];
+               }
+       }
+       return NULL;
+}
+
 /*
  * mono_method_to_ir: translates IL into basic blocks containing trees
  */
@@ -2445,6 +2484,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                bbhash = g_hash_table_new (g_direct_hash, NULL);
        }
 
+       if (cfg->verbose_level > 2)
+               g_print ("method to IR %s\n", mono_method_full_name (method, TRUE));
+
        if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
                cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
 
@@ -3404,7 +3446,53 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ip++;
                        break;
                case CEE_CPOBJ:
-                       g_error ("opcode 0x%02x not handled", *ip);
+                       CHECK_STACK (2);
+                       token = read32 (ip + 1);
+                       if (method->wrapper_type != MONO_WRAPPER_NONE)
+                               klass = mono_method_get_wrapper_data (method, token);
+                       else
+                               klass = mono_class_get (image, token);
+
+                       mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+                       sp -= 2;
+                       if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                               MonoInst *store, *load;
+                               MONO_INST_NEW (cfg, load, CEE_LDIND_REF);
+                               load->cil_code = ip;
+                               load->inst_i0 = sp [1];
+                               load->type = ldind_type [CEE_LDIND_REF];
+                               load->flags |= ins_flag;
+                               MONO_INST_NEW (cfg, store, CEE_STIND_REF);
+                               store->cil_code = ip;
+                               handle_loaded_temps (cfg, bblock, stack_start, sp);
+                               MONO_ADD_INS (bblock, store);
+                               store->inst_i0 = sp [0];
+                               store->inst_i1 = load;
+                               store->flags |= ins_flag;
+                       } else {
+                               n = mono_class_value_size (klass, NULL);
+                               if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
+                                       MonoInst *copy;
+                                       MONO_INST_NEW (cfg, copy, OP_MEMCPY);
+                                       copy->inst_left = sp [0];
+                                       copy->inst_right = sp [1];
+                                       copy->cil_code = ip;
+                                       copy->unused = n;
+                                       MONO_ADD_INS (bblock, copy);
+                               } else {
+                                       MonoInst *iargs [3];
+                                       iargs [0] = sp [0];
+                                       iargs [1] = sp [1];
+                                       NEW_ICONST (cfg, iargs [2], n);
+                                       iargs [2]->cil_code = ip;
+
+                                       mono_emit_jit_icall (cfg, bblock, helper_memcpy, iargs, ip);
+                               }
+                       }
+                       ins_flag = 0;
+                       ip += 5;
                        break;
                case CEE_LDOBJ: {
                        MonoInst *iargs [3];
@@ -3417,6 +3505,19 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                klass = mono_class_get (image, token);
 
                        mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+                       if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                               MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
+                               ins->cil_code = ip;
+                               ins->inst_i0 = sp [0];
+                               ins->type = ldind_type [CEE_LDIND_REF];
+                               ins->flags |= ins_flag;
+                               ins_flag = 0;
+                               *sp++ = ins;
+                               ip += 5;
+                               break;
+                       }
                        n = mono_class_value_size (klass, NULL);
                        ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
                        NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
@@ -3438,6 +3539,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        NEW_TEMPLOAD (cfg, *sp, ins->inst_c0);
                        ++sp;
                        ip += 5;
+                       ins_flag = 0;
                        inline_costs += 1;
                        break;
                }
@@ -3529,7 +3631,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        } else {
                                                MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
                                                NEW_PCONST (cfg, iargs [0], vtable);
-                                               temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
+                                               if (cmethod->klass->has_finalize || cmethod->klass->marshalbyref || (cfg->prof_options & MONO_PROFILE_ALLOCATIONS))
+                                                       temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
+                                               else
+                                                       temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_fast, iargs, ip);
                                        }
                                        NEW_TEMPLOAD (cfg, *sp, temp);
                                }
@@ -3588,6 +3693,73 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ip += 5;
                        *sp++ = ins;
                        break;
+               case CEE_UNBOX_ANY: {
+                       MonoInst *add, *vtoffset;
+                       MonoInst *iargs [3];
+
+                       CHECK_STACK (1);
+                       --sp;
+                       token = read32 (ip + 1);
+                       if (method->wrapper_type != MONO_WRAPPER_NONE)
+                               klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
+                       else 
+                               klass = mono_class_get (image, token);
+                       mono_class_init (klass);
+
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+
+                       if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                               /* CASTCLASS */
+                               MONO_INST_NEW (cfg, ins, CEE_CASTCLASS);
+                               ins->type = STACK_OBJ;
+                               ins->inst_left = *sp;
+                               ins->klass = klass;
+                               ins->inst_newa_class = klass;
+                               ins->cil_code = ip;
+                               *sp++ = ins;
+                               ip += 5;
+                               break;
+                       }
+
+                       MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
+                       ins->type = STACK_OBJ;
+                       ins->inst_left = *sp;
+                       ins->klass = klass;
+                       ins->inst_newa_class = klass;
+                       ins->cil_code = ip;
+
+                       MONO_INST_NEW (cfg, add, CEE_ADD);
+                       NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
+                       add->inst_left = ins;
+                       add->inst_right = vtoffset;
+                       add->type = STACK_MP;
+                       *sp = add;
+                       ip += 5;
+                       /* LDOBJ impl */
+                       n = mono_class_value_size (klass, NULL);
+                       ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
+                       NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
+                       if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
+                               MonoInst *copy;
+                               MONO_INST_NEW (cfg, copy, OP_MEMCPY);
+                               copy->inst_left = iargs [0];
+                               copy->inst_right = *sp;
+                               copy->cil_code = ip;
+                               copy->unused = n;
+                               MONO_ADD_INS (bblock, copy);
+                       } else {
+                               iargs [1] = *sp;
+                               NEW_ICONST (cfg, iargs [2], n);
+                               iargs [2]->cil_code = ip;
+
+                               mono_emit_jit_icall (cfg, bblock, helper_memcpy, iargs, ip);
+                       }
+                       NEW_TEMPLOAD (cfg, *sp, ins->inst_c0);
+                       ++sp;
+                       inline_costs += 2;
+                       break;
+               }
                case CEE_UNBOX: {
                        MonoInst *add, *vtoffset;
 
@@ -3600,6 +3772,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                klass = mono_class_get (image, token);
                        mono_class_init (klass);
 
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
 
                        MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
                        ins->type = STACK_OBJ;
@@ -3624,6 +3798,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        klass = mono_class_get (image, read32 (ip + 1));
                        mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
                        ins->type = STACK_OBJ;
                        ins->inst_left = *sp;
                        ins->klass = klass;
@@ -3663,6 +3839,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        //      goto unverified;
                        token = read32 (ip + 1);
                        field = mono_field_from_token (image, token, &klass);
+                       if (field->parent->gen_params)
+                               field = get_generic_field_inst (field, method->klass, &klass);
                        mono_class_init (klass);
 
                        foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
@@ -3956,6 +4134,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        else
                                klass = mono_class_get (image, token);
                        mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
                        n = mono_type_to_stind (&klass->byval_arg);
                        if (n == CEE_STOBJ) {
                                handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE);
@@ -3986,12 +4166,28 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        else
                                klass = mono_class_get (image, token);
                        mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
 
+                       if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                               *sp = val;
+                               ip += 5;
+                               break;
+                       }
                        /* much like NEWOBJ */
-                       NEW_DOMAINCONST (cfg, iargs [0]);
-                       NEW_CLASSCONST (cfg, iargs [1], klass);
-                       
-                       temp = mono_emit_jit_icall (cfg, bblock, mono_object_new, iargs, ip);
+                       if ((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot) {
+                               NEW_DOMAINCONST (cfg, iargs [0]);
+                               NEW_CLASSCONST (cfg, iargs [1], klass);
+
+                               temp = mono_emit_jit_icall (cfg, bblock, mono_object_new, iargs, ip);
+                       } else {
+                               MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
+                               NEW_PCONST (cfg, iargs [0], vtable);
+                               if (1 || klass->has_finalize || (cfg->prof_options & MONO_PROFILE_ALLOCATIONS))
+                                       temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
+                               else
+                                       temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_fast, iargs, ip);
+                       }
                        NEW_TEMPLOAD (cfg, load, temp);
                        NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
                        MONO_INST_NEW (cfg, add, CEE_ADD);
@@ -4034,6 +4230,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                klass = mono_class_get (image, token);
 
                        mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
                        ins->inst_newa_class = klass;
                        ins->inst_newa_len = *sp;
                        ins->type = STACK_OBJ;
@@ -4055,11 +4253,32 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        sp -= 2;
                        klass = mono_class_get (image, read32 (ip + 1));
                        mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
                        NEW_LDELEMA (cfg, ins, sp, klass);
                        ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 5;
                        break;
+               case CEE_LDELEM: {
+                       MonoInst *load;
+                       CHECK_STACK (2);
+                       sp -= 2;
+                       token = read32 (ip + 1);
+                       klass = mono_class_get (image, token);
+                       mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+                       NEW_LDELEMA (cfg, load, sp, klass);
+                       load->cil_code = ip;
+                       MONO_INST_NEW (cfg, ins, mono_type_to_ldind (&klass->byval_arg));
+                       ins->cil_code = ip;
+                       ins->inst_left = load;
+                       *sp++ = ins;
+                       type_to_eval_stack_type (&klass->byval_arg, ins);
+                       ip += 5;
+                       break;
+               }
                case CEE_LDELEM_I1:
                case CEE_LDELEM_U1:
                case CEE_LDELEM_I2:
@@ -4115,7 +4334,44 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ++ip;
                        handle_loaded_temps (cfg, bblock, stack_start, sp);
                        MONO_ADD_INS (bblock, ins);
-                       /* FIXME: add the implicit STELEM_REF castclass */
+                       inline_costs += 1;
+                       cfg->disable_ssa = TRUE;
+                       break;
+               }
+               case CEE_STELEM: {
+                       MonoInst *load;
+                       /*
+                        * translate to:
+                        * stind.x (ldelema (array, index), val)
+                        * ldelema does the bounds check
+                        */
+                       CHECK_STACK (3);
+                       sp -= 3;
+                       token = read32 (ip + 1);
+                       klass = mono_class_get (image, token);
+                       mono_class_init (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VAR)
+                               klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+                       if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                               MonoInst *iargs [3];
+                               handle_loaded_temps (cfg, bblock, stack_start, sp);
+
+                               iargs [2] = sp [2];
+                               iargs [1] = sp [1];
+                               iargs [0] = sp [0];
+                       
+                               mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+                       } else {
+                               NEW_LDELEMA (cfg, load, sp, klass);
+                               load->cil_code = ip;
+                               MONO_INST_NEW (cfg, ins, mono_type_to_stind (&klass->byval_arg));
+                               ins->cil_code = ip;
+                               ins->inst_left = load;
+                               ins->inst_right = sp [2];
+                               handle_loaded_temps (cfg, bblock, stack_start, sp);
+                               MONO_ADD_INS (bblock, ins);
+                       }
+                       ip += 5;
                        inline_costs += 1;
                        cfg->disable_ssa = TRUE;
                        break;
@@ -4728,10 +4984,31 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        klass = mono_method_get_wrapper_data (method, token);
                                else
                                        klass = mono_class_get (image, token);
-                               handle_initobj (cfg, bblock, *sp, NULL, klass, stack_start, sp);
+                               if (klass->byval_arg.type == MONO_TYPE_VAR)
+                                       klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+                               if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                                       MonoInst *store, *load;
+                                       NEW_PCONST (cfg, load, NULL);
+                                       load->cil_code = ip;
+                                       load->type = STACK_OBJ;
+                                       MONO_INST_NEW (cfg, store, CEE_STIND_REF);
+                                       store->cil_code = ip;
+                                       handle_loaded_temps (cfg, bblock, stack_start, sp);
+                                       MONO_ADD_INS (bblock, store);
+                                       store->inst_i0 = sp [0];
+                                       store->inst_i1 = load;
+                                       break;
+                               } else {
+                                       handle_initobj (cfg, bblock, *sp, NULL, klass, stack_start, sp);
+                               }
                                ip += 6;
                                inline_costs += 1;
                                break;
+                       case CEE_CONSTRAINED_:
+                               /* FIXME: implement */
+                               token = read32 (ip + 2);
+                               ip += 6;
+                               break;
                        case CEE_CPBLK:
                        case CEE_INITBLK: {
                                MonoInst *iargs [3];
@@ -4750,6 +5027,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                inline_costs += 1;
                                break;
                        }
+                       case CEE_NO_:
+                               if (ip [2] & 0x1)
+                                       ins_flag |= MONO_INST_NOTYPECHECK;
+                               if (ip [2] & 0x2)
+                                       ins_flag |= MONO_INST_NORANGECHECK;
+                               /* we ignore the no-nullcheck for now since we
+                                * really do it explicitly only when doing callvirt->call
+                                */
+                               ip += 3;
+                               break;
                        case CEE_RETHROW: {
                                MonoInst *load;
                                /* FIXME: check we are in a catch handler */
@@ -4767,6 +5054,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        case CEE_SIZEOF:
                                CHECK_STACK_OVF (1);
                                token = read32 (ip + 2);
+                               /* FIXXME: handle generics. */
                                if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
                                        MonoType *type = mono_type_create_from_typespec (image, token);
                                        token = mono_type_size (type, &align);
@@ -4784,6 +5072,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        case CEE_REFANYTYPE:
                                g_error ("opcode 0xfe 0x%02x not handled", ip [1]);
                                break;
+                       case CEE_READONLY_:
+                               ip += 2;
+                               break;
                        default:
                                g_error ("opcode 0xfe 0x%02x not handled", ip [1]);
                        }
@@ -5318,8 +5609,7 @@ decompose_foreach (MonoInst *tree, gpointer data)
                        info = newarr_info;
                }
                else {
-                       MonoVTable *vtable = mono_class_vtable (cfg->domain, 
-                                                                                                       mono_array_class_get (&tree->inst_newa_class->byval_arg, 1));
+                       MonoVTable *vtable = mono_class_vtable (cfg->domain, mono_array_class_get (tree->inst_newa_class, 1));
 
                        NEW_PCONST (cfg, iargs [0], vtable);
                        iargs [1] = tree->inst_newa_len;
@@ -5510,28 +5800,40 @@ mono_thread_abort (MonoObject *obj)
 {
        MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
        
-       g_free (jit_tls);
+       /* handle_remove should be eventually called for this thread, too
+       g_free (jit_tls);*/
 
        ExitThread (-1);
 }
 
 static void
-mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
+setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
 {
        MonoJitTlsData *jit_tls;
        MonoLMF *lmf;
+       MonoThread *thread;
 
        jit_tls = g_new0 (MonoJitTlsData, 1);
 
        TlsSetValue (mono_jit_tls_id, jit_tls);
 
-       jit_tls->abort_func = mono_thread_abort;
+       jit_tls->abort_func = abort_func;
        jit_tls->end_of_stack = stack_start;
 
        lmf = g_new0 (MonoLMF, 1);
        lmf->ebp = -1;
 
-       jit_tls->lmf = lmf;
+       jit_tls->lmf = jit_tls->first_lmf = lmf;
+
+       thread = mono_thread_current ();
+       if (thread)
+               thread->jit_data = jit_tls;
+}
+
+static void
+mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
+{
+       setup_jit_tls_data (stack_start, mono_thread_abort);
 }
 
 void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
@@ -5548,20 +5850,19 @@ mono_thread_abort_dummy (MonoObject *obj)
 static void
 mono_thread_attach_cb (guint32 tid, gpointer stack_start)
 {
-       MonoJitTlsData *jit_tls;
-       MonoLMF *lmf;
-
-       jit_tls = g_new0 (MonoJitTlsData, 1);
-
-       TlsSetValue (mono_jit_tls_id, jit_tls);
-
-       jit_tls->abort_func = mono_thread_abort_dummy;
-       jit_tls->end_of_stack = stack_start;
+       setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
+}
 
-       lmf = g_new0 (MonoLMF, 1);
-       lmf->ebp = -1;
+static void
+mini_thread_cleanup (MonoThread *thread)
+{
+       MonoJitTlsData *jit_tls = thread->jit_data;
 
-       jit_tls->lmf = lmf;
+       if (jit_tls) {
+               g_free (jit_tls->first_lmf);
+               g_free (jit_tls);
+               thread->jit_data = NULL;
+       }
 }
 
 void
@@ -5926,6 +6227,8 @@ mono_compile_create_vars (MonoCompile *cfg)
                cfg->ret->inst_vtype = sig->ret;
                cfg->ret->klass = mono_class_from_mono_type (sig->ret);
        }
+       if (cfg->verbose_level > 2)
+               g_print ("creating vars\n");
 
        if (sig->hasthis)
                mono_compile_create_var (cfg, &cfg->method->klass->this_arg, OP_ARG);
@@ -5935,8 +6238,12 @@ mono_compile_create_vars (MonoCompile *cfg)
 
        cfg->locals_start = cfg->num_varinfo;
 
+       if (cfg->verbose_level > 2)
+               g_print ("creating locals\n");
        for (i = 0; i < header->num_locals; ++i)
                mono_compile_create_var (cfg, header->locals [i], OP_LOCAL);
+       if (cfg->verbose_level > 2)
+               g_print ("locals done\n");
 }
 
 #if 0
@@ -6421,14 +6728,14 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, int p
        cfg->intvars = mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX * 
                                            ((MonoMethodNormal *)method)->header->max_stack);
 
+       if (cfg->verbose_level > 2)
+               g_print ("converting method %s\n", mono_method_full_name (method, TRUE));
+
        /*
         * create MonoInst* which represents arguments and local variables
         */
        mono_compile_create_vars (cfg);
 
-       if (cfg->verbose_level > 2)
-               g_print ("converting method %s\n", mono_method_full_name (method, TRUE));
-
        if ((i = mono_method_to_ir (cfg, method, NULL, NULL, cfg->locals_start, NULL, NULL, NULL, 0, FALSE)) < 0) {
                if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
                        mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
@@ -6817,6 +7124,18 @@ sigusr1_signal_handler (int _dummy)
        mono_arch_handle_exception (ctx, thread->abort_exc, FALSE);
 }
 
+static void
+sigquit_signal_handler (int _dummy)
+{
+       MonoException *exc;
+       GET_CONTEXT
+
+       exc = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
+       
+       mono_arch_handle_exception (ctx, exc, FALSE);
+}
+
+
 static void
 mono_runtime_install_handlers (void)
 {
@@ -6843,6 +7162,12 @@ mono_runtime_install_handlers (void)
        //g_assert (syscall (SYS_sigaction, SIGFPE, &sa, NULL) != -1);
        g_assert (sigaction (SIGFPE, &sa, NULL) != -1);
 
+       /* catch SIGQUIT */
+       sa.sa_handler = sigquit_signal_handler;
+       sigemptyset (&sa.sa_mask);
+       sa.sa_flags = 0;
+       g_assert (sigaction (SIGQUIT, &sa, NULL) != -1);
+
        /* catch SIGILL */
        sa.sa_handler = sigill_signal_handler;
        sigemptyset (&sa.sa_mask);
@@ -6910,6 +7235,7 @@ mini_init (const char *filename)
        mono_burg_init ();
 
        mono_runtime_install_handlers ();
+       mono_threads_install_cleanup (mini_thread_cleanup);
 
        mono_install_compile_method (mono_jit_compile_method);
        mono_install_trampoline (mono_arch_create_jit_trampoline);
@@ -6987,6 +7313,7 @@ mini_init (const char *filename)
        mono_register_jit_icall (helper_stelem_ref, "helper_stelem_ref", helper_sig_stelem_ref, FALSE);
        mono_register_jit_icall (mono_object_new, "mono_object_new", helper_sig_object_new, FALSE);
        mono_register_jit_icall (mono_object_new_specific, "mono_object_new_specific", helper_sig_object_new_specific, FALSE);
+       mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", helper_sig_object_new_specific, FALSE);
        mono_register_jit_icall (mono_array_new, "mono_array_new", helper_sig_newarr, FALSE);
        mono_register_jit_icall (mono_array_new_specific, "mono_array_new_specific", helper_sig_newarr_specific, FALSE);
        mono_register_jit_icall (mono_string_to_utf16, "mono_string_to_utf16", helper_sig_ptr_obj, FALSE);
@@ -7009,8 +7336,8 @@ mini_init (const char *filename)
        mono_register_jit_icall (mono_ldftn, "mono_ldftn", helper_sig_compile, FALSE);
        mono_register_jit_icall (mono_ldvirtfn, "mono_ldvirtfn", helper_sig_compile_virt, FALSE);
 
-       mono_runtime_init (domain, mono_thread_start_cb,
-                          mono_thread_attach_cb);
+       mono_runtime_install_cleanup ((MonoDomainFunc)mini_cleanup);
+       mono_runtime_init (domain, mono_thread_start_cb, mono_thread_attach_cb);
 
        //mono_thread_attach (domain);
        return domain;