Lldb support code for mono (#4225)
[mono.git] / mono / mini / mini-trampolines.c
index 68b5a8b0a47b5efbfa8421bb212c0f8d014e905a..7d6712c958b5b2cbaa6e6455902f4b5790a75c17 100644 (file)
@@ -18,6 +18,7 @@
 #include <mono/utils/mono-threads-coop.h>
 
 #include "mini.h"
+#include "lldb.h"
 
 /*
  * Address of the trampoline code.  This is used by the debugger to check
@@ -154,7 +155,7 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr)
  * Either IMPL_METHOD or OUT_AOT_ADDR will be set on return.
  */
 gpointer*
-mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr, gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface)
+mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr, gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface, MonoError *error)
 {
        MonoMethod *impl = NULL, *generic_virtual = NULL;
        gboolean lookup_aot, variance_used = FALSE, need_rgctx_tramp = FALSE;
@@ -166,6 +167,7 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
 
        g_assert (imt_slot < MONO_IMT_SIZE);
 
+       mono_error_init (error);
        /* This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement */
        interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, &variance_used);
        if (interface_offset < 0)
@@ -188,7 +190,6 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
                mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));
 
        if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
-               MonoError error;
                MonoGenericContext context = { NULL, NULL };
 
                /*
@@ -198,18 +199,17 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
                /* imt_method->slot might not be set */
                impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot);
 
-               if (impl->klass->generic_class)
-                       context.class_inst = impl->klass->generic_class->context.class_inst;
+               if (mono_class_is_ginst (impl->klass))
+                       context.class_inst = mono_class_get_generic_class (impl->klass)->context.class_inst;
                context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst;
-               impl = mono_class_inflate_generic_method_checked (impl, &context, &error);
-               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+               impl = mono_class_inflate_generic_method_checked (impl, &context, error);
+               mono_error_assert_ok (error);
        } else {
-               MonoError error;
 
                /* Avoid loading metadata or creating a generic vtable if possible */
                if (lookup_aot && !vt->klass->valuetype) {
-                       aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method), &error);
-                       mono_error_raise_exception (&error); // FIXME: Don't raise here
+                       aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method), error);
+                       return_val_if_nok (error, NULL);
                } else {
                        aot_addr = NULL;
                }
@@ -367,12 +367,9 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad
 
        if (callee_array_helper) {
                add_static_rgctx_tramp = FALSE;
-               /* FIXME: ji->from_aot is not set for llvm methods */
-               if (ji && (ji->from_aot || mono_aot_only)) {
-                       /* In AOT mode, compiled_method points to one of the InternalArray methods in Array. */
-                       if (!mono_llvm_only && mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE))
-                               add_static_rgctx_tramp = TRUE;
-               }
+               /* In AOT mode, compiled_method points to one of the InternalArray methods in Array. */
+               if (ji && !mono_llvm_only && mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE))
+                       add_static_rgctx_tramp = TRUE;
        }
 
        if (mono_llvm_only)
@@ -562,8 +559,10 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                                need_rgctx_tramp = TRUE;
                        }
 
-                       vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface);
-                       /* This is the vcall slot which gets called through the IMT thunk */
+                       vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface, error);
+                       return_val_if_nok (error, NULL);
+
+                       /* This is the vcall slot which gets called through the IMT trampoline */
                        vtable_slot_to_patch = vtable_slot;
 
                        if (addr) {
@@ -585,7 +584,6 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
         * return TRUE for methods used in IMT calls too.
         */
        if (virtual_ && is_generic_method_definition (m)) {
-               MonoError error;
                MonoGenericContext context = { NULL, NULL };
                MonoMethod *declaring;
 
@@ -594,18 +592,18 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                else
                        declaring = m;
 
-               if (m->klass->generic_class)
-                       context.class_inst = m->klass->generic_class->context.class_inst;
+               if (mono_class_is_ginst (m->klass))
+                       context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
                else
-                       g_assert (!m->klass->generic_container);
+                       g_assert (!mono_class_is_gtd (m->klass));
 
                generic_virtual = mono_arch_find_imt_method (regs, code);
                g_assert (generic_virtual);
                g_assert (generic_virtual->is_inflated);
                context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
 
-               m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
-               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+               m = mono_class_inflate_generic_method_checked (declaring, &context, error);
+               mono_error_assert_ok (error);
                /* FIXME: only do this if the method is sharable */
                need_rgctx_tramp = TRUE;
        } else if ((context_used = mono_method_check_context_used (m))) {
@@ -658,7 +656,6 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                }
 
                if (method_inst || m->wrapper_type) {
-                       MonoError error;
                        MonoGenericContext context = { NULL, NULL };
 
                        if (m->is_inflated)
@@ -666,14 +663,14 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                        else
                                declaring = m;
 
-                       if (klass->generic_class)
-                               context.class_inst = klass->generic_class->context.class_inst;
-                       else if (klass->generic_container)
-                               context.class_inst = klass->generic_container->context.class_inst;
+                       if (mono_class_is_ginst (klass))
+                               context.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
+                       else if (mono_class_is_gtd (klass))
+                               context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
                        context.method_inst = method_inst;
 
-                       actual_method = mono_class_inflate_generic_method_checked (declaring, &context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       actual_method = mono_class_inflate_generic_method_checked (declaring, &context, error);
+                       mono_error_assert_ok (error);
                } else {
                        actual_method = mono_class_get_method_generic (klass, m);
                }
@@ -800,7 +797,11 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                                 */
                                no_patch = TRUE;
                        }
-
+#if LLVM_API_VERSION > 100
+                       /* LLVM code doesn't make direct calls */
+                       if (ji && ji->from_llvm)
+                               no_patch = TRUE;
+#endif
                        if (!no_patch && mono_method_same_domain (ji, target_ji))
                                mono_arch_patch_callsite ((guint8 *)ji->code_start, code, (guint8 *)addr);
                }
@@ -850,7 +851,7 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp)
        gpointer *vtable_slot;
        MonoMethod *m;
        MonoError error;
-       gpointer addr, res;
+       gpointer addr, res = NULL;
 
        trampoline_calls ++;
 
@@ -935,10 +936,10 @@ mono_generic_virtual_remoting_trampoline (mgreg_t *regs, guint8 *code, MonoMetho
        else
                declaring = m;
 
-       if (m->klass->generic_class)
-               context.class_inst = m->klass->generic_class->context.class_inst;
+       if (mono_class_is_ginst (m->klass))
+               context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
        else
-               g_assert (!m->klass->generic_container);
+               g_assert (!mono_class_is_gtd (m->klass));
 
        imt_method = mono_arch_find_imt_method (regs, code);
        if (imt_method->is_inflated)
@@ -1188,7 +1189,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr
                         * If the call doesn't return a valuetype, then the vcall uses the same calling
                         * convention as a normal call.
                         */
-                       if (((method->klass->flags & TYPE_ATTRIBUTE_SEALED) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
+                       if ((mono_class_is_sealed (method->klass) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
                                callvirt = FALSE;
                                enable_caching = FALSE;
                        }
@@ -1197,7 +1198,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr
                if (delegate->target && 
                        method->flags & METHOD_ATTRIBUTE_VIRTUAL && 
                        method->flags & METHOD_ATTRIBUTE_ABSTRACT &&
-                       method->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) {
+                       mono_class_is_abstract (method->klass)) {
                        method = mono_object_get_virtual_method (delegate->target, method);
                        enable_caching = FALSE;
                }
@@ -1275,7 +1276,7 @@ mono_handler_block_guard_trampoline (mgreg_t *regs, guint8 *code, gpointer *tram
 
        MonoContext ctx;
        MonoException *exc;
-       MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
        gpointer resume_ip = jit_tls->handler_block_return_address;
 
        memcpy (&ctx, &jit_tls->handler_block_context, sizeof (MonoContext));
@@ -1301,15 +1302,19 @@ gpointer
 mono_create_handler_block_trampoline (void)
 {
        static gpointer code;
-       if (code) {
+
+       if (code)
+               return code;
+
+       if (mono_aot_only) {
+               gpointer tmp = mono_aot_get_trampoline ("handler_block_trampoline");
+               g_assert (tmp);
                mono_memory_barrier ();
+               code = tmp;
                return code;
        }
 
-       g_assert (!mono_aot_only);
-
        mono_trampolines_lock ();
-
        if (!code) {
                MonoTrampInfo *info;
                gpointer tmp;
@@ -1432,10 +1437,17 @@ mono_get_trampoline_code (MonoTrampolineType tramp_type)
 gpointer
 mono_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
 {
+       gpointer code;
+       guint32 len;
+
        if (mono_aot_only)
-               return mono_aot_create_specific_trampoline (mono_defaults.corlib, arg1, tramp_type, domain, code_len);
+               code = mono_aot_create_specific_trampoline (mono_defaults.corlib, arg1, tramp_type, domain, &len);
        else
-               return mono_arch_create_specific_trampoline (arg1, tramp_type, domain, code_len);
+               code = mono_arch_create_specific_trampoline (arg1, tramp_type, domain, &len);
+       mono_lldb_save_specific_trampoline_info (arg1, tramp_type, domain, code, len);
+       if (code_len)
+               *code_len = len;
+       return code;
 }
 
 gpointer
@@ -1506,14 +1518,16 @@ mono_create_jit_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *e
        mono_error_init (error);
 
        if (mono_aot_only) {
+               if (mono_llvm_only && method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+                       method = mono_marshal_get_synchronized_wrapper (method);
+
                /* Avoid creating trampolines if possible */
                gpointer code = mono_jit_find_compiled_method (domain, method);
                
                if (code)
                        return code;
                if (mono_llvm_only) {
-                       if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST || method->wrapper_type == MONO_WRAPPER_LDFLD_REMOTE ||
-                               method->wrapper_type == MONO_WRAPPER_STFLD_REMOTE)
+                       if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST)
                                /* These wrappers are not generated */
                                return method_not_found;
                        /* Methods are lazily initialized on first call, so this can't lead recursion */