diff options
author | Vlad Brezae <brezaevlad@gmail.com> | 2018-10-12 00:18:30 +0300 |
---|---|---|
committer | Ludovic Henry <luhenry@microsoft.com> | 2018-10-12 00:18:30 +0300 |
commit | 431628cad7286fbd0bd03675f5953056203a111b (patch) | |
tree | 80b76d04ad716c8016a270819ebd842efb091c23 | |
parent | 15ae6a97ad9687d108bd06d7009bc7b8f42bbbbb (diff) |
[interp] Implement interpreter entry trampolines on amd64 (#10978)
* [interp] Avoid unnecessary allocations when pinvoke void functions
* [amd64] Refactor interp pinvoke context computation
* [amd64] Interp trampoline for interpreter entry
* [aot] Don't include interp_in_wrapper when we use entry trampoline
These wrappers take a lot of space in the image.
-rw-r--r-- | mono/mini/aot-compiler.c | 4 | ||||
-rw-r--r-- | mono/mini/mini-amd64.c | 267 | ||||
-rw-r--r-- | mono/mini/mini-amd64.h | 5 | ||||
-rw-r--r-- | mono/mini/mini-arm.c | 46 | ||||
-rw-r--r-- | mono/mini/mini-arm64.c | 64 | ||||
-rw-r--r-- | mono/mini/tramp-amd64.c | 80 |
6 files changed, 323 insertions, 143 deletions
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 3e3d3af0ac6..da3822fb324 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -7880,11 +7880,13 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean wrapper = mini_get_gsharedvt_out_sig_wrapper (sig); add_extra_method (acfg, wrapper); } +#ifndef MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE if (interp_in) { wrapper = mini_get_interp_in_wrapper (sig); add_extra_method (acfg, wrapper); //printf ("X: %s\n", mono_method_full_name (wrapper, 1)); } +#endif } /* @@ -12861,6 +12863,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options, MonoMethod *wrapper = mini_get_interp_lmf_wrapper (); add_method (acfg, wrapper); +#ifndef MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE for (int i = 0; i < sizeof (interp_in_static_sigs) / sizeof (const char *); i++) { MonoMethodSignature *sig = mono_create_icall_signature (interp_in_static_sigs [i]); sig = mono_metadata_signature_dup_full (mono_get_corlib (), sig); @@ -12868,6 +12871,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options, wrapper = mini_get_interp_in_wrapper (sig); add_method (acfg, wrapper); } +#endif } TV_GETTIME (atv); diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 5da5c110257..d44684b66f0 100644 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -1093,72 +1093,182 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) return cinfo; } +static int +arg_need_temp (ArgInfo *ainfo) +{ + if (ainfo->storage == ArgValuetypeInReg) + return ainfo->nregs * sizeof (host_mgreg_t); + return 0; +} + +static gpointer +arg_get_storage (CallContext *ccontext, ArgInfo *ainfo) +{ + switch (ainfo->storage) { + case ArgInIReg: + return &ccontext->gregs [ainfo->reg]; + case ArgInFloatSSEReg: + case ArgInDoubleSSEReg: + return &ccontext->fregs [ainfo->reg]; + case ArgOnStack: + return ccontext->stack + ainfo->offset; + case ArgValuetypeInReg: + // Empty struct + g_assert (!ainfo->nregs); + return NULL; + default: + g_error ("Arg storage type not yet supported"); + } +} + +static void +arg_get_val (CallContext *ccontext, ArgInfo *ainfo, gpointer dest) +{ + g_assert (arg_need_temp (ainfo)); + + host_mgreg_t *dest_cast = (host_mgreg_t*)dest; + /* Reconstruct the value type */ + for (int k = 0; k < ainfo->nregs; k++) { + int storage_type = ainfo->pair_storage [k]; + int reg_storage = ainfo->pair_regs [k]; + switch (storage_type) { + case ArgInIReg: + *dest_cast = ccontext->gregs [reg_storage]; + break; + case ArgInFloatSSEReg: + case ArgInDoubleSSEReg: + *(double*)dest_cast = ccontext->fregs [reg_storage]; + break; + default: + g_assert_not_reached (); + } + dest_cast++; + } +} + +static void +arg_set_val (CallContext *ccontext, ArgInfo *ainfo, gpointer src) +{ + g_assert (arg_need_temp (ainfo)); + + host_mgreg_t *src_cast = (host_mgreg_t*)src; + for (int k = 0; k < ainfo->nregs; k++) { + int storage_type = ainfo->pair_storage [k]; + int reg_storage = ainfo->pair_regs [k]; + switch (storage_type) { + case ArgInIReg: + ccontext->gregs [reg_storage] = *src_cast; + break; + case ArgInFloatSSEReg: + case ArgInDoubleSSEReg: + ccontext->fregs [reg_storage] = *(double*)src_cast; + break; + default: + g_assert_not_reached (); + } + src_cast++; + } +} + void mono_arch_set_native_call_context_args (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) { CallInfo *cinfo = get_call_info (NULL, sig); MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); + gpointer storage; + ArgInfo *ainfo; memset (ccontext, 0, sizeof (CallContext)); ccontext->stack_size = ALIGN_TO (cinfo->stack_usage, MONO_ARCH_FRAME_ALIGNMENT); if (ccontext->stack_size) - ccontext->stack = (gpointer*)g_malloc (ccontext->stack_size); + ccontext->stack = (guint8*)g_calloc (1, ccontext->stack_size); if (sig->ret->type != MONO_TYPE_VOID) { - if (cinfo->ret.storage == ArgValuetypeAddrInIReg) { - gpointer ret_storage = interp_cb->frame_arg_to_storage ((MonoInterpFrameHandle)frame, sig, -1); - ccontext->gregs [cinfo->ret.reg] = (host_mgreg_t)ret_storage; + ainfo = &cinfo->ret; + if (ainfo->storage == ArgValuetypeAddrInIReg) { + storage = interp_cb->frame_arg_to_storage ((MonoInterpFrameHandle)frame, sig, -1); + ccontext->gregs [cinfo->ret.reg] = (host_mgreg_t)storage; } } - for (int i = 0; i < sig->param_count + sig->hasthis; i++) { - ArgInfo *ainfo = &cinfo->args [i]; - gpointer storage; - int storage_type = ainfo->storage; - int reg_storage = ainfo->reg; - switch (storage_type) { - case ArgInIReg: { - storage = &ccontext->gregs [reg_storage]; - break; - } - case ArgInFloatSSEReg: - case ArgInDoubleSSEReg: { - storage = &ccontext->fregs [reg_storage]; - break; - } - case ArgOnStack: { - storage = (char*)ccontext->stack + ainfo->offset; - break; - } - case ArgValuetypeInReg: { - // FIXME? Alloca in a loop. - storage = g_newa (mgreg_t, ainfo->nregs); - break; - } - default: - g_error ("Arg storage type not yet supported"); - } + g_assert (!sig->hasthis); + + for (int i = 0; i < sig->param_count; i++) { + ainfo = &cinfo->args [i]; + int temp_size = arg_need_temp (ainfo); + + if (temp_size) + storage = alloca (temp_size); // FIXME? alloca in a loop + else + storage = arg_get_storage (ccontext, ainfo); + interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, i, storage); - if (storage_type == ArgValuetypeInReg) { - /* Split up the value type into the reg pairs */ - for (int k = 0; k < ainfo->nregs; k++) { - storage_type = ainfo->pair_storage [k]; - reg_storage = ainfo->pair_regs [k]; - switch (storage_type) { - case ArgInIReg: - ccontext->gregs [reg_storage] = *(mgreg_t*)storage; - break; - case ArgInFloatSSEReg: - case ArgInDoubleSSEReg: - ccontext->fregs [reg_storage] = *(double*)storage; - break; - default: - g_assert_not_reached (); - } - storage = (gpointer*)storage + 1; - } + if (temp_size) + arg_set_val (ccontext, ainfo, storage); + } + + g_free (cinfo); +} + +void +mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) +{ + MonoEECallbacks *interp_cb; + CallInfo *cinfo; + gpointer storage; + ArgInfo *ainfo; + + if (sig->ret->type == MONO_TYPE_VOID) + return; + + interp_cb = mini_get_interp_callbacks (); + cinfo = get_call_info (NULL, sig); + ainfo = &cinfo->ret; + + if (cinfo->ret.storage != ArgValuetypeAddrInIReg) { + int temp_size = arg_need_temp (ainfo); + + if (temp_size) + storage = alloca (temp_size); + else + storage = arg_get_storage (ccontext, ainfo); + memset (ccontext, 0, sizeof (CallContext)); // FIXME + interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); + if (temp_size) + arg_set_val (ccontext, ainfo, storage); + } + + g_free (cinfo); +} + +void +mono_arch_get_native_call_context_args (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) +{ + MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); + CallInfo *cinfo = get_call_info (NULL, sig); + gpointer storage; + ArgInfo *ainfo; + + if (sig->ret->type != MONO_TYPE_VOID) { + ainfo = &cinfo->ret; + if (ainfo->storage == ArgValuetypeAddrInIReg) { + storage = (gpointer) ccontext->gregs [cinfo->ret.reg]; + interp_cb->frame_arg_set_storage ((MonoInterpFrameHandle)frame, sig, -1, storage); + } + } + + for (int i = 0; i < sig->param_count + sig->hasthis; i++) { + ainfo = &cinfo->args [i]; + int temp_size = arg_need_temp (ainfo); + + if (temp_size) { + storage = alloca (temp_size); // FIXME? alloca in a loop + arg_get_val (ccontext, ainfo, storage); + } else { + storage = arg_get_storage (ccontext, ainfo); } + interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, i, storage); } g_free (cinfo); @@ -1167,63 +1277,32 @@ mono_arch_set_native_call_context_args (CallContext *ccontext, gpointer frame, M void mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) { - MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); + MonoEECallbacks *interp_cb; CallInfo *cinfo; + ArgInfo *ainfo; + gpointer storage; /* No return value */ if (sig->ret->type == MONO_TYPE_VOID) return; + interp_cb = mini_get_interp_callbacks (); cinfo = get_call_info (NULL, sig); + ainfo = &cinfo->ret; /* The return values were stored directly at address passed in reg */ - if (cinfo->ret.storage == ArgValuetypeAddrInIReg) - goto done; + if (cinfo->ret.storage != ArgValuetypeAddrInIReg) { + int temp_size = arg_need_temp (ainfo); - ArgInfo *ainfo; - ainfo = &cinfo->ret; - gpointer storage; - int storage_type; - storage_type = ainfo->storage; - int reg_storage; - reg_storage = ainfo->reg; - switch (storage_type) { - case ArgInIReg: { - storage = &ccontext->gregs [reg_storage]; - break; - } - case ArgInFloatSSEReg: - case ArgInDoubleSSEReg: { - storage = &ccontext->fregs [reg_storage]; - break; - } - case ArgValuetypeInReg: { - storage = g_newa (mgreg_t, ainfo->nregs); - mgreg_t *storage_tmp = (mgreg_t*)storage; - /* Reconstruct the value type */ - for (int k = 0; k < ainfo->nregs; k++) { - storage_type = ainfo->pair_storage [k]; - reg_storage = ainfo->pair_regs [k]; - switch (storage_type) { - case ArgInIReg: - *storage_tmp = ccontext->gregs [reg_storage]; - break; - case ArgInFloatSSEReg: - case ArgInDoubleSSEReg: - *(double*)storage_tmp = ccontext->fregs [reg_storage]; - break; - default: - g_assert_not_reached (); - } - storage_tmp++; - } - break; + if (temp_size) { + storage = alloca (temp_size); + arg_get_val (ccontext, ainfo, storage); + } else { + storage = arg_get_storage (ccontext, ainfo); } - default: - g_error ("Arg storage type not yet supported"); + interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, -1, storage); } - interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, -1, storage); -done: + g_free (cinfo); } diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index a89dd580959..8acc897669b 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -346,8 +346,8 @@ typedef struct { /* Floating registers */ double fregs [AMD64_XMM_NREG]; /* Stack usage, used for passing params on stack */ - size_t stack_size; - gpointer *stack; + guint32 stack_size; + guint8 *stack; } CallContext; #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->gregs [AMD64_RAX] = (gsize)exc; } while (0) @@ -464,6 +464,7 @@ typedef struct { #define MONO_ARCH_FLOAT32_SUPPORTED 1 #define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP +#define MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE 1 #define MONO_ARCH_HAVE_INTERP_NATIVE_TO_MANAGED 1 #if defined(TARGET_OSX) || defined(__linux__) diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 107d9f2a3f9..aeece6ebbae 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -1727,19 +1727,23 @@ mono_arch_set_native_call_context_args (CallContext *ccontext, gpointer frame, M void mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) { - MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); - CallInfo *cinfo = get_call_info (NULL, sig); + MonoEECallbacks *interp_cb; + CallInfo *cinfo; gpointer storage; ArgInfo *ainfo; - if (sig->ret->type != MONO_TYPE_VOID) { - ainfo = &cinfo->ret; - if (ainfo->storage != RegTypeStructByAddr) { - g_assert (!arg_need_temp (ainfo)); - storage = arg_get_storage (ccontext, ainfo); - memset (ccontext, 0, sizeof (CallContext)); // FIXME - interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); - } + if (sig->ret->type == MONO_TYPE_VOID) + return; + + interp_cb = mini_get_interp_callbacks (); + cinfo = get_call_info (NULL, sig); + ainfo = &cinfo->ret; + + if (ainfo->storage != RegTypeStructByAddr) { + g_assert (!arg_need_temp (ainfo)); + storage = arg_get_storage (ccontext, ainfo); + memset (ccontext, 0, sizeof (CallContext)); // FIXME + interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); } g_free (cinfo); @@ -1782,18 +1786,22 @@ mono_arch_get_native_call_context_args (CallContext *ccontext, gpointer frame, M void mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) { - MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); - CallInfo *cinfo = get_call_info (NULL, sig); + MonoEECallbacks *interp_cb; + CallInfo *cinfo; ArgInfo *ainfo; gpointer storage; - if (sig->ret->type != MONO_TYPE_VOID) { - ainfo = &cinfo->ret; - if (ainfo->storage != RegTypeStructByAddr) { - g_assert (!arg_need_temp (ainfo)); - storage = arg_get_storage (ccontext, ainfo); - interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, -1, storage); - } + if (sig->ret->type == MONO_TYPE_VOID) + return; + + interp_cb = mini_get_interp_callbacks (); + cinfo = get_call_info (NULL, sig); + ainfo = &cinfo->ret; + + if (ainfo->storage != RegTypeStructByAddr) { + g_assert (!arg_need_temp (ainfo)); + storage = arg_get_storage (ccontext, ainfo); + interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, -1, storage); } g_free (cinfo); diff --git a/mono/mini/mini-arm64.c b/mono/mini/mini-arm64.c index 88f7bee8202..6c7405b165b 100644 --- a/mono/mini/mini-arm64.c +++ b/mono/mini/mini-arm64.c @@ -1484,25 +1484,29 @@ mono_arch_set_native_call_context_args (CallContext *ccontext, gpointer frame, M void mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) { - MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); - CallInfo *cinfo = get_call_info (NULL, sig); + MonoEECallbacks *interp_cb; + CallInfo *cinfo; gpointer storage; ArgInfo *ainfo; - if (sig->ret->type != MONO_TYPE_VOID) { - ainfo = &cinfo->ret; - if (ainfo->storage != ArgVtypeByRef) { - int temp_size = arg_need_temp (ainfo); + if (sig->ret->type == MONO_TYPE_VOID) + return; - if (temp_size) - storage = alloca (temp_size); - else - storage = arg_get_storage (ccontext, ainfo); - memset (ccontext, 0, sizeof (CallContext)); // FIXME - interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); - if (temp_size) - arg_set_val (ccontext, ainfo, storage); - } + interp_cb = mini_get_interp_callbacks (); + cinfo = get_call_info (NULL, sig); + ainfo = &cinfo->ret; + + if (ainfo->storage != ArgVtypeByRef) { + int temp_size = arg_need_temp (ainfo); + + if (temp_size) + storage = alloca (temp_size); + else + storage = arg_get_storage (ccontext, ainfo); + memset (ccontext, 0, sizeof (CallContext)); // FIXME + interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); + if (temp_size) + arg_set_val (ccontext, ainfo, storage); } g_free (cinfo); @@ -1545,24 +1549,28 @@ mono_arch_get_native_call_context_args (CallContext *ccontext, gpointer frame, M void mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) { - MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); - CallInfo *cinfo = get_call_info (NULL, sig); + MonoEECallbacks *interp_cb; + CallInfo *cinfo; ArgInfo *ainfo; gpointer storage; - if (sig->ret->type != MONO_TYPE_VOID) { - ainfo = &cinfo->ret; - if (ainfo->storage != ArgVtypeByRef) { - int temp_size = arg_need_temp (ainfo); + if (sig->ret->type == MONO_TYPE_VOID) + return; - if (temp_size) { - storage = alloca (temp_size); - arg_get_val (ccontext, ainfo, storage); - } else { - storage = arg_get_storage (ccontext, ainfo); - } - interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, -1, storage); + interp_cb = mini_get_interp_callbacks (); + cinfo = get_call_info (NULL, sig); + ainfo = &cinfo->ret; + + if (ainfo->storage != ArgVtypeByRef) { + int temp_size = arg_need_temp (ainfo); + + if (temp_size) { + storage = alloca (temp_size); + arg_get_val (ccontext, ainfo, storage); + } else { + storage = arg_get_storage (ccontext, ainfo); } + interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, -1, storage); } g_free (cinfo); diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c index 8d98010516e..9c88f06c8ea 100644 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -1021,6 +1021,79 @@ mono_arch_get_interp_to_native_trampoline (MonoTrampInfo **info) return NULL; #endif /* DISABLE_INTERPRETER */ } + +gpointer +mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info) +{ +#ifndef DISABLE_INTERPRETER + guint8 *start = NULL, *code; + MonoJumpInfo *ji = NULL; + GSList *unwind_ops = NULL; + int buf_len, i; + int framesize; + + buf_len = 512; + start = code = (guint8 *) mono_global_codeman_reserve (buf_len); + + unwind_ops = mono_arch_get_cie_program (); + + amd64_push_reg (code, AMD64_RBP); + /* CFA = SP + 8 (RIP) + 8 (RBP) */ + mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, 16); + mono_add_unwind_op_offset (unwind_ops, code, start, AMD64_RBP, -16); + + amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof (mgreg_t)); + mono_add_unwind_op_def_cfa (unwind_ops, code, start, AMD64_RBP, 16); + + /* allocate the CallContext on the stack */ + framesize = ALIGN_TO (MONO_ABI_SIZEOF (CallContext), MONO_ARCH_FRAME_ALIGNMENT); + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize); + + /* save all general purpose registers into the CallContext */ + for (i = 0; i < PARAM_REGS; i++) + amd64_mov_membase_reg (code, AMD64_RSP, MONO_STRUCT_OFFSET (CallContext, gregs) + param_regs [i] * sizeof (mgreg_t), param_regs [i], sizeof (mgreg_t)); + + /* save all floating registers into the CallContext */ + for (i = 0; i < FLOAT_PARAM_REGS; i++) + amd64_sse_movsd_membase_reg (code, AMD64_RSP, MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double), i); + + /* set the stack pointer to the value at call site */ + amd64_mov_reg_reg (code, AMD64_R11, AMD64_RBP, sizeof (mgreg_t)); + amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, 2 * sizeof (mgreg_t)); + amd64_mov_membase_reg (code, AMD64_RSP, MONO_STRUCT_OFFSET (CallContext, stack), AMD64_R11, sizeof (mgreg_t)); + + /* call interp_entry with the ccontext and rmethod as arguments */ + amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RSP, sizeof (mgreg_t)); + amd64_mov_reg_membase (code, AMD64_ARG_REG2, MONO_ARCH_RGCTX_REG, MONO_STRUCT_OFFSET (MonoFtnDesc, arg), sizeof (mgreg_t)); + amd64_mov_reg_membase (code, AMD64_R11, MONO_ARCH_RGCTX_REG, MONO_STRUCT_OFFSET (MonoFtnDesc, addr), sizeof (mgreg_t)); + amd64_call_reg (code, AMD64_R11); + + /* load the return values from the context */ + for (i = 0; i < RETURN_REGS; i++) + amd64_mov_reg_membase (code, return_regs [i], AMD64_RSP, MONO_STRUCT_OFFSET (CallContext, gregs) + return_regs [i] * sizeof (mgreg_t), sizeof (mgreg_t)); + + for (i = 0; i < FLOAT_RETURN_REGS; i++) + amd64_sse_movsd_reg_membase (code, i, AMD64_RSP, MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double)); + + /* reset stack and return */ + amd64_mov_reg_reg (code, AMD64_RSP, AMD64_RBP, 8); + amd64_pop_reg (code, AMD64_RBP); + amd64_ret (code); + + g_assert (code - start < buf_len); + + mono_arch_flush_icache (start, code - start); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); + + if (info) + *info = mono_tramp_info_create ("native_to_interp_trampoline", start, code - start, ji, unwind_ops); + + return start; +#else + g_assert_not_reached (); + return NULL; +#endif /* DISABLE_INTERPRETER */ +} #endif /* !DISABLE_JIT */ #ifdef DISABLE_JIT @@ -1086,4 +1159,11 @@ mono_arch_get_interp_to_native_trampoline (MonoTrampInfo **info) g_assert_not_reached (); return NULL; } + +gpointer +mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info) +{ + g_assert_not_reached (); + return NULL; +} #endif /* DISABLE_JIT */ |