Please see the attached patch that is a separated and improved version
of the prevously submitted patch.
ChangeLog draft:
mono_image_fixup_vtable is now called only when the image is loaded and
creates trampolines rather than pointers to wrapper functions.
A new trampoline type MONO_TRAMPOLINE_VTFIXUP is added that is created
by mono_image_fixup_vtable, and is replacing the pointer to the
trampoline with the result mono_marshal_get_vtfixup_ftnptr.
Please review and if you like it, approve the patch.
Thanks.
Kornél
Index: mono/mono/metadata/assembly.c
===================================================================
--- mono/mono/metadata/assembly.c (revision 145149)
+++ mono/mono/metadata/assembly.c (working copy)
@@ -1522,11 +1522,6 @@
loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
mono_assemblies_unlock ();
-#ifdef PLATFORM_WIN32
- if (image->is_module_handle)
- mono_image_fixup_vtable (image);
-#endif
-
mono_assembly_invoke_load_hook (ass);
mono_profiler_assembly_loaded (ass, MONO_PROFILE_OK);
Index: mono/mono/metadata/coree.c
===================================================================
--- mono/mono/metadata/coree.c (revision 145149)
+++ mono/mono/metadata/coree.c (working copy)
@@ -106,20 +106,12 @@
}
}
- if (!image) {
- g_free (file_name);
+ g_free (file_name);
+
+ if (!image)
return FALSE;
- }
- /*
- * FIXME: Find a better way to call mono_image_fixup_vtable.
Only
- * loader trampolines should be used and assembly loading should
- * probably be delayed until the first call to an exported
function.
- */
- if (image->tables [MONO_TABLE_ASSEMBLY].rows &&
((MonoCLIImageInfo*) image->image_info)->cli_cli_header.ch_vtable_fixups.rva)
- assembly = mono_assembly_open (file_name, NULL);
-
- g_free (file_name);
+ mono_image_fixup_vtable (image);
break;
case DLL_PROCESS_DETACH:
if (lpReserved != NULL)
@@ -198,6 +190,8 @@
argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
LocalFree (argvw);
+ mono_image_fixup_vtable (image);
+
mono_runtime_run_main (method, argc, argv, NULL);
mono_thread_manage ();
@@ -919,8 +913,10 @@
void
mono_fixup_exe_image (MonoImage* image)
{
- if (!init_from_coree && image && image->is_module_handle)
+ if (!init_from_coree && image && image->is_module_handle) {
MonoFixupExe ((HMODULE) image->raw_data);
+ mono_image_fixup_vtable (image);
+ }
}
#endif /* PLATFORM_WIN32 */
Index: mono/mono/metadata/object.c
===================================================================
--- mono/mono/metadata/object.c (revision 145149)
+++ mono/mono/metadata/object.c (working copy)
@@ -470,10 +470,18 @@
return NULL;
}
+static gpointer
+default_vtfixup_trampoline (gpointer slot, MonoImage *image, guint32 token,
guint16 type)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
static MonoJumpTrampoline arch_create_jump_trampoline =
default_jump_trampoline;
static MonoRemotingTrampoline arch_create_remoting_trampoline =
default_remoting_trampoline;
static MonoDelegateTrampoline arch_create_delegate_trampoline =
default_delegate_trampoline;
+static MonoVTFixupTrampoline arch_create_vtfixup_trampoline =
default_vtfixup_trampoline;
static MonoImtThunkBuilder imt_thunk_builder = NULL;
#define ARCH_USE_IMT (imt_thunk_builder != NULL)
#if (MONO_IMT_SIZE > 32)
@@ -517,6 +525,12 @@
}
void
+mono_install_vtfixup_trampoline (MonoVTFixupTrampoline func)
+{
+ arch_create_vtfixup_trampoline = func? func: default_vtfixup_trampoline;
+}
+
+void
mono_install_imt_thunk_builder (MonoImtThunkBuilder func) {
imt_thunk_builder = func;
}
@@ -564,6 +578,12 @@
return arch_create_delegate_trampoline (klass);
}
+gpointer
+mono_runtime_create_vtfixup_trampoline (gpointer slot, MonoImage *image,
guint32 token, guint16 type)
+{
+ return arch_create_vtfixup_trampoline (slot, image, token, type);
+}
+
static MonoFreeMethodFunc default_mono_free_method = NULL;
/**
Index: mono/mono/metadata/class-internals.h
===================================================================
--- mono/mono/metadata/class-internals.h (revision 145149)
+++ mono/mono/metadata/class-internals.h (working copy)
@@ -803,6 +803,7 @@
typedef gpointer (*MonoJumpTrampoline) (MonoDomain *domain, MonoMethod
*method, gboolean add_sync_wrapper);
typedef gpointer (*MonoRemotingTrampoline) (MonoDomain *domain,
MonoMethod *method, MonoRemotingTarget target);
typedef gpointer (*MonoDelegateTrampoline) (MonoClass *klass);
+typedef gpointer (*MonoVTFixupTrampoline) (gpointer slot, MonoImage
*image, guint32 token, guint16 type);
typedef gpointer (*MonoLookupDynamicToken) (MonoImage *image, guint32 token,
gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
@@ -892,6 +893,9 @@
void
mono_install_delegate_trampoline (MonoDelegateTrampoline func) MONO_INTERNAL;
+void
+mono_install_vtfixup_trampoline (MonoVTFixupTrampoline func) MONO_INTERNAL;
+
gpointer
mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext
*context) MONO_INTERNAL;
@@ -907,6 +911,9 @@
gpointer
mono_runtime_create_delegate_trampoline (MonoClass *klass) MONO_INTERNAL;
+gpointer
+mono_runtime_create_vtfixup_trampoline (gpointer slot, MonoImage *image,
guint32 token, guint16 type) MONO_INTERNAL;
+
void
mono_install_get_cached_class_info (MonoGetCachedClassInfo func) MONO_INTERNAL;
Index: mono/mono/metadata/image.c
===================================================================
--- mono/mono/metadata/image.c (revision 145149)
+++ mono/mono/metadata/image.c (working copy)
@@ -572,10 +572,6 @@
if (image->modules [idx - 1]) {
mono_image_addref (image->modules [idx - 1]);
image->modules [idx - 1]->assembly =
image->assembly;
-#ifdef PLATFORM_WIN32
- if (image->modules [idx - 1]->is_module_handle)
- mono_image_fixup_vtable (image->modules
[idx - 1]);
-#endif
/* g_print ("loaded module %s from %s (%p)\n",
module_ref, image->name, image->assembly); */
}
g_free (module_ref);
@@ -1292,7 +1288,6 @@
void
mono_image_fixup_vtable (MonoImage *image)
{
-#ifdef PLATFORM_WIN32
MonoCLIImageInfo *iinfo;
MonoPEDirEntry *de;
MonoVTableFixup *vtfixup;
@@ -1301,7 +1296,10 @@
guint16 slot_type;
int slot_count;
- g_assert (image->is_module_handle);
+#ifdef PLATFORM_WIN32
+ if (!image->is_module_handle)
+#endif
+ g_assert_not_reached();
iinfo = image->image_info;
de = &iinfo->cli_cli_header.ch_vtable_fixups;
@@ -1310,7 +1308,7 @@
vtfixup = (MonoVTableFixup*) mono_image_rva_map (image, de->rva);
if (!vtfixup)
return;
-
+
count = de->size / sizeof (MonoVTableFixup);
while (count--) {
if (!vtfixup->rva || !vtfixup->count)
@@ -1320,24 +1318,26 @@
g_assert (slot);
slot_type = vtfixup->type;
slot_count = vtfixup->count;
- if (slot_type & VTFIXUP_TYPE_32BIT)
+
+ switch (slot_type & (VTFIXUP_TYPE_32BIT | VTFIXUP_TYPE_64BIT)) {
+ case VTFIXUP_TYPE_32BIT:
while (slot_count--) {
- *((guint32*) slot) = (guint32)
mono_marshal_get_vtfixup_ftnptr (image, *((guint32*) slot), slot_type);
+ *((guint32*) slot) = (guint32)
mono_runtime_create_vtfixup_trampoline (slot, image, *((guint32*) slot),
slot_type);
slot = ((guint32*) slot) + 1;
}
- else if (slot_type & VTFIXUP_TYPE_64BIT)
+ break;
+ case VTFIXUP_TYPE_64BIT:
while (slot_count--) {
- *((guint64*) slot) = (guint64)
mono_marshal_get_vtfixup_ftnptr (image, *((guint64*) slot), slot_type);
- slot = ((guint32*) slot) + 1;
+ *((guint64*) slot) = (guint64)
mono_runtime_create_vtfixup_trampoline (slot, image, *((guint64*) slot),
slot_type);
+ slot = ((guint64*) slot) + 1;
}
- else
+ break;
+ default:
g_assert_not_reached();
+ }
vtfixup++;
}
-#else
- g_assert_not_reached();
-#endif
}
static void
@@ -1926,10 +1926,6 @@
}
image->files [fileidx - 1] = res;
-#ifdef PLATFORM_WIN32
- if (res->is_module_handle)
- mono_image_fixup_vtable (res);
-#endif
}
mono_loader_unlock ();
g_free (name);
Index: mono/mono/metadata/marshal.c
===================================================================
--- mono/mono/metadata/marshal.c (revision 145149)
+++ mono/mono/metadata/marshal.c (working copy)
@@ -8591,7 +8591,7 @@
}
gpointer
-mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
+mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16
type, MonoMethod **wrapper_method)
{
MonoMethod *method;
MonoMethodSignature *sig;
@@ -8641,9 +8641,15 @@
mono_metadata_free_marshal_spec (mspecs [i]);
g_free (mspecs);
+ *wrapper_method = method;
return mono_compile_method (method);
}
+ if (!(type & VTFIXUP_TYPE_CALL_MOST_DERIVED)) {
+ wrapper_method = NULL;
+ return mono_compile_method (method);
+ }
+
sig = mono_method_signature (method);
mb = mono_mb_new (method->klass, method->name,
MONO_WRAPPER_MANAGED_TO_MANAGED);
@@ -8651,16 +8657,14 @@
for (i = 0; i < param_count; i++)
mono_mb_emit_ldarg (mb, i);
- if (type & VTFIXUP_TYPE_CALL_MOST_DERIVED)
- mono_mb_emit_op (mb, CEE_CALLVIRT, method);
- else
- mono_mb_emit_op (mb, CEE_CALL, method);
+ mono_mb_emit_op (mb, CEE_CALLVIRT, method);
mono_mb_emit_byte (mb, CEE_RET);
mb->dynamic = 1;
method = mono_mb_create_method (mb, sig, param_count);
mono_mb_free (mb);
+ *wrapper_method = method;
return mono_compile_method (method);
}
Index: mono/mono/metadata/marshal.h
===================================================================
--- mono/mono/metadata/marshal.h (revision 145149)
+++ mono/mono/metadata/marshal.h (working copy)
@@ -199,7 +199,7 @@
mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass
*delegate_klass, MonoObject **this_loc) MONO_INTERNAL;
gpointer
-mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16
type) MONO_INTERNAL;
+mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16
type, MonoMethod **wrapper_method) MONO_INTERNAL;
MonoMethod *
mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name,
gconstpointer func, gboolean check_exceptions) MONO_INTERNAL;
Index: mono/mono/mini/mini.c
===================================================================
--- mono/mono/mini/mini.c (revision 145149)
+++ mono/mono/mini/mini.c (working copy)
@@ -5058,6 +5058,7 @@
mono_install_jump_trampoline (mono_create_jump_trampoline);
mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline);
mono_install_delegate_trampoline (mono_create_delegate_trampoline);
+ mono_install_vtfixup_trampoline (mono_create_vtfixup_trampoline);
mono_install_create_domain_hook (mini_create_jit_domain_info);
mono_install_free_domain_hook (mini_free_jit_domain_info);
#endif
Index: mono/mono/mini/mini.h
===================================================================
--- mono/mono/mini/mini.h (revision 145149)
+++ mono/mono/mini/mini.h (working copy)
@@ -827,6 +827,7 @@
MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
MONO_TRAMPOLINE_MONITOR_ENTER,
MONO_TRAMPOLINE_MONITOR_EXIT,
+ MONO_TRAMPOLINE_VTFIXUP,
#ifdef ENABLE_LLVM
MONO_TRAMPOLINE_LLVM_VCALL,
#endif
@@ -1482,6 +1483,7 @@
gpointer mono_create_monitor_enter_trampoline (void) MONO_INTERNAL;
gpointer mono_create_monitor_exit_trampoline (void) MONO_INTERNAL;
gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer
addr) MONO_INTERNAL;
+gpointer mono_create_vtfixup_trampoline (gpointer slot, MonoImage
*image, guint32 token, guint16 type) MONO_INTERNAL;
gpointer mono_create_llvm_vcall_trampoline (MonoMethod *method)
MONO_INTERNAL;
MonoVTable* mono_find_class_init_trampoline_by_addr (gconstpointer addr)
MONO_INTERNAL;
guint32 mono_find_rgctx_lazy_fetch_trampoline_by_addr (gconstpointer
addr) MONO_INTERNAL;
Index: mono/mono/mini/mini-trampolines.c
===================================================================
--- mono/mono/mini/mini-trampolines.c (revision 145149)
+++ mono/mono/mini/mini-trampolines.c (working copy)
@@ -6,6 +6,8 @@
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/cil-coff.h>
#include <mono/utils/mono-counters.h>
#ifdef HAVE_VALGRIND_MEMCHECK_H
@@ -779,6 +781,61 @@
mono_monitor_exit (obj);
}
+static gpointer
+mono_vtfixup_trampoline (gssize *regs, guint8 *code, guint8 *slot_info,
guint8* tramp)
+{
+ gpointer tramp_addr;
+ gpointer slot, slot_addr;
+ MonoImage *image;
+ guint32 token;
+ guint16 type;
+ gpointer addr;
+ MonoMethod *wrapper_method;
+ MonoImageOpenStatus status;
+
+ tramp_addr = *((gpointer*) (gpointer) slot_info);
+ slot_info += sizeof (gpointer);
+ slot = *((gpointer*) (gpointer) slot_info);
+ slot_info += sizeof (gpointer);
+ image = *((gpointer*) (gpointer) slot_info);
+ slot_info += sizeof (gpointer);
+ token = *((guint32*) (gpointer) slot_info);
+ slot_info += sizeof (guint32);
+ type = *((guint16*) (gpointer) slot_info);
+
+ if (type & VTFIXUP_TYPE_64BIT)
+ slot_addr = (gpointer) *((volatile gint64*) (slot));
+ else
+ slot_addr = (gpointer) *((volatile gint32*) (slot));
+
+ if (slot_addr != tramp_addr)
+ return slot_addr;
+
+ if (!image->assembly) {
+ // FIXME: Throw exceptions when assembly cannot be loaded
+ // FIXME: Fix mono_assembly_load_from_full to allow loading
mscorlib.dll
+ g_assert (mono_assembly_load_from_full (image, image->name,
&status, FALSE));
+ }
+
+ addr = mono_marshal_get_vtfixup_ftnptr (image, token, type,
&wrapper_method);
+ if (type & VTFIXUP_TYPE_64BIT)
+#if SIZEOF_VOID_P == 8
+ slot_addr = InterlockedCompareExchangePointer (slot, addr,
tramp_addr);
+#else
+ slot_addr = (gpointer)
ves_icall_System_Threading_Interlocked_CompareExchange_Long ((gint64*) slot,
(gint64) addr, (gint64) tramp_addr);
+#endif
+ else
+ slot_addr = (gpointer) InterlockedCompareExchange ((gint32*)
slot, (gint32) addr, (gint32) tramp_addr);
+
+ if (slot_addr == tramp_addr)
+ return addr;
+
+ if (wrapper_method)
+ mono_free_method (wrapper_method);
+
+ return slot_addr;
+}
+
#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
/**
@@ -922,6 +979,8 @@
return mono_monitor_enter_trampoline;
case MONO_TRAMPOLINE_MONITOR_EXIT:
return mono_monitor_exit_trampoline;
+ case MONO_TRAMPOLINE_VTFIXUP:
+ return mono_vtfixup_trampoline;
#ifdef ENABLE_LLVM
case MONO_TRAMPOLINE_LLVM_VCALL:
return mono_llvm_vcall_trampoline;
@@ -956,6 +1015,7 @@
mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING);
mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER);
mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_EXIT] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
+ mono_trampoline_code [MONO_TRAMPOLINE_VTFIXUP] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_VTFIXUP);
#ifdef ENABLE_LLVM
mono_trampoline_code [MONO_TRAMPOLINE_LLVM_VCALL] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_LLVM_VCALL);
#endif
@@ -1280,7 +1340,31 @@
#endif
return code;
}
-
+
+gpointer
+mono_create_vtfixup_trampoline (gpointer slot, MonoImage *image, guint32
token, guint16 type)
+{
+ gpointer tramp;
+
+ MonoDomain *domain = mono_get_root_domain ();
+ guint8 *buf, *start;
+
+ buf = start = mono_domain_code_reserve (domain, 3 * sizeof (gpointer) +
sizeof (guint32) + sizeof (guint16));
+
+ buf += sizeof (gpointer);
+ *(gpointer*) (gpointer) buf = slot;
+ buf += sizeof (gpointer);
+ *(gpointer*) (gpointer) buf = image;
+ buf += sizeof (gpointer);
+ *(guint32*) (gpointer) buf = token;
+ buf += sizeof (guint32);
+ *(guint16*) (gpointer) buf = type;
+
+ tramp = mono_create_specific_trampoline (start,
MONO_TRAMPOLINE_VTFIXUP, domain, NULL);
+ *(gpointer*) (gpointer) start = tramp;
+ return tramp;
+}
+
#ifdef ENABLE_LLVM
/*
* mono_create_llvm_vcall_trampoline:
_______________________________________________
Mono-devel-list mailing list
[email protected]
http://lists.ximian.com/mailman/listinfo/mono-devel-list