Merge pull request #4615 from alexanderkyte/string_error_handling
[mono.git] / mono / mini / method-to-ir.c
index 342f357f466dd0e881829b1a02cd1f594c4411b9..99a0b10e2d75162342e00f2b53bf713c4ab076e7 100644 (file)
@@ -1261,16 +1261,22 @@ mono_get_got_var (MonoCompile *cfg)
        return cfg->got_var;
 }
 
-static MonoInst *
-mono_get_vtable_var (MonoCompile *cfg)
+static void
+mono_create_rgctx_var (MonoCompile *cfg)
 {
-       g_assert (cfg->gshared);
-
        if (!cfg->rgctx_var) {
                cfg->rgctx_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
                /* force the var to be stack allocated */
                cfg->rgctx_var->flags |= MONO_INST_VOLATILE;
        }
+}
+
+static MonoInst *
+mono_get_vtable_var (MonoCompile *cfg)
+{
+       g_assert (cfg->gshared);
+
+       mono_create_rgctx_var (cfg);
 
        return cfg->rgctx_var;
 }
@@ -3002,11 +3008,18 @@ emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
                wbarrier->sreg1 = ptr->dreg;
                wbarrier->sreg2 = value->dreg;
                MONO_ADD_INS (cfg->cbb, wbarrier);
-       } else if (card_table && !cfg->compile_aot && !mono_gc_card_table_nursery_check ()) {
+       } else if (card_table) {
                int offset_reg = alloc_preg (cfg);
                int card_reg;
                MonoInst *ins;
 
+               /*
+                * We emit a fast light weight write barrier. This always marks cards as in the concurrent
+                * collector case, so, for the serial collector, it might slightly slow down nursery
+                * collections. We also expect that the host system and the target system have the same card
+                * table configuration, which is the case if they have the same pointer size.
+                */
+
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, offset_reg, ptr->dreg, card_table_shift_bits);
                if (card_table_mask)
                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PAND_IMM, offset_reg, offset_reg, card_table_mask);
@@ -3281,6 +3294,16 @@ emit_get_rgctx (MonoCompile *cfg, MonoMethod *method, int context_used)
                mrgctx_loc = mono_get_vtable_var (cfg);
                EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
 
+               return mrgctx_var;
+       } else if (MONO_CLASS_IS_INTERFACE (cfg->method->klass)) {
+               MonoInst *mrgctx_loc, *mrgctx_var;
+
+               /* Default interface methods need an mrgctx since the vtabke at runtime points at an implementing class */
+               mrgctx_loc = mono_get_vtable_var (cfg);
+               EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
+
+               g_assert (mono_method_needs_static_rgctx_invoke (cfg->method, TRUE));
+
                return mrgctx_var;
        } else if (method->flags & METHOD_ATTRIBUTE_STATIC || method->klass->valuetype) {
                MonoInst *vtable_loc, *vtable_var;
@@ -4579,9 +4602,11 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        /* also consider num_locals? */
        /* Do the size check early to avoid creating vtables */
        if (!inline_limit_inited) {
-               if (g_getenv ("MONO_INLINELIMIT"))
-                       inline_limit = atoi (g_getenv ("MONO_INLINELIMIT"));
-               else
+               char *inlinelimit;
+               if ((inlinelimit = g_getenv ("MONO_INLINELIMIT"))) {
+                       inline_limit = atoi (inlinelimit);
+                       g_free (inlinelimit);
+               } else
                        inline_limit = INLINE_LENGTH_LIMIT;
                inline_limit_inited = TRUE;
        }
@@ -4715,7 +4740,11 @@ mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono
 #if SIZEOF_REGISTER == 8
        /* The array reg is 64 bits but the index reg is only 32 */
        if (COMPILE_LLVM (cfg)) {
-               /* Not needed */
+               /*
+                * abcrem can't handle the OP_SEXT_I4, so add this after abcrem,
+                * during OP_BOUNDS_CHECK decomposition, and in the implementation
+                * of OP_X86_LEA for llvm.
+                */
                index2_reg = index_reg;
        } else {
                index2_reg = alloc_preg (cfg);
@@ -4884,13 +4913,13 @@ static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
  * \param policy_callback the new callback function
  *
  * Allow embedders to decide wherther to actually obey breakpoint instructions
- * (both break IL instructions and \c Debugger.Break() method calls), for example
+ * (both break IL instructions and \c Debugger.Break method calls), for example
  * to not allow an app to be aborted by a perfectly valid IL opcode when executing
  * untrusted or semi-trusted code.
  *
  * \p policy_callback will be called every time a break point instruction needs to
- * be inserted with the method argument being the method that calls \c Debugger.Break()
- * or has the IL break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
+ * be inserted with the method argument being the method that calls \c Debugger.Break
+ * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
  * if it wants the breakpoint to not be effective in the given method.
  * \c MONO_BREAK_POLICY_ALWAYS is the default.
  */
@@ -6890,14 +6919,12 @@ initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, Mono
                        return NULL;
                if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib)
                        return NULL;
-               switch (mono_type_get_underlying_type (&klass->byval_arg)->type) {
-               case MONO_TYPE_BOOLEAN:
+               switch (mini_get_underlying_type (&klass->byval_arg)->type) {
                case MONO_TYPE_I1:
                case MONO_TYPE_U1:
                        size = 1; break;
                /* we need to swap on big endian, so punt. Should we handle R4 and R8 as well? */
 #if TARGET_BYTE_ORDER == G_LITTLE_ENDIAN
-               case MONO_TYPE_CHAR:
                case MONO_TYPE_I2:
                case MONO_TYPE_U2:
                        size = 2; break;
@@ -12342,6 +12369,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ins->type = STACK_I4;
                                MONO_ADD_INS (cfg->cbb, ins);
 
+                               ip += 2;
+                               *sp++ = ins;
+                               break;
+                       case CEE_MONO_GET_RGCTX_ARG:
+                               CHECK_OPSIZE (2);
+                               CHECK_STACK_OVF (1);
+
+                               mono_create_rgctx_var (cfg);
+
+                               MONO_INST_NEW (cfg, ins, OP_MOVE);
+                               ins->dreg = alloc_dreg (cfg, STACK_PTR);
+                               ins->sreg1 = cfg->rgctx_var->dreg;
+                               ins->type = STACK_PTR;
+                               MONO_ADD_INS (cfg->cbb, ins);
+
                                ip += 2;
                                *sp++ = ins;
                                break;