2009-05-08 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Fri, 8 May 2009 13:35:14 +0000 (13:35 -0000)
committerZoltan Varga <vargaz@gmail.com>
Fri, 8 May 2009 13:35:14 +0000 (13:35 -0000)
* method-to-ir.c (mono_emit_call_args): Add a 'tail' flag argument.
(mono_method_to_ir): Use MONO_ARCH_USE_OP_TAIL_CALL macro to determine
whenever to make tail calls using OP_TAIL_CALL. Enable support for tail
calls returning structures by addr on amd64.

* mini-amd64.h (MONO_ARCH_USE_OP_TAIL_CALL): New arch-specific macro.

* iltests.il.in: Restructure the tail call tests a bit.

svn path=/trunk/mono/; revision=133766

mono/mini/ChangeLog
mono/mini/iltests.il.in
mono/mini/method-to-ir.c
mono/mini/mini-amd64.h

index 47c23cc20a14026c030c75ada4765ff87d98ba59..e5649213582d0b4194d0d4bdc3377ac80b1102fd 100644 (file)
@@ -2,6 +2,17 @@
 
        * aot-compiler.c (arch_emit_got_access): Fix the aot-not-supported build.
 
+2009-05-08  Zoltan Varga  <vargaz@gmail.com>
+
+       * method-to-ir.c (mono_emit_call_args): Add a 'tail' flag argument.
+       (mono_method_to_ir): Use MONO_ARCH_USE_OP_TAIL_CALL macro to determine
+       whenever to make tail calls using OP_TAIL_CALL. Enable support for tail
+       calls returning structures by addr on amd64.
+
+       * mini-amd64.h (MONO_ARCH_USE_OP_TAIL_CALL): New arch-specific macro.
+
+       * iltests.il.in: Restructure the tail call tests a bit.
+       
 2009-05-07  Zoltan Varga  <vargaz@gmail.com>
 
        * aot-compiler.c (add_wrappers): Add remoting-invoke-with-check wrappers
index d9125fb86370922a87b32466caa81ce3a27ed2a2..4e3759739ac85dfdf390864debd743c252f26f1d 100644 (file)
@@ -491,9 +491,11 @@ COND:   ldloc.0
                .field public int32 a
                .field public int32 b
                .field public int32 c
+               .field public int32 d
+               .field public int32 e
        }
 
-       .method static valuetype Tests/TailCallStructBig tail1_big (valuetype Tests/TailCallStructBig arg) {
+       .method static valuetype Tests/TailCallStructBig tail_vret_by_addr_inner (valuetype Tests/TailCallStructBig arg) {
                ldarga 0
                ldarga 0
                ldfld int32 Tests/TailCallStructBig::a
@@ -504,19 +506,36 @@ COND:   ldloc.0
                ret
        }
 
-       .method static valuetype Tests/TailCallStructBig tail2_big (valuetype Tests/TailCallStructBig arg) {
+       .method static valuetype Tests/TailCallStructBig tail_vret_by_addr (valuetype Tests/TailCallStructBig arg) {
                ldarg.0
                tail.
-               call valuetype Tests/TailCallStructBig Tests::tail1_big (valuetype Tests/TailCallStructBig)
+               call valuetype Tests/TailCallStructBig Tests::tail_vret_by_addr_inner (valuetype Tests/TailCallStructBig)
                ret
        }
 
-       .method static public int32 test_0_tail_calls () il managed {
+       .method static public int32 test_3_tail_call_vret_by_addr () il managed {
                .maxstack 16
                .locals init (
-                       valuetype Tests/TailCallStruct arg,
                        valuetype Tests/TailCallStructBig arg2
                )
+
+               ldloca 0
+               ldc.i4.2
+               stfld int32 Tests/TailCallStructBig::a
+               ldloc.0
+               call valuetype Tests/TailCallStructBig Tests::tail_vret_by_addr (valuetype Tests/TailCallStructBig)
+               stloc.0
+
+               ldloca 0
+               ldfld int32 Tests/TailCallStructBig::a
+               ret
+       }
+
+       .method static public int32 test_9_tail_call_vret_by_val () il managed {
+               .maxstack 16
+               .locals init (
+                       valuetype Tests/TailCallStruct arg
+               )
                ldloca 0
                ldc.i4.2
                stfld int32 Tests/TailCallStruct::a
@@ -527,23 +546,11 @@ COND:   ldloc.0
                call valuetype Tests/TailCallStruct Tests::tail2 (valuetype Tests/TailCallStruct)
                stloc.0
 
-               ldloca 1
-               ldc.i4.2
-               stfld int32 Tests/TailCallStructBig::a
-               ldloc.1
-               call valuetype Tests/TailCallStructBig Tests::tail2_big (valuetype Tests/TailCallStructBig)
-               stloc.1
-
                ldloca 0
                ldfld int32 Tests/TailCallStruct::a
                ldloca 0
                ldfld int32 Tests/TailCallStruct::b
                add
-               ldloca 1
-               ldfld int32 Tests/TailCallStructBig::a
-               add
-               ldc.i4 12
-               sub
                ret
        }
 
index 18e1483945b212798d7baa1bacebd29b398c12f1..19f36bc4b5178f13923da925278c2279fcba0999 100644 (file)
@@ -2103,21 +2103,29 @@ mono_emit_jit_icall (MonoCompile *cfg, gconstpointer func, MonoInst **args);
 
 inline static MonoCallInst *
 mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, 
-                    MonoInst **args, int calli, int virtual)
+                                        MonoInst **args, int calli, int virtual, int tail)
 {
        MonoCallInst *call;
 #ifdef MONO_ARCH_SOFT_FLOAT
        int i;
 #endif
 
-       MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (sig->ret, calli, virtual, cfg->generic_sharing_context));
+       if (tail)
+               MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
+       else
+               MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (sig->ret, calli, virtual, cfg->generic_sharing_context));
 
        call->args = args;
        call->signature = sig;
 
        type_to_eval_stack_type ((cfg), sig->ret, &call->inst);
 
-       if (MONO_TYPE_ISSTRUCT (sig->ret)) {
+       if (tail) {
+               if (MONO_TYPE_ISSTRUCT (sig->ret)) {
+                       call->vret_var = cfg->vret_addr;
+                       //g_assert_not_reached ();
+               }
+       } else if (MONO_TYPE_ISSTRUCT (sig->ret)) {
                MonoInst *temp = mono_compile_create_var (cfg, sig->ret, OP_LOCAL);
                MonoInst *loada;
 
@@ -2191,7 +2199,7 @@ mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
 inline static MonoInst*
 mono_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr)
 {
-       MonoCallInst *call = mono_emit_call_args (cfg, sig, args, TRUE, FALSE);
+       MonoCallInst *call = mono_emit_call_args (cfg, sig, args, TRUE, FALSE, FALSE);
 
        call->inst.sreg1 = addr->dreg;
 
@@ -2241,7 +2249,7 @@ mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign
                sig = ctor_sig;
        }
 
-       call = mono_emit_call_args (cfg, sig, args, FALSE, virtual);
+       call = mono_emit_call_args (cfg, sig, args, FALSE, virtual, FALSE);
 
        if (this && sig->hasthis && 
            (method->klass->marshalbyref || method->klass == mono_defaults.object_class) && 
@@ -2397,7 +2405,7 @@ mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature
 
        g_assert (sig);
 
-       call = mono_emit_call_args (cfg, sig, args, FALSE, FALSE);
+       call = mono_emit_call_args (cfg, sig, args, FALSE, FALSE, FALSE);
        call->fptr = func;
 
        MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
@@ -5947,7 +5955,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS)
                                CHECK_CFG_EXCEPTION;
 
-#ifdef TARGET_AMD64
+#ifdef MONO_ARCH_USE_OP_TAIL_CALL
                        {
                                MonoMethodSignature *fsig = mono_method_signature (cmethod);
                                int i, n;
@@ -5996,6 +6004,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        gboolean pass_mrgctx = FALSE;
                        MonoInst *vtable_arg = NULL;
                        gboolean check_this = FALSE;
+                       gboolean supported_tail_call = FALSE;
 
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
@@ -6303,27 +6312,30 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                break;
                        }
 
+#ifdef MONO_ARCH_USE_OP_TAIL_CALL
+                       supported_tail_call = cmethod && MONO_ARCH_USE_OP_TAIL_CALL (mono_method_signature (method), mono_method_signature (cmethod));
+#else
+                       supported_tail_call = mono_metadata_signature_equal (mono_method_signature (method), mono_method_signature (cmethod))) && !MONO_TYPE_ISSTRUCT (mono_method_signature (cmethod)->ret);
+#endif
+
                        /* Tail prefix */
                        /* FIXME: runtime generic context pointer for jumps? */
                        /* FIXME: handle this for generic sharing eventually */
-                       if ((ins_flag & MONO_INST_TAILCALL) && !cfg->generic_sharing_context && !vtable_arg && cmethod && (*ip == CEE_CALL) &&
-                               (mono_metadata_signature_equal (mono_method_signature (method), mono_method_signature (cmethod))) && !MONO_TYPE_ISSTRUCT (mono_method_signature (cmethod)->ret)) {
+                       if ((ins_flag & MONO_INST_TAILCALL) && !cfg->generic_sharing_context && !vtable_arg && cmethod && (*ip == CEE_CALL) && supported_tail_call) {
                                MonoCallInst *call;
 
                                /* Prevent inlining of methods with tail calls (the call stack would be altered) */
                                INLINE_FAILURE;
 
+#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);
+#else
                                MONO_INST_NEW_CALL (cfg, call, OP_JMP);
                                call->tail_call = TRUE;
                                call->method = cmethod;
                                call->signature = mono_method_signature (cmethod);
 
-#ifdef TARGET_AMD64
-                               /* Handle tail calls similarly to calls */
-                               call->inst.opcode = OP_TAILCALL;
-                               call->args = sp;
-                               mono_arch_emit_call (cfg, call);
-#else
                                /*
                                 * We implement tail calls by storing the actual arguments into the 
                                 * argument variables, then emitting a CEE_JMP.
index 108900a8704fcad17eebdb18be40486b6c2c2df9..b3bf41007a95148c81276dc7d156dd6d94ecdd19 100644 (file)
@@ -337,6 +337,8 @@ typedef struct {
 #define MONO_AMD64_NO_PUSHES 1
 #endif
 
+#define MONO_ARCH_USE_OP_TAIL_CALL(caller_sig, callee_sig) mono_metadata_signature_equal ((caller_sig), (callee_sig))
+
 /* Used for optimization, not complete */
 #define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)