2010-02-10 Miguel de Icaza <miguel@novell.com>
[mono.git] / mono / mini / mini-trampolines.c
index ef2fc96e0dc6f19329e6ccec31f7401f6a7ae388..2860fb4e20fd544126fdb0728d809dab4a73bcb3 100644 (file)
@@ -20,6 +20,7 @@ guint8* mono_trampoline_code [MONO_TRAMPOLINE_NUM];
 static GHashTable *class_init_hash_addr = NULL;
 static GHashTable *rgctx_lazy_fetch_trampoline_hash = NULL;
 static GHashTable *rgctx_lazy_fetch_trampoline_hash_addr = NULL;
+static guint32 trampoline_calls;
 
 #define mono_trampolines_lock() EnterCriticalSection (&trampolines_mutex)
 #define mono_trampolines_unlock() LeaveCriticalSection (&trampolines_mutex)
@@ -81,6 +82,7 @@ rgctx_tramp_info_hash (gconstpointer data)
  * methods code. These trampolines are similar to the unbox trampolines, they
  * perform the same task as the static rgctx wrappers, but they are smaller/faster,
  * and can be made to work with full AOT.
+ * On PPC addr should be an ftnptr and the return value is an ftnptr too.
  */
 gpointer
 mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr)
@@ -91,6 +93,10 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr)
        RgctxTrampInfo tmp_info;
        RgctxTrampInfo *info;
 
+#ifdef PPC_USES_FUNCTION_DESCRIPTOR
+       g_assert (((gpointer*)addr) [2] == 0);
+#endif
+
        if (mini_method_get_context (m)->method_inst)
                ctx = mono_method_lookup_rgctx (mono_class_vtable (mono_domain_get (), m->klass), mini_method_get_context (m)->method_inst);
        else
@@ -242,7 +248,7 @@ mono_convert_imt_slot_to_vtable_slot (gpointer* slot, mgreg_t *regs, guint8 *cod
 static gpointer
 common_call_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp, MonoVTable *vt, gpointer *vtable_slot, gboolean need_rgctx_tramp)
 {
-       gpointer addr;
+       gpointer addr, compiled_method;
        gboolean generic_shared = FALSE;
        MonoMethod *m;
        MonoMethod *declaring = NULL;
@@ -482,7 +488,7 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp
        if (!code && mono_method_needs_static_rgctx_invoke (m, FALSE))
                need_rgctx_tramp = TRUE;
 
-       addr = mono_compile_method (m);
+       addr = compiled_method = mono_compile_method (m);
        g_assert (addr);
 
        mono_debugger_trampoline_compiled (code, m, addr);
@@ -567,7 +573,7 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp
 
                        } else {
                                MonoJitInfo *target_ji = 
-                                       mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (addr));
+                                       mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method));
 
                                if (!ji)
                                        ji = mono_jit_info_table_find (mono_domain_get (), (char*)code);
@@ -593,6 +599,8 @@ mono_magic_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp)
        int displacement;
        MonoVTable *vt;
 
+       trampoline_calls ++;
+
        if (code && !mono_use_llvm)
                vt = mono_arch_get_vcall_slot (code, regs, &displacement);
        else
@@ -619,6 +627,8 @@ mono_llvm_vcall_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8 *
        gpointer *vtable_slot;
        int slot;
 
+       trampoline_calls ++;
+
        /* 
         * We have the method which is called, we need to obtain the vtable slot without
         * disassembly which is impossible with LLVM.
@@ -650,6 +660,8 @@ mono_generic_virtual_remoting_trampoline (mgreg_t *regs, guint8 *code, MonoMetho
        MonoMethod *imt_method, *declaring;
        gpointer addr;
 
+       trampoline_calls ++;
+
        g_assert (m->is_generic);
 
        if (m->is_inflated)
@@ -698,6 +710,8 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info,
        guint8 *plt_entry;
        gboolean need_rgctx_tramp = FALSE;
 
+       trampoline_calls ++;
+
        image = *(gpointer*)(gpointer)token_info;
        token_info += sizeof (gpointer);
        token = *(guint32*)(gpointer)token_info;
@@ -753,8 +767,19 @@ mono_aot_plt_trampoline (mgreg_t *regs, guint8 *code, guint8 *aot_module,
                                                 guint8* tramp)
 {
        guint32 plt_info_offset = mono_aot_get_plt_info_offset (regs, code);
+       gpointer res;
 
-       return mono_aot_plt_resolve (aot_module, plt_info_offset, code);
+       trampoline_calls ++;
+
+       res = mono_aot_plt_resolve (aot_module, plt_info_offset, code);
+       if (!res) {
+               if (mono_loader_get_last_error ())
+                       mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
+               // FIXME: Error handling (how ?)
+               g_assert (res);
+       }
+
+       return res;
 }
 #endif
 
@@ -769,6 +794,8 @@ mono_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, gui
 {
        guint8 *plt_entry = mono_aot_get_plt_entry (code);
 
+       trampoline_calls ++;
+
        mono_runtime_class_init (vtable);
 
        if (plt_entry) {
@@ -787,6 +814,8 @@ mono_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, gui
 void
 mono_generic_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
 {
+       trampoline_calls ++;
+
        mono_runtime_class_init (vtable);
 }
 
@@ -802,6 +831,8 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu
        guint32 index = MONO_RGCTX_SLOT_INDEX (slot);
        gboolean mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
 
+       trampoline_calls ++;
+
        if (!inited) {
                mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_lookups);
                inited = TRUE;
@@ -852,6 +883,8 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *tramp_data, gui
        guint8 *impl_this = tramp_data [1];
        guint8 *impl_nothis = tramp_data [2];
 
+       trampoline_calls ++;
+
        /* Obtain the delegate object according to the calling convention */
 
        /* 
@@ -1012,6 +1045,8 @@ mono_trampolines_init (void)
 #ifdef MONO_ARCH_LLVM_SUPPORTED
        mono_trampoline_code [MONO_TRAMPOLINE_LLVM_VCALL] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_LLVM_VCALL);
 #endif
+
+       mono_counters_register ("Calls to trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &trampoline_calls);
 }
 
 void
@@ -1086,7 +1121,8 @@ mono_create_generic_class_init_trampoline (void)
 
        if (!code) {
                if (mono_aot_only)
-                       code = mono_aot_get_named_code ("generic_class_init_trampoline");
+                       /* get_named_code () might return an ftnptr, but our caller expects a direct pointer */
+                       code = mono_get_addr_from_ftnptr (mono_aot_get_named_code ("generic_class_init_trampoline"));
                else
                        code = mono_arch_create_generic_class_init_trampoline ();
        }