MONO_TRAMPOLINE_CLASS_INIT
} MonoTrampolineType;
-/* adapt to mini later... */
-#define mono_jit_share_code (1)
-
/*
* Address of the trampoline code. This is used by the debugger to check
* whether a method is a trampoline.
*/
guint8 *mono_generic_trampoline_code = NULL;
+/*
+ * AMD64 processors maintain icache coherency only for pages which are marked
+ * executable, so we have to alloc memory through a code manager.
+ */
+static CRITICAL_SECTION tramp_codeman_mutex;
+static MonoCodeManager *tramp_codeman;
+
/*
* get_unbox_trampoline:
* @m: method pointer
{
guint8 *code, *start;
int this_reg = AMD64_RDI;
+ MonoDomain *domain = mono_domain_get ();
if (!m->signature->ret->byref && MONO_TYPE_ISSTRUCT (m->signature->ret))
this_reg = AMD64_RSI;
-
- start = code = g_malloc (20);
+
+ mono_domain_lock (domain);
+ start = code = mono_code_manager_reserve (domain->code_mp, 20);
+ mono_domain_unlock (domain);
amd64_alu_reg_imm (code, X86_ADD, this_reg, sizeof (MonoObject));
/* FIXME: Optimize this */
{
mono_runtime_class_init (vtable);
- /* FIXME: patch calling code */
-
code -= 3;
if ((code [0] == 0x49) && (code [1] == 0xff)) {
if (!mono_running_on_valgrind ()) {
+ /* amd64_set_reg_template is 10 bytes long */
+ guint8* buf = code - 10;
/* FIXME: Make this thread safe */
- code [0] = code [1] = code [2] = 0x90;
+ /* Padding code suggested by the AMD64 Opt Manual */
+ buf [0] = 0x66;
+ buf [1] = 0x66;
+ buf [2] = 0x66;
+ buf [3] = 0x90;
+ buf [4] = 0x66;
+ buf [5] = 0x66;
+ buf [6] = 0x66;
+ buf [7] = 0x90;
+ buf [8] = 0x66;
+ buf [9] = 0x66;
+ buf [10] = 0x90;
+ buf [11] = 0x66;
+ buf [12] = 0x90;
}
}
else
- if (code [0] == 0x90 || code [0] == 0xeb)
+ if (code [0] == 0x90 || code [0] == 0xeb || code [0] == 0x66)
/* Already changed by another thread */
;
else {
break;
}
- code = buf = g_malloc (512);
+ EnterCriticalSection (&tramp_codeman_mutex);
+ code = buf = mono_code_manager_reserve (tramp_codeman, 512);
+ LeaveCriticalSection (&tramp_codeman_mutex);
framesize = 512 + sizeof (MonoLMF);
framesize = (framesize + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
g_assert ((code - buf) <= 512);
+ mono_arch_flush_icache (buf, code - buf);
+
switch (tramp_type) {
case MONO_TRAMPOLINE_GENERIC:
mono_generic_trampoline_code = buf;
return buf;
}
-#define TRAMPOLINE_SIZE 30
+#define TRAMPOLINE_SIZE 34
static MonoJitInfo*
create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain)
MonoJitInfo *ji;
MonoDomain *domain = mono_domain_get ();
- /* Trampoline are arch specific, so cache only the one used in the root domain */
+ /* Trampoline are domain specific, so cache only the one used in the root domain */
if ((domain == mono_get_root_domain ()) && method->info)
return method->info;
return code;
}
+void
+mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
+{
+ /* FIXME: This is not thread safe */
+ guint8 *code = ji->code_start;
+
+ amd64_mov_reg_imm (code, AMD64_RDI, func_arg);
+ amd64_mov_reg_imm (code, AMD64_R11, func);
+
+ x86_push_imm (code, (guint64)func_arg);
+ amd64_call_reg (code, AMD64_R11);
+}
+
/*
* This method is only called when running in the Mono Debugger.
*/
{
guint8 *ptr, *buf;
- ptr = buf = g_malloc0 (16);
+ EnterCriticalSection (&tramp_codeman_mutex);
+ ptr = buf = mono_code_manager_reserve (tramp_codeman, 16);
+ LeaveCriticalSection (&tramp_codeman_mutex);
+
x86_breakpoint (buf);
if (notification_address)
*notification_address = buf;
return ptr;
}
+void
+mono_amd64_tramp_init (void)
+{
+ InitializeCriticalSection (&tramp_codeman_mutex);
+
+ tramp_codeman = mono_code_manager_new ();
+
+ create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
+ create_trampoline_code (MONO_TRAMPOLINE_JUMP);
+ create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
+}