diff options
author | Zoltan Varga <vargaz@gmail.com> | 2012-10-17 00:05:39 +0400 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2012-10-17 00:05:50 +0400 |
commit | d22db24e11d3130c534ec7aa98a0d5e62878ecd0 (patch) | |
tree | 2b89c6b163152f673b5e9d3aa66bdea7b428b796 | |
parent | f4822194a5e72e68ba150bca96f9ab78017e0b6d (diff) |
Treat the 'this' parameter slot as a managed pointer for interface calls, since the unbox trampolines can transform it from a reference to an internal pointer.
-rw-r--r-- | mono/mini/gc-test.cs | 21 | ||||
-rw-r--r-- | mono/mini/method-to-ir.c | 15 | ||||
-rw-r--r-- | mono/mini/mini-x86.c | 11 | ||||
-rw-r--r-- | mono/mini/mini.h | 2 |
4 files changed, 41 insertions, 8 deletions
diff --git a/mono/mini/gc-test.cs b/mono/mini/gc-test.cs index 896f9cea6a4..8f80d934627 100644 --- a/mono/mini/gc-test.cs +++ b/mono/mini/gc-test.cs @@ -559,6 +559,27 @@ class Tests { liveness_12_inner (1, 2, 3, 4, 5, 6, new object (), ref f.s); return 0; } + + interface IFace { + int foo (); + } + + struct BarStruct : IFace { + int i; + + public int foo () { + GC.Collect (); + return i; + } + } + + public static int test_0_liveness_unbox_trampoline () { + var s = new BarStruct (); + + IFace iface = s; + iface.foo (); + return 0; + } public static void liveness_13_inner (ref ArrayList arr) { // The value of arr will be stored in a spill slot diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 62b2c1a89eb..ba025490237 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -2222,7 +2222,7 @@ mono_patch_info_new (MonoMemPool *mp, int ip, MonoJumpInfoType type, gconstpoint inline static MonoCallInst * mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, - MonoInst **args, int calli, int virtual, int tail, int rgctx) + MonoInst **args, int calli, int virtual, int tail, int rgctx, int unbox_trampoline) { MonoCallInst *call; #ifdef MONO_ARCH_SOFT_FLOAT @@ -2303,6 +2303,8 @@ mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, } #endif + call->need_unbox_trampoline = unbox_trampoline; + #ifdef ENABLE_LLVM if (COMPILE_LLVM (cfg)) mono_llvm_emit_call (cfg, call); @@ -2344,7 +2346,7 @@ mono_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, Mo MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, rgctx_reg, rgctx_arg->dreg); } - call = mono_emit_call_args (cfg, sig, args, TRUE, FALSE, FALSE, rgctx_arg ? TRUE : FALSE); + call = mono_emit_call_args (cfg, sig, args, TRUE, FALSE, FALSE, rgctx_arg ? TRUE : FALSE, FALSE); call->inst.sreg1 = addr->dreg; @@ -2371,6 +2373,7 @@ mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign int context_used; MonoCallInst *call; int rgctx_reg = 0; + gboolean need_unbox_trampoline; if (rgctx_arg) { rgctx_reg = mono_alloc_preg (cfg); @@ -2402,7 +2405,9 @@ mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign return mono_emit_calli (cfg, sig, args, addr, NULL); } - call = mono_emit_call_args (cfg, sig, args, FALSE, virtual, FALSE, rgctx_arg ? TRUE : FALSE); + need_unbox_trampoline = method->klass == mono_defaults.object_class || (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE); + + call = mono_emit_call_args (cfg, sig, args, FALSE, virtual, FALSE, rgctx_arg ? TRUE : FALSE, need_unbox_trampoline); if (might_be_remote) call->method = mono_marshal_get_remoting_invoke_with_check (method); @@ -2535,7 +2540,7 @@ mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature g_assert (sig); - call = mono_emit_call_args (cfg, sig, args, FALSE, FALSE, FALSE, FALSE); + call = mono_emit_call_args (cfg, sig, args, FALSE, FALSE, FALSE, FALSE, FALSE); call->fptr = func; MONO_ADD_INS (cfg->cbb, (MonoInst*)call); @@ -7523,7 +7528,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b #ifdef MONO_ARCH_USE_OP_TAIL_CALL /* Handle tail calls similarly to calls */ - call = mono_emit_call_args (cfg, mono_method_signature (cmethod), sp, FALSE, FALSE, TRUE, FALSE); + call = mono_emit_call_args (cfg, mono_method_signature (cmethod), sp, FALSE, FALSE, TRUE, FALSE, FALSE); #else MONO_INST_NEW_CALL (cfg, call, OP_JMP); call->tail_call = TRUE; diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index ce39e948ad0..f562ea7f5ad 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -1576,11 +1576,16 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) if (cfg->compute_gc_maps) { if (argsize == 4) { /* FIXME: The == STACK_OBJ check might be fragile ? */ - if (sig->hasthis && i == 0 && call->args [i]->type == STACK_OBJ) + if (sig->hasthis && i == 0 && call->args [i]->type == STACK_OBJ) { /* this */ - emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.object_class->byval_arg); - else + if (call->need_unbox_trampoline) + /* The unbox trampoline transforms this into a managed pointer */ + emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.int_class->this_arg); + else + emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.object_class->byval_arg); + } else { emit_gc_param_slot_def (cfg, sp_offset, orig_type); + } } else { /* i8/r8 */ for (j = 0; j < argsize; j += 4) diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 3dd34d53d5a..18b0050b625 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -803,6 +803,8 @@ struct MonoCallInst { guint dynamic_imt_arg : 1; /* Whenever there is an RGCTX argument */ guint32 rgctx_reg : 1; + /* Whenever the call will need an unbox trampoline */ + guint need_unbox_trampoline : 1; regmask_t used_iregs; regmask_t used_fregs; GSList *out_ireg_args; |