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:
authorVlad Brezae <brezaevlad@gmail.com>2018-10-18 22:55:37 +0300
committerLudovic Henry <luhenry@microsoft.com>2018-10-18 22:55:37 +0300
commitf0db92c2b6d3e6690cdc1069237f034570950e62 (patch)
tree7fce0a489441dd611d721390c4647d55e8fcc7a1
parentc1f1a7bfed91e05a968e3ca8940c9684bd1e4392 (diff)
[interp] Implement interpreter entry trampolines on amd64 (#10978) (#11165)
* [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.c4
-rw-r--r--mono/mini/mini-amd64.c263
-rw-r--r--mono/mini/mini-amd64.h5
-rw-r--r--mono/mini/mini-arm.c46
-rw-r--r--mono/mini/mini-arm64.c64
-rw-r--r--mono/mini/tramp-amd64.c80
6 files changed, 323 insertions, 139 deletions
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c
index 72adcbab7c9..61bb53847f7 100644
--- a/mono/mini/aot-compiler.c
+++ b/mono/mini/aot-compiler.c
@@ -7851,11 +7851,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
}
/*
@@ -12816,6 +12818,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);
@@ -12823,6 +12826,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 1ad38235798..a4b3c5ece9c 100644
--- a/mono/mini/mini-amd64.c
+++ b/mono/mini/mini-amd64.c
@@ -1087,133 +1087,216 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
return cinfo;
}
+static int
+arg_need_temp (ArgInfo *ainfo)
+{
+ if (ainfo->storage == ArgValuetypeInReg)
+ return ainfo->nregs * sizeof (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));
+
+ mgreg_t *dest_cast = (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));
+
+ mgreg_t *src_cast = (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 = 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] = (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] = (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: {
- storage = alloca (ainfo->nregs * sizeof (mgreg_t));
- 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);
}
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 = &cinfo->ret;
- 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 ArgValuetypeInReg: {
- storage = alloca (ainfo->nregs * sizeof (mgreg_t));
- mgreg_t *storage_tmp = 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 52a2f86ef19..c8c077dbe13 100644
--- a/mono/mini/mini-amd64.h
+++ b/mono/mini/mini-amd64.h
@@ -331,8 +331,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)
@@ -451,6 +451,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 06bd9533a5c..2c567f9f92c 100644
--- a/mono/mini/mini-arm.c
+++ b/mono/mini/mini-arm.c
@@ -1723,19 +1723,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);
@@ -1778,18 +1782,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 e0e9b12b018..b4707111a36 100644
--- a/mono/mini/mini-arm64.c
+++ b/mono/mini/mini-arm64.c
@@ -1486,25 +1486,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);
@@ -1547,24 +1551,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 e9ee72523f7..bcdaebad972 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 (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 */