New test.
[mono.git] / mono / mini / aot-compiler.c
index 0cbd6d0891adc1f2ea2193c41ad071402d6c15db..0afd5ba593f32b784d7f93d424757d18e01bd034 100644 (file)
@@ -57,7 +57,7 @@
 #include <mono/metadata/mempool-internals.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/threads-types.h>
-#include <mono/utils/mono-logger.h>
+#include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-mmap.h>
@@ -1197,32 +1197,6 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
 #endif
 }
 
-/*
- * mono_arch_get_cie_program:
- *
- *   Get the unwind bytecode for the DWARF CIE.
- */
-GSList*
-mono_arch_get_cie_program (void)
-{
-#ifdef TARGET_AMD64
-       GSList *l = NULL;
-
-       mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, AMD64_RSP, 8);
-       mono_add_unwind_op_offset (l, (guint8*)NULL, (guint8*)NULL, AMD64_RIP, -8);
-
-       return l;
-#elif defined(TARGET_POWERPC)
-       GSList *l = NULL;
-
-       mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ppc_r1, 0);
-
-       return l;
-#else
-       return NULL;
-#endif
-}
-
 /* END OF ARCH SPECIFIC CODE */
 
 static guint32
@@ -2386,7 +2360,7 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
 
        iter = NULL;
        while ((method = mono_class_get_methods (klass, &iter))) {
-               if (mono_method_is_generic_sharable_impl (method, FALSE))
+               if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE))
                        /* Already added */
                        continue;
 
@@ -2507,18 +2481,98 @@ add_generic_instances (MonoAotCompile *acfg)
                token = MONO_TOKEN_METHOD_SPEC | (i + 1);
                method = mono_get_method (acfg->image, token, NULL);
 
-               context = mono_method_get_context (method);
-               if (context && ((context->class_inst && context->class_inst->is_open) ||
-                                               (context->method_inst && context->method_inst->is_open)))
+               if (method->klass->image != acfg->image)
                        continue;
 
-               if (method->klass->image != acfg->image)
+               context = mono_method_get_context (method);
+
+               if (context && ((context->class_inst && context->class_inst->is_open)))
                        continue;
 
-               if (mono_method_is_generic_sharable_impl (method, FALSE))
-                       /* Already added */
+               /*
+                * For open methods, create an instantiation which can be passed to the JIT.
+                * FIXME: Handle class_inst as well.
+                */
+               if (context && context->method_inst && context->method_inst->is_open) {
+                       MonoGenericContext shared_context;
+                       MonoGenericInst *inst;
+                       MonoType **type_argv;
+                       int i;
+                       MonoMethod *declaring_method;
+                       gboolean supported = TRUE;
+
+                       /* Check that the context doesn't contain open constructed types */
+                       if (context->class_inst) {
+                               inst = context->class_inst;
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               continue;
+                                       if (mono_class_is_open_constructed_type (inst->type_argv [i]))
+                                               supported = FALSE;
+                               }
+                       }
+                       if (context->method_inst) {
+                               inst = context->method_inst;
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               continue;
+                                       if (mono_class_is_open_constructed_type (inst->type_argv [i]))
+                                               supported = FALSE;
+                               }
+                       }
+
+                       if (!supported)
+                               continue;
+
+                       memset (&shared_context, 0, sizeof (MonoGenericContext));
+
+                       inst = context->class_inst;
+                       if (inst) {
+                               type_argv = g_new0 (MonoType*, inst->type_argc);
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               type_argv [i] = &mono_defaults.object_class->byval_arg;
+                                       else
+                                               type_argv [i] = inst->type_argv [i];
+                               }
+                               
+                               shared_context.class_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
+                               g_free (type_argv);
+                       }
+
+                       inst = context->method_inst;
+                       if (inst) {
+                               type_argv = g_new0 (MonoType*, inst->type_argc);
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               type_argv [i] = &mono_defaults.object_class->byval_arg;
+                                       else
+                                               type_argv [i] = inst->type_argv [i];
+                               }
+
+                               shared_context.method_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
+                               g_free (type_argv);
+                       }
+
+                       if (method->is_generic || method->klass->generic_container)
+                               declaring_method = method;
+                       else
+                               declaring_method = mono_method_get_declaring_generic_method (method);
+
+                       method = mono_class_inflate_generic_method (declaring_method, &shared_context);
+               }
+
+               /* 
+                * If the method is fully sharable, it was already added in place of its
+                * generic definition.
+                */
+               if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE))
                        continue;
 
+               /*
+                * FIXME: Partially shared methods are not shared here, so we end up with
+                * many identical methods.
+                */
                add_extra_method (acfg, method);
        }
 
@@ -3214,29 +3268,49 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
        }
 
        /* Exception table */
-       if (jinfo->num_clauses)
-               encode_value (jinfo->num_clauses, p, &p);
+       if (cfg->compile_llvm) {
+               /* The assembly might be CIL stripped so emit the data ourselves */
+               if (header->num_clauses)
+                       encode_value (header->num_clauses, p, &p);
 
-       for (k = 0; k < jinfo->num_clauses; ++k) {
-               MonoJitExceptionInfo *ei = &jinfo->clauses [k];
+               for (k = 0; k < header->num_clauses; ++k) {
+                       MonoExceptionClause *clause;
 
-               encode_value (ei->flags, p, &p);
-               encode_value (ei->exvar_offset, p, &p);
+                       clause = &header->clauses [k];
 
-               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
-                       encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
-               else {
-                       if (ei->data.catch_class) {
+                       encode_value (clause->flags, p, &p);
+                       if (clause->data.catch_class) {
                                encode_value (1, p, &p);
-                               encode_klass_ref (acfg, ei->data.catch_class, p, &p);
+                               encode_klass_ref (acfg, clause->data.catch_class, p, &p);
                        } else {
                                encode_value (0, p, &p);
                        }
                }
+       } else {
+               if (jinfo->num_clauses)
+                       encode_value (jinfo->num_clauses, p, &p);
+
+               for (k = 0; k < jinfo->num_clauses; ++k) {
+                       MonoJitExceptionInfo *ei = &jinfo->clauses [k];
+
+                       encode_value (ei->flags, p, &p);
+                       encode_value (ei->exvar_offset, p, &p);
+
+                       if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
+                               encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
+                       else {
+                               if (ei->data.catch_class) {
+                                       encode_value (1, p, &p);
+                                       encode_klass_ref (acfg, ei->data.catch_class, p, &p);
+                               } else {
+                                       encode_value (0, p, &p);
+                               }
+                       }
 
-               encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
-               encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
-               encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
+                       encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
+                       encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
+                       encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
+               }
        }
 
        if (jinfo->has_generic_jit_info) {
@@ -4225,7 +4299,7 @@ load_profile_files (MonoAotCompile *acfg)
 
        file_index = 0;
        while (TRUE) {
-               tmp = g_strdup_printf ("%s/.mono/aot-profile-data/%s-%s-%d", g_get_home_dir (), acfg->image->assembly_name, acfg->image->guid, file_index);
+               tmp = g_strdup_printf ("%s/.mono/aot-profile-data/%s-%d", g_get_home_dir (), acfg->image->assembly_name, file_index);
 
                if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR)) {
                        g_free (tmp);
@@ -4241,21 +4315,38 @@ load_profile_files (MonoAotCompile *acfg)
                file_index ++;
 
                res = fscanf (infile, "%32s\n", ver);
-               if ((res != 1) || strcmp (ver, "#VER:1") != 0) {
+               if ((res != 1) || strcmp (ver, "#VER:2") != 0) {
                        printf ("Profile file has wrong version or invalid.\n");
                        fclose (infile);
                        continue;
                }
 
                while (TRUE) {
-                       res = fscanf (infile, "%d\n", &token);
-                       if (res < 1)
+                       char name [1024];
+                       MonoMethodDesc *desc;
+                       MonoMethod *method;
+
+                       if (fgets (name, 1023, infile) == NULL)
                                break;
 
-                       method_index = mono_metadata_token_index (token) - 1;
+                       /* Kill the newline */
+                       if (strlen (name) > 0)
+                               name [strlen (name) - 1] = '\0';
+
+                       desc = mono_method_desc_new (name, TRUE);
+
+                       method = mono_method_desc_search_in_image (desc, acfg->image);
+
+                       if (method && mono_method_get_token (method)) {
+                               token = mono_method_get_token (method);
+                               method_index = mono_metadata_token_index (token) - 1;
 
-                       if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index)))
-                               acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
+                               if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index))) {
+                                       acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
+                               }
+                       } else {
+                               //printf ("No method found matching '%s'.\n", name);
+                       }
                }
                fclose (infile);
        }
@@ -4810,6 +4901,8 @@ emit_extra_methods (MonoAotCompile *acfg)
 
                nmethods ++;
 
+               method = cfg->method_to_register;
+
                name = NULL;
                if (method->wrapper_type) {
                        /* 
@@ -6006,7 +6099,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        img_writer_emit_start (acfg->w);
 
        if (acfg->dwarf)
-               mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_arch_get_cie_program ());
+               mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_unwind_get_cie_program ());
 
        emit_code (acfg);