Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2012-10-17 00:05:39 +0400
committerZoltan Varga <vargaz@gmail.com>2012-10-17 00:05:50 +0400
commitd22db24e11d3130c534ec7aa98a0d5e62878ecd0 (patch)
tree2b89c6b163152f673b5e9d3aa66bdea7b428b796
parentf4822194a5e72e68ba150bca96f9ab78017e0b6d (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.cs21
-rw-r--r--mono/mini/method-to-ir.c15
-rw-r--r--mono/mini/mini-x86.c11
-rw-r--r--mono/mini/mini.h2
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;