2004-03-11 Zoltan Varga <vargaz@freemail.hu>
authorZoltan Varga <vargaz@gmail.com>
Thu, 11 Mar 2004 18:26:11 +0000 (18:26 -0000)
committerZoltan Varga <vargaz@gmail.com>
Thu, 11 Mar 2004 18:26:11 +0000 (18:26 -0000)
* mini-sparc.h mini-sparc.c tramp-sparc.c exceptions-sparc.c: Ongoing
sparc work.

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

mono/mini/ChangeLog
mono/mini/exceptions-sparc.c
mono/mini/mini-sparc.c
mono/mini/mini-sparc.h
mono/mini/tramp-sparc.c

index d6438fe8e166f2a882d2f6a4ddf2da51cc2ffff5..625f42593bfafb77e4da075ea136f6841457dff8 100644 (file)
@@ -1,5 +1,8 @@
 2004-03-11  Zoltan Varga  <vargaz@freemail.hu>
 
+       * mini-sparc.h mini-sparc.c tramp-sparc.c exceptions-sparc.c: Ongoing
+       sparc work.
+
        * basic-float.cs basic-calls.cs: New regression tests.
 
 2004-03-10  Zoltan Varga  <vargaz@freemail.hu>
index b096fbedfe6ffb50895b18837fd697dabbbb3b3f..392d08491288f28c94d043a1074c4a996a8c81fc 100644 (file)
@@ -391,7 +391,37 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
 }
 
 void
-mono_jit_walk_stack (MonoStackWalk func, gpointer user_data) {
+mono_jit_walk_stack (MonoStackWalk func, gpointer user_data)
+{
+       MonoDomain *domain = mono_domain_get ();
+       MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
+       MonoLMF *lmf = jit_tls->lmf;
+       MonoJitInfo *ji, rji;
+       gint native_offset, il_offset;
+       gboolean managed;
+
+       MonoContext ctx, new_ctx;
+
+       mono_sparc_flushw ();
+
+       MONO_CONTEXT_SET_IP (&ctx, __builtin_return_address (0));
+       MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (1));
+
+       while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) {
+               
+               ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed);
+               g_assert (ji);
+
+               if (ji == (gpointer)-1)
+                       return;
+
+               il_offset = mono_debug_il_offset_from_address (ji->method, native_offset, domain);
+
+               if (func (ji->method, native_offset, il_offset, managed, user_data))
+                       return;
+               
+               ctx = new_ctx;
+       }
 }
 
 MonoBoolean
index 7d20acfb144a402342b4baccd55f05e824899a21..837be49606275de86e15cece8dd50f0c5fe48ac3 100644 (file)
@@ -197,7 +197,7 @@ mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
 }
 
 #ifdef __GNUC__
-#define flushi(addr)    __asm__ __volatile__ ("flush %0"::"r"(addr):"memory")
+#define flushi(addr)    __asm__ __volatile__ ("iflush %0"::"r"(addr):"memory")
 #else /* assume Sun's compiler */
 static void flushi(void *addr)
 {
@@ -208,17 +208,51 @@ static void flushi(void *addr)
 void
 mono_arch_flush_icache (guint8 *code, gint size)
 {
+       guint64 *p = (guint64*)code;
+       guint64 *end = (guint64*)(code + ((size + 8) /8));
+
        /* 
-        * FIXME: This might not work on older machines, but flushing code in dword
-        * chunks in _slow_.
+        * FIXME: Flushing code in dword chunks in _slow_.
         */
-          
-       flushi (code);
 
-       /*
-       for (i = 0; i < (size/8); i++)
-               flushi(code + (i*8));
-       */
+       while (p < end)
+#ifdef __GNUC__
+               __asm__ __volatile__ ("iflush %0"::"r"(p++));
+#else
+                       flushi (p ++);
+#endif
+}
+
+/*
+ * mono_sparc_flushw:
+ *
+ * Flush all register windows to memory. Every register window is saved to
+ * a 16 word area on the stack pointed to by its %sp register.
+ */
+void
+mono_sparc_flushw (void)
+{
+       static guint32 start [64];
+       static int inited = 0;
+       guint32 *code;
+       static void (*flushw) (void);
+
+       if (!inited) {
+               code = start;
+
+               sparc_save_imm (code, sparc_sp, -160, sparc_sp);
+               sparc_flushw (code);
+               sparc_ret (code);
+               sparc_restore_simple (code);
+
+               g_assert ((code - start) < 64);
+
+               flushw = (gpointer)start;
+
+               inited = 1;
+       }
+
+       flushw ();
 }
 
 typedef enum {
@@ -329,7 +363,6 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke)
        enum_calc_size:
                switch (simpletype) {
                case MONO_TYPE_BOOLEAN:
-               case MONO_TYPE_CHAR:
                case MONO_TYPE_I1:
                case MONO_TYPE_U1:
                        add_general (&gr, &stack_size, ainfo, FALSE);
@@ -338,6 +371,7 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke)
                        break;
                case MONO_TYPE_I2:
                case MONO_TYPE_U2:
+               case MONO_TYPE_CHAR:
                        add_general (&gr, &stack_size, ainfo, FALSE);
                        /* the value is in the ls word */
                        ainfo->offset += 2;
@@ -444,7 +478,9 @@ mono_arch_allocate_vars (MonoCompile *m)
        MonoInst *inst;
        int i, offset, size, align, curinst;
        CallInfo *cinfo;
+
+       if (strstr (m->method->name, "pass_byref_double"))
+               printf ("FOO");
        header = ((MonoMethodNormal *)m->method)->header;
 
        sig = m->method->signature;
@@ -540,8 +576,8 @@ mono_arch_allocate_vars (MonoCompile *m)
                        else
                                arg_type = sig->params [i - sig->hasthis];
 
-                       if ((arg_type->type == MONO_TYPE_R4) 
-                               || (arg_type->type == MONO_TYPE_R8))
+                       if (!arg_type->byref && ((arg_type->type == MONO_TYPE_R4) 
+                                                                        || (arg_type->type == MONO_TYPE_R8)))
                                /*
                                 * Since float arguments are passed in integer registers, we need to
                                 * save them to the stack in the prolog.
@@ -576,7 +612,7 @@ mono_arch_allocate_vars (MonoCompile *m)
                                inst->inst_basereg = sparc_fp;
                                inst->inst_offset = ainfo->offset + 68;
 
-                               if (arg_type->type == MONO_TYPE_R8) {
+                               if (!arg_type->byref && (arg_type->type == MONO_TYPE_R8)) {
                                        /* 
                                         * It is very hard to load doubles from non-doubleword aligned
                                         * memory locations. So if the offset is misaligned, we copy the
@@ -1922,6 +1958,23 @@ sparc_patch (guint8 *code, const guint8 *target)
 //     g_print ("patched with 0x%08x\n", ins);
 }
 
+static guint32*
+emit_save_sp_to_lmf (MonoCompile *cfg, guint32 *code)
+{
+       /*
+        * Since register windows are saved to the current value of %sp, we need to
+        * set the sp field in the lmf before the call, not in the prolog.
+        */
+       if (cfg->method->save_lmf) {
+               gint32 lmf_offset = - cfg->arch.lmf_offset;
+
+               /* Save sp */
+               sparc_st_imm (code, sparc_sp, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, sp));
+       }
+
+       return code;
+}
+
 static guint32*
 emit_vret_token (MonoInst *ins, guint32 *code)
 {
@@ -2015,6 +2068,43 @@ mono_sparc_is_virtual_call (guint32 *code)
        return FALSE;
 }
 
+/*
+ * mono_sparc_get_vcall_slot_addr:
+ *
+ *  Determine the vtable slot used by a virtual call.
+ */
+gpointer*
+mono_sparc_get_vcall_slot_addr (guint32 *code, guint32 *fp)
+{
+       guint32 ins = code [0];
+       guint32 prev_ins = code [-1];
+
+       mono_sparc_flushw ();
+
+       if ((sparc_inst_op (ins) == 0x2) && (sparc_inst_op3 (ins) == 0x38)) {
+               if ((sparc_inst_op (prev_ins) == 0x3) && (sparc_inst_op3 (prev_ins) == 0)) {
+                       /* ld [r1 + CONST ], r2; call r2 */
+                       guint32 base = sparc_inst_rs1 (prev_ins);
+                       guint32 disp = sparc_inst_imm13 (prev_ins);
+                       guint32 base_val;
+
+                       g_assert (sparc_inst_rd (prev_ins) == sparc_inst_rs1 (ins));
+
+                       g_assert ((base >= sparc_o0) && (base <= sparc_i7));
+                       
+                       base_val = fp [base - 16];
+
+                       return (gpointer)((guint8*)base_val + disp);
+               }
+               else
+                       g_assert_not_reached ();
+       }
+       else
+               g_assert_not_reached ();
+
+       return FALSE;
+}
+
 /*
  * Some conventions used in the following code.
  * 2) The only scratch registers we have are o7 and g1.  We try to
@@ -2323,7 +2413,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                sparc_mov_reg_reg (code, ins->sreg1, ins->dreg);
                        break;
                case CEE_JMP:
-                       g_assert_not_reached ();
+                       if (cfg->method->save_lmf)
+                               NOT_IMPLEMENTED;
+                       mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0);
+                       sparc_set (code, 0xffffff, sparc_o7);
+                       sparc_jmpl (code, sparc_o7, sparc_g0, sparc_g0);
+                       /* Restore parent frame in delay slot */
+                       sparc_restore_imm (code, sparc_g0, 0, sparc_g0);
+
+                       /* FIXME: Need to handle arguments */
+                       NOT_IMPLEMENTED;
                        break;
                case OP_CHECK_THIS:
                        /* ensure ins->sreg1 is not NULL */
@@ -2336,10 +2435,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case CEE_CALL:
                        call = (MonoCallInst*)ins;
                        g_assert (!call->virtual);
+                       code = emit_save_sp_to_lmf (cfg, code);
                        if (ins->flags & MONO_INST_HAS_METHOD)
-                               mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD, call->method);
+                               mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_METHOD, call->method);
                        else
-                               mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, call->fptr);
+                               mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_ABS, call->fptr);
                        sparc_call_simple (code, 0);
                        sparc_nop (code);
 
@@ -2352,6 +2452,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_VOIDCALL_REG:
                case OP_CALL_REG:
                        call = (MonoCallInst*)ins;
+                       code = emit_save_sp_to_lmf (cfg, code);
                        sparc_jmpl (code, ins->sreg1, sparc_g0, sparc_callsite);
                        /*
                         * We emit a special kind of nop in the delay slot to tell the 
@@ -2373,7 +2474,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_CALL_MEMBASE:
                        call = (MonoCallInst*)ins;
                        g_assert (sparc_is_imm13 (ins->inst_offset));
-
+                       code = emit_save_sp_to_lmf (cfg, code);
                        sparc_ld_imm (code, ins->inst_basereg, ins->inst_offset, sparc_o7);
                        sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite);
                        if (call->virtual)
@@ -2645,13 +2746,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                }
                case OP_FCONV_TO_I8:
                case OP_FCONV_TO_U8:
-                       NOT_IMPLEMENTED;
+                       /* Emulated */
+                       g_assert_not_reached ();
                        break;
                case CEE_CONV_R_UN:
-                       NOT_IMPLEMENTED;
+                       /* Emulated */
+                       g_assert_not_reached ();
                        break;
                case OP_LCONV_TO_R_UN: { 
-                       NOT_IMPLEMENTED;
+                       /* Emulated */
+                       g_assert_not_reached ();
                        break;
                }
                case OP_LCONV_TO_OVF_I: {
@@ -2783,7 +2887,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        EMIT_FLOAT_COND_BRANCH (ins, sparc_fbu);
                        break;
                case CEE_CKFINITE: {
-                       NOT_IMPLEMENTED;
+                       guint32 offset = mono_spillvar_offset_float (cfg, 0);
+                       if (!sparc_is_imm13 (offset))
+                               NOT_IMPLEMENTED;
+                       sparc_stdf_imm (code, ins->sreg1, sparc_sp, offset);
+                       sparc_lduh_imm (code, sparc_sp, offset, sparc_o7);
+                       sparc_srl_imm (code, sparc_o7, 4, sparc_o7);
+                       sparc_and_imm (code, FALSE, sparc_o7, 2047, sparc_o7);
+                       sparc_cmp_imm (code, sparc_o7, 2047);
+                       EMIT_COND_SYSTEM_EXCEPTION (ins, sparc_be, "ArithmeticException");
+                       sparc_fmovs (code, ins->sreg1, ins->dreg);
+                       sparc_fmovs (code, ins->sreg1 + 1, ins->dreg + 1);
                        break;
                }
                default:
@@ -2828,97 +2942,27 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono
                unsigned char *ip = patch_info->ip.i + code;
                const unsigned char *target = NULL;
 
-               switch (patch_info->type) {
-               case MONO_PATCH_INFO_BB:
-                       target = patch_info->data.bb->native_offset + code;
-                       break;
-               case MONO_PATCH_INFO_ABS:
-                       target = patch_info->data.target;
-                       break;
-               case MONO_PATCH_INFO_LABEL:
-                       target = patch_info->data.inst->inst_c0 + code;
-                       break;
-               case MONO_PATCH_INFO_IP:
-                       target = ip;
-                       break;
-               case MONO_PATCH_INFO_METHOD_REL:
-                       target = code + patch_info->data.offset;
-                       if (ip == 0xfdec419c)
-                               printf ("X: %p %p.\n", ip, target);
-                       break;
-               case MONO_PATCH_INFO_INTERNAL_METHOD: {
-                       MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
-                       if (!mi) {
-                               g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info->data.name);
-                               g_assert_not_reached ();
-                       }
-                       target = mono_icall_get_wrapper (mi);
-                       break;
-               }
-               case MONO_PATCH_INFO_METHOD_JUMP: {
-                       GSList *list;
+               target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors);
 
-                       /* get the trampoline to the method from the domain */
-                       target = mono_arch_create_jump_trampoline (patch_info->data.method);
-                       if (!domain->jump_target_hash)
-                               domain->jump_target_hash = g_hash_table_new (NULL, NULL);
-                       list = g_hash_table_lookup (domain->jump_target_hash, patch_info->data.method);
-                       list = g_slist_prepend (list, ip);
-                       g_hash_table_insert (domain->jump_target_hash, patch_info->data.method, list);
-                       break;
-               }
-               case MONO_PATCH_INFO_METHOD:
-                       if (patch_info->data.method == method) {
-                               target = code;
-                       } else
-                               /* get the trampoline to the method from the domain */
-                               target = mono_arch_create_jit_trampoline (patch_info->data.method);
-                       break;
-               case MONO_PATCH_INFO_SWITCH: {
-                       guint32 *p = (guint32*)ip;
-                       gpointer *jump_table = mono_code_manager_reserve (domain->code_mp, sizeof (gpointer) * patch_info->table_size);
-                       int i;
-
-                       target = jump_table;
-
-                       for (i = 0; i < patch_info->table_size; i++) {
-                               jump_table [i] = code + (int)patch_info->data.table [i];
-                       }
-                       break;
-               }
+               switch (patch_info->type) {
                case MONO_PATCH_INFO_METHODCONST:
                case MONO_PATCH_INFO_CLASS:
                case MONO_PATCH_INFO_IMAGE:
                case MONO_PATCH_INFO_FIELD:
                        NOT_IMPLEMENTED;
-                       *((gconstpointer *)(ip + 1)) = patch_info->data.target;
                        continue;
                case MONO_PATCH_INFO_IID:
                        NOT_IMPLEMENTED;
-                       mono_class_init (patch_info->data.klass);
-                       *((guint32 *)(ip + 1)) = patch_info->data.klass->interface_id;
                        continue;                       
                case MONO_PATCH_INFO_VTABLE:
                        NOT_IMPLEMENTED;
-                       *((gconstpointer *)(ip + 1)) = mono_class_vtable (domain, patch_info->data.klass);
                        continue;
                case MONO_PATCH_INFO_CLASS_INIT: {
-                       /* Might already been changed to a nop */
-                       target = mono_create_class_init_trampoline (mono_class_vtable (domain, patch_info->data.klass));
+                       /* FIXME: Might already been changed to a nop */
                        break;
                }
                case MONO_PATCH_INFO_SFLDA: {
-                       MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
-                       if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && mono_class_needs_cctor_run (vtable->klass, method))
-                               /* Done by the generated code */
-                               ;
-                       else {
-                               if (run_cctors)
-                                       mono_runtime_class_init (vtable);
-                       }
                        NOT_IMPLEMENTED;
-                       *((gconstpointer *)(ip + 1)) = 
-                               (char*)vtable->data + patch_info->data.field->offset;
                        continue;
                }
                case MONO_PATCH_INFO_R4: {
@@ -2933,43 +2977,17 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono
                        target = d;                     
                        break;
                }
-               case MONO_PATCH_INFO_EXC_NAME:
-                       target = patch_info->data.name;
-                       break;
                case MONO_PATCH_INFO_LDSTR:
                        NOT_IMPLEMENTED;
-                       *((gconstpointer *)(ip + 1)) = 
-                               mono_ldstr (domain, patch_info->data.token->image, 
-                                                       mono_metadata_token_index (patch_info->data.token->token));
                        continue;
                case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
-                       gpointer handle;
-                       MonoClass *handle_class;
-
-                       handle = mono_ldtoken (patch_info->data.token->image, 
-                                                                  patch_info->data.token->token, &handle_class);
-                       mono_class_init (handle_class);
-                       mono_class_init (mono_class_from_mono_type (handle));
-
                        NOT_IMPLEMENTED;
-                       *((gconstpointer *)(ip + 1)) = 
-                               mono_type_get_object (domain, handle);
                        continue;
                }
                case MONO_PATCH_INFO_LDTOKEN: {
-                       gpointer handle;
-                       MonoClass *handle_class;
-
-                       handle = mono_ldtoken (patch_info->data.token->image,
-                                                                  patch_info->data.token->token, &handle_class);
-                       mono_class_init (handle_class);
-
                        NOT_IMPLEMENTED;
-                       *((gconstpointer *)(ip + 1)) = handle;
                        continue;
                }
-               default:
-                       g_assert_not_reached ();
                }
                sparc_patch (ip, target);
        }
@@ -3228,7 +3246,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        sparc_st_imm (code, sparc_i5, inst->inst_basereg, stack_offset);
                }
 
-               if (arg_type->type == MONO_TYPE_R8) {
+               if (!arg_type->byref && (arg_type->type == MONO_TYPE_R8)) {
                        /* Save the argument to a dword aligned stack location */
                        /*
                         * stack_offset contains the offset of the argument on the stack.
@@ -3359,7 +3377,14 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                sparc_st (code, sparc_l0, sparc_l1, sparc_g0);
        }
 
-       sparc_ret (code);
+       /* 
+        * The sparc ABI requires that calls to functions which return a structure
+        * return to %i7+12
+        */
+       if (cfg->method->signature->pinvoke && MONO_TYPE_ISSTRUCT(cfg->method->signature->ret))
+               sparc_jmpl_imm (code, sparc_i7, 12, sparc_g0);
+       else
+               sparc_ret (code);
        sparc_restore_imm (code, sparc_g0, 0, sparc_g0);
 
        /* add code to raise exceptions */
index 3c24678580325171c1fbd0801d2162c54db73382..ba9b971112731b73bc737c95c27d3d5947224973 100644 (file)
@@ -38,4 +38,8 @@ typedef struct MonoCompileArch {
 
 gboolean mono_sparc_is_virtual_call (guint32 *code);
 
+gpointer* mono_sparc_get_vcall_slot_addr (guint32 *code, guint32 *fp);
+
+void mono_sparc_flushw (void);
+
 #endif /* __MONO_MINI_SPARC_H__ */  
index 32e305690d2e7425708f619b5aba93bdb2e4c538..ba06c683ec2fab4bfda25cd0006281a9e9a4ed15 100644 (file)
@@ -72,6 +72,7 @@ get_unbox_trampoline (MonoMethod *m, gpointer addr)
  * sparc_magic_trampoline:
  * @m: the method to translate
  * @code: the address of the call instruction
+ * @fp: address of the stack frame for the caller
  *
  * This method is called by the trampoline functions for methods. It calls the
  * JIT compiler to compile the method, then patches the calling instruction so
@@ -79,9 +80,10 @@ get_unbox_trampoline (MonoMethod *m, gpointer addr)
  * address of the vtable slot and updates it.
  */
 static gpointer
-sparc_magic_trampoline (MonoMethod *m, guint32 *code)
+sparc_magic_trampoline (MonoMethod *m, guint32 *code, guint32 *fp)
 {
        gpointer addr;
+       gpointer *vtable_slot;
 
        addr = mono_compile_method (m);
        g_assert (addr);
@@ -95,6 +97,15 @@ sparc_magic_trampoline (MonoMethod *m, guint32 *code)
        if (mono_sparc_is_virtual_call (code)) {
                if (m->klass->valuetype)
                        addr = get_unbox_trampoline (m, addr);
+
+               /* Compute address of vtable slot */
+               vtable_slot = mono_sparc_get_vcall_slot_addr (code, fp);
+               *vtable_slot = addr;
+       }
+       else {
+               /* Patch calling code */
+               if (sparc_inst_op (*code) == 0x1)
+                       sparc_call_simple (code, (guint8*)addr - (guint8*)code);
        }
 
        return addr;
@@ -143,6 +154,8 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                tramp_addr = &sparc_class_init_trampoline;
        else
                tramp_addr = &sparc_magic_trampoline;
+       /* pass parent frame address as third argument */
+       sparc_mov_reg_reg (code, sparc_fp, sparc_o2);
        sparc_call_simple (code, tramp_addr - code);
        /* set %o1 to caller address in delay slot */
        sparc_mov_reg_reg (code, sparc_i7, sparc_o1);
@@ -208,7 +221,7 @@ create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type)
 MonoJitInfo*
 mono_arch_create_jump_trampoline (MonoMethod *method)
 {
-       MonoJitInfo *ji = create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC);
+       MonoJitInfo *ji = create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP);
 
        ji->method = method;
        return ji;