Merge pull request #3240 from alexanderkyte/aot_compiler_leaks
[mono.git] / mono / mini / method-to-ir.c
index 7df45ee2556f8ea504cc06ddbe7435fbaa49df3e..7f3c4f7e9c803d6ce2bbdae62bd5cee68638ed75 100644 (file)
@@ -661,6 +661,24 @@ mono_find_block_region (MonoCompile *cfg, int offset)
        return -1;
 }
 
+static gboolean
+ip_in_finally_clause (MonoCompile *cfg, int offset)
+{
+       MonoMethodHeader *header = cfg->header;
+       MonoExceptionClause *clause;
+       int i;
+
+       for (i = 0; i < header->num_clauses; ++i) {
+               clause = &header->clauses [i];
+               if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT)
+                       continue;
+
+               if (MONO_OFFSET_IN_HANDLER (clause, offset))
+                       return TRUE;
+       }
+       return FALSE;
+}
+
 static GList*
 mono_find_final_block (MonoCompile *cfg, unsigned char *ip, unsigned char *target, int type)
 {
@@ -2197,7 +2215,6 @@ target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg)
        if (target->byref) {
                /* FIXME: check that the pointed to types match */
                if (arg->type == STACK_MP) {
-                       if (cfg->verbose_level) printf ("ok\n");
                        /* This is needed to handle gshared types + ldaddr. We lower the types so we can handle enums and other typedef-like types. */
                        MonoClass *target_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&mono_class_from_mono_type (target)->byval_arg));
                        MonoClass *source_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&arg->klass->byval_arg));
@@ -4034,7 +4051,8 @@ handle_unbox_nullable (MonoCompile* cfg, MonoInst* val, MonoClass* klass, int co
                   RGCTX. */
                addr = emit_get_rgctx_method (cfg, context_used, method,
                                                                          MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
-               if (cfg->llvm_only && cfg->gsharedvt) {
+               if (cfg->llvm_only) {
+                       cfg->signatures = g_slist_prepend_mempool (cfg->mempool, cfg->signatures, mono_method_signature (method));
                        return emit_llvmonly_calli (cfg, mono_method_signature (method), &val, addr);
                } else {
                        rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
@@ -5886,7 +5904,7 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                if (opcode && fsig->param_count == 1) {
                        MONO_INST_NEW (cfg, ins, opcode);
                        ins->type = STACK_R8;
-                       ins->dreg = mono_alloc_freg (cfg);
+                       ins->dreg = mono_alloc_dreg (cfg, ins->type);
                        ins->sreg1 = args [0]->dreg;
                        MONO_ADD_INS (cfg->cbb, ins);
                }
@@ -5917,7 +5935,7 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                if (opcode && fsig->param_count == 2) {
                        MONO_INST_NEW (cfg, ins, opcode);
                        ins->type = fsig->params [0]->type == MONO_TYPE_I4 ? STACK_I4 : STACK_I8;
-                       ins->dreg = mono_alloc_ireg (cfg);
+                       ins->dreg = mono_alloc_dreg (cfg, ins->type);
                        ins->sreg1 = args [0]->dreg;
                        ins->sreg2 = args [1]->dreg;
                        MONO_ADD_INS (cfg->cbb, ins);
@@ -8173,7 +8191,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        if (!header) {
                mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
                goto exception_exit;
+       } else {
+               cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
        }
+
        generic_container = mono_method_get_generic_container (method);
        sig = mono_method_signature (method);
        num_args = sig->hasthis + sig->param_count;
@@ -9032,6 +9053,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                for (i = 0; i < n; ++i)
                                        EMIT_NEW_ARGLOAD (cfg, call->args [i], i);
 
+                               if (mini_type_is_vtype (mini_get_underlying_type (call->signature->ret)))
+                                       call->vret_var = cfg->vret_addr;
+
                                mono_arch_emit_call (cfg, call);
                                cfg->param_area = MAX(cfg->param_area, call->stack_usage);
                                MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
@@ -9724,6 +9748,20 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        inline_costs += 10 * num_calls++;
 
+                       /*
+                        * Synchronized wrappers.
+                        * Its hard to determine where to replace a method with its synchronized
+                        * wrapper without causing an infinite recursion. The current solution is
+                        * to add the synchronized wrapper in the trampolines, and to
+                        * change the called method to a dummy wrapper, and resolve that wrapper
+                        * to the real method in mono_jit_compile_method ().
+                        */
+                       if (cfg->method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
+                               MonoMethod *orig = mono_marshal_method_from_wrapper (cfg->method);
+                               if (cmethod == orig || (cmethod->is_inflated && mono_method_get_declaring_generic_method (cmethod) == orig))
+                                       cmethod = mono_marshal_get_synchronized_inner_wrapper (cmethod);
+                       }
+
                        /*
                         * Making generic calls out of gsharedvt methods.
                         * This needs to be used for all generic calls, not just ones with a gsharedvt signature, to avoid
@@ -9943,20 +9981,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        }
 
-                       /* 
-                        * Synchronized wrappers.
-                        * Its hard to determine where to replace a method with its synchronized
-                        * wrapper without causing an infinite recursion. The current solution is
-                        * to add the synchronized wrapper in the trampolines, and to
-                        * change the called method to a dummy wrapper, and resolve that wrapper
-                        * to the real method in mono_jit_compile_method ().
-                        */
-                       if (cfg->method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
-                               MonoMethod *orig = mono_marshal_method_from_wrapper (cfg->method);
-                               if (cmethod == orig || (cmethod->is_inflated && mono_method_get_declaring_generic_method (cmethod) == orig))
-                                       cmethod = mono_marshal_get_synchronized_inner_wrapper (cmethod);
-                       }
-
                        /*
                         * Virtual calls in llvm-only mode.
                         */
@@ -11309,6 +11333,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                        MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
 
+                                       if (ins_flag & MONO_INST_VOLATILE) {
+                                               /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
+                                               emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
+                                       }
+
                                        if (mini_is_gsharedvt_klass (klass)) {
                                                MonoInst *offset_ins;
 
@@ -12268,6 +12297,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                INLINE_FAILURE ("throw");
                        break;
                case CEE_ENDFINALLY:
+                       if (!ip_in_finally_clause (cfg, ip - header->code))
+                               UNVERIFIED;
                        /* mono_save_seq_point_info () depends on this */
                        if (sp != stack_start)
                                emit_seq_point (cfg, method, ip, FALSE, FALSE);
@@ -13228,8 +13259,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ip += 4;
                                inline_costs += 1;
                                break;
-                       case CEE_LOCALLOC:
+                       case CEE_LOCALLOC: {
                                CHECK_STACK (1);
+                               MonoBasicBlock *non_zero_bb, *end_bb;
+                               int alloc_ptr = alloc_preg (cfg);
                                --sp;
                                if (sp != stack_start) 
                                        UNVERIFIED;
@@ -13241,8 +13274,20 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         */
                                        INLINE_FAILURE("localloc");
 
+                               NEW_BBLOCK (cfg, non_zero_bb);
+                               NEW_BBLOCK (cfg, end_bb);
+
+                               /* if size != zero */
+                               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, sp [0]->dreg, 0);
+                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, non_zero_bb);
+
+                               //size is zero, so result is NULL
+                               MONO_EMIT_NEW_PCONST (cfg, alloc_ptr, NULL);
+                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+                               MONO_START_BB (cfg, non_zero_bb);
                                MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
-                               ins->dreg = alloc_preg (cfg);
+                               ins->dreg = alloc_ptr;
                                ins->sreg1 = sp [0]->dreg;
                                ins->type = STACK_PTR;
                                MONO_ADD_INS (cfg->cbb, ins);
@@ -13251,9 +13296,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (init_locals)
                                        ins->flags |= MONO_INST_INIT;
 
+                               MONO_START_BB (cfg, end_bb);
+                               EMIT_NEW_UNALU (cfg, ins, OP_MOVE, alloc_preg (cfg), alloc_ptr);
+                               ins->type = STACK_PTR;
+
                                *sp++ = ins;
                                ip += 2;
                                break;
+                       }
                        case CEE_ENDFILTER: {
                                MonoExceptionClause *clause, *nearest;
                                int cc;
@@ -13633,7 +13683,6 @@ mono_error_exit:
        g_slist_free (class_inits);
        mono_basic_block_free (original_bb);
        cfg->dont_inline = g_list_remove (cfg->dont_inline, method);
-       cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
        if (cfg->exception_type)
                return -1;
        else