From 79e05e9d6f8eca93467f104aed4fc19733e909a7 Mon Sep 17 00:00:00 2001 From: Chris Toshok Date: Tue, 16 Feb 2010 23:06:33 +0000 Subject: merge -r151658:151801 from mono-2-6 branch svn path=/branches/moon-2-99-0-3/mono/; revision=151880 --- mono/metadata/ChangeLog | 5 ++ mono/metadata/debug-helpers.c | 35 +++++++++++++ mono/mini/ChangeLog | 23 +++++++++ mono/mini/aot-compiler.c | 31 ++++++++--- mono/mini/aot-runtime.c | 105 ++++++++++++++++++++++++++++++++++++-- mono/mini/debugger-agent.c | 32 ++++++++++-- mono/mini/driver.c | 2 +- mono/mini/mini-arm.c | 26 ++++++++++ mono/mini/mini.c | 20 +++++++- mono/mini/mini.h | 3 ++ mono/profiler/ChangeLog | 6 +++ mono/profiler/mono-profiler-aot.c | 9 ++-- 12 files changed, 274 insertions(+), 23 deletions(-) diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 0dbd09498ba..16b1574c7d4 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,8 @@ +2010-02-13 Zoltan Varga + + * debug-helpers.c (mono_method_desc_search_in_image): Handle short names like + 'int' for system classes. + 2010-01-16 Zoltan Varga * generic-sharing.c (instantiate_other_info): Don't create ftnptr's from the diff --git a/mono/metadata/debug-helpers.c b/mono/metadata/debug-helpers.c index 58765ebf2f7..e1adb9d9dc7 100644 --- a/mono/metadata/debug-helpers.c +++ b/mono/metadata/debug-helpers.c @@ -86,6 +86,31 @@ append_class_name (GString *res, MonoClass *class, gboolean include_namespace) g_string_append_printf (res, "%s", class->name); } +static MonoClass* +find_system_class (const char *name) +{ + if (!strcmp (name, "void")) + return mono_defaults.void_class; + else if (!strcmp (name, "char")) return mono_defaults.char_class; + else if (!strcmp (name, "bool")) return mono_defaults.boolean_class; + else if (!strcmp (name, "byte")) return mono_defaults.byte_class; + else if (!strcmp (name, "sbyte")) return mono_defaults.sbyte_class; + else if (!strcmp (name, "uint16")) return mono_defaults.uint16_class; + else if (!strcmp (name, "int16")) return mono_defaults.int16_class; + else if (!strcmp (name, "uint")) return mono_defaults.uint32_class; + else if (!strcmp (name, "int")) return mono_defaults.int32_class; + else if (!strcmp (name, "ulong")) return mono_defaults.uint64_class; + else if (!strcmp (name, "long")) return mono_defaults.int64_class; + else if (!strcmp (name, "uintptr")) return mono_defaults.uint_class; + else if (!strcmp (name, "intptr")) return mono_defaults.int_class; + else if (!strcmp (name, "single")) return mono_defaults.single_class; + else if (!strcmp (name, "double")) return mono_defaults.double_class; + else if (!strcmp (name, "string")) return mono_defaults.string_class; + else if (!strcmp (name, "object")) return mono_defaults.object_class; + else + return NULL; +} + void mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) { @@ -281,6 +306,9 @@ mono_method_desc_new (const char *name, gboolean include_namespace) class_nspace = g_strdup (name); use_args = strchr (class_nspace, '('); if (use_args) { + /* Allow a ' ' between the method name and the signature */ + if (use_args > class_nspace && use_args [-1] == ' ') + use_args [-1] = 0; *use_args++ = 0; end = strchr (use_args, ')'); if (!end) { @@ -463,6 +491,13 @@ mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image) MonoMethod *method; int i; + /* Handle short names for system classes */ + if (!desc->namespace && image == mono_defaults.corlib) { + klass = find_system_class (desc->klass); + if (klass) + return mono_method_desc_search_in_class (desc, klass); + } + if (desc->namespace && desc->klass) { klass = mono_class_from_name (image, desc->namespace, desc->klass); if (!klass) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 997c4c7ec19..12fdc80b6b1 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,26 @@ +2010-02-13 Zoltan Varga + + * aot-compiler.c (load_profile_files): Update after the profiler changes. + +2010-02-13 Zoltan Varga + + * mini.c (mono_jit_compile_method_inner): Avoid passing icall wrappers to + mono_profiler_method_end_jit, since the profiler has no way to process wrappers. + + * aot-runtime.c mini.c: Resurrect the aot pagefault profiling stuff, it is useful + for mtouch. + +2010-02-13 Gonzalo Paniagua Javier + + * debugger-agent.c: handle incomplete reads and EINTR in + recv()/send(). This could have been causing random + disconnections. + +2010-02-13 Zoltan Varga + + * mini-arm.c (mono_arch_allocate_vars): Allocate the seq point related vars first + so they have small offsets. Fixes #566311. + 2010-02-12 Rodrigo Kumpera * method-to-ir.c (mono_method_check_inlining): Check for loader errors. diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 4f7a0d47e49..20f488f94bc 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -3937,7 +3937,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); @@ -3953,21 +3953,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); } diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 9a7a5a6ff32..eae228bbc59 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -156,6 +156,7 @@ static gint32 mono_last_aot_method = -1; static gboolean make_unreadable = FALSE; static guint32 name_table_accesses = 0; +static guint32 n_pagefaults = 0; /* Used to speed-up find_aot_module () */ static gsize aot_code_low_addr = (gssize)-1; @@ -1097,17 +1098,19 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) if (make_unreadable) { #ifndef PLATFORM_WIN32 guint8 *addr; - guint8 *page_start; - int pages, err, len; + guint8 *page_start, *page_end; + int err, len; addr = amodule->mem_begin; len = amodule->mem_end - amodule->mem_begin; /* Round down in both directions to avoid modifying data which is not ours */ page_start = (guint8 *) (((gssize) (addr)) & ~ (mono_pagesize () - 1)) + mono_pagesize (); - pages = ((addr + len - page_start + mono_pagesize () - 1) / mono_pagesize ()) - 1; - err = mono_mprotect (page_start, pages * mono_pagesize (), MONO_MMAP_NONE); - g_assert (err == 0); + page_end = (guint8 *) (((gssize) (addr + len)) & ~ (mono_pagesize () - 1)); + if (page_end > page_start) { + err = mono_mprotect (page_start, (page_end - page_start), MONO_MMAP_NONE); + g_assert (err == 0); + } #endif } @@ -3053,6 +3056,98 @@ mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem return code; } + +/* + * mono_aot_set_make_unreadable: + * + * Set whenever to make all mmaped memory unreadable. In conjuction with a + * SIGSEGV handler, this is useful to find out which pages the runtime tries to read. + */ +void +mono_aot_set_make_unreadable (gboolean unreadable) +{ + static int inited; + + make_unreadable = unreadable; + + if (make_unreadable && !inited) { + mono_counters_register ("AOT pagefaults", MONO_COUNTER_JIT | MONO_COUNTER_INT, &n_pagefaults); + } +} + +typedef struct { + MonoAotModule *module; + guint8 *ptr; +} FindMapUserData; + +static void +find_map (gpointer key, gpointer value, gpointer user_data) +{ + MonoAotModule *module = (MonoAotModule*)value; + FindMapUserData *data = (FindMapUserData*)user_data; + + if (!data->module) + if ((data->ptr >= module->mem_begin) && (data->ptr < module->mem_end)) + data->module = module; +} + +static MonoAotModule* +find_module_for_addr (void *ptr) +{ + FindMapUserData data; + + if (!make_unreadable) + return NULL; + + data.module = NULL; + data.ptr = (guint8*)ptr; + + mono_aot_lock (); + g_hash_table_foreach (aot_modules, (GHFunc)find_map, &data); + mono_aot_unlock (); + + return data.module; +} + +/* + * mono_aot_is_pagefault: + * + * Should be called from a SIGSEGV signal handler to find out whenever @ptr is + * within memory allocated by this module. + */ +gboolean +mono_aot_is_pagefault (void *ptr) +{ + if (!make_unreadable) + return FALSE; + + /* + * Not signal safe, but SIGSEGV's are synchronous, and + * this is only turned on by a MONO_DEBUG option. + */ + return find_module_for_addr (ptr) != NULL; +} + +/* + * mono_aot_handle_pagefault: + * + * Handle a pagefault caused by an unreadable page by making it readable again. + */ +void +mono_aot_handle_pagefault (void *ptr) +{ +#ifndef PLATFORM_WIN32 + guint8* start = (guint8*)ROUND_DOWN (((gssize)ptr), mono_pagesize ()); + int res; + + mono_aot_lock (); + res = mono_mprotect (start, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC); + g_assert (res == 0); + + n_pagefaults ++; + mono_aot_unlock (); +#endif +} #else /* AOT disabled */ diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 3cdcd535afe..d86929c489a 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -881,6 +881,24 @@ mono_debugger_agent_cleanup (void) mono_cond_destroy (&debugger_thread_exited_cond); } +/* + * recv_length: + * + * recv() + handle incomplete reads and EINTR + */ +static int +recv_length (int fd, void *buf, int len, int flags) +{ + int res; + int total = 0; + + do { + res = recv (fd, (char *) buf + total, len - total, flags); + if (res > 0) + total += res; + } while ((res > 0 && total < len) || (res == -1 && errno == EINTR)); + return total; +} /* * transport_connect: * @@ -1029,11 +1047,13 @@ transport_connect (const char *host, int port) /* Write handshake message */ sprintf (handshake_msg, "DWP-Handshake"); - res = send (conn_fd, handshake_msg, strlen (handshake_msg), 0); + do { + res = send (conn_fd, handshake_msg, strlen (handshake_msg), 0); + } while (res == -1 && errno == EINTR); g_assert (res != -1); /* Read answer */ - res = recv (conn_fd, buf, strlen (handshake_msg), 0); + res = recv_length (conn_fd, buf, strlen (handshake_msg), 0); if ((res != strlen (handshake_msg)) || (memcmp (buf, handshake_msg, strlen (handshake_msg) != 0))) { fprintf (stderr, "debugger-agent: DWP handshake failed.\n"); exit (1); @@ -1059,7 +1079,9 @@ transport_send (guint8 *data, int len) { int res; - res = send (conn_fd, data, len, 0); + do { + res = send (conn_fd, data, len, 0); + } while (res == -1 && errno == EINTR); if (res != len) return FALSE; else @@ -5959,7 +5981,7 @@ debugger_thread (void *arg) mono_set_is_debugger_attached (TRUE); while (TRUE) { - res = recv (conn_fd, header, HEADER_LENGTH, 0); + res = recv_length (conn_fd, header, HEADER_LENGTH, 0); /* This will break if the socket is closed during shutdown too */ if (res != HEADER_LENGTH) @@ -5981,7 +6003,7 @@ debugger_thread (void *arg) data = g_malloc (len - HEADER_LENGTH); if (len - HEADER_LENGTH > 0) { - res = recv (conn_fd, data, len - HEADER_LENGTH, 0); + res = recv_length (conn_fd, data, len - HEADER_LENGTH, 0); if (res != len - HEADER_LENGTH) break; } diff --git a/mono/mini/driver.c b/mono/mini/driver.c index e9068d9278e..c4e7f4ccdb3 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -1333,7 +1333,7 @@ mono_main (int argc, char* argv[]) mini_verbose++; } else if (strcmp (argv [i], "--version") == 0 || strcmp (argv [i], "-V") == 0) { char *build = mono_get_runtime_build_info (); - g_print ("Mono JIT compiler version %s\nCopyright (C) 2002-2008 Novell, Inc and Contributors. www.mono-project.com\n", build); + g_print ("Mono JIT compiler version %s\nCopyright (C) 2002-2010 Novell, Inc and Contributors. www.mono-project.com\n", build); g_free (build); g_print (info); if (mini_verbose) { diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 4b79838bb30..d33d47db8cc 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -1113,6 +1113,32 @@ mono_arch_allocate_vars (MonoCompile *cfg) cfg->sig_cookie += sizeof (gpointer); } + /* Allocate these first so they have a small offset, OP_SEQ_POINT depends on this */ + if (cfg->arch.seq_point_info_var) { + MonoInst *ins; + + ins = cfg->arch.seq_point_info_var; + + size = 4; + align = 4; + offset += align - 1; + offset &= ~(align - 1); + ins->opcode = OP_REGOFFSET; + ins->inst_basereg = frame_reg; + ins->inst_offset = offset; + offset += size; + + ins = cfg->arch.ss_trigger_page_var; + size = 4; + align = 4; + offset += align - 1; + offset &= ~(align - 1); + ins->opcode = OP_REGOFFSET; + ins->inst_basereg = frame_reg; + ins->inst_offset = offset; + offset += size; + } + curinst = cfg->locals_start; for (i = curinst; i < cfg->num_varinfo; ++i) { inst = cfg->varinfo [i]; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 8554f600c0b..69564bce4fd 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -4320,8 +4320,13 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in mono_raise_exception (exc); } - if (prof_options & MONO_PROFILE_JIT_COMPILATION) - mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK); + if (prof_options & MONO_PROFILE_JIT_COMPILATION) { + if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) + /* The profiler doesn't know about wrappers, so pass the original icall method */ + mono_profiler_method_end_jit (mono_marshal_method_from_wrapper (method), jinfo, MONO_PROFILE_OK); + else + mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK); + } mono_runtime_class_init (vtable); return code; @@ -4789,6 +4794,13 @@ SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) } #endif +#ifndef PLATFORM_WIN32 + if (mono_aot_is_pagefault (info->si_addr)) { + mono_aot_handle_pagefault (info->si_addr); + return; + } +#endif + /* The thread might no be registered with the runtime */ if (!mono_domain_get () || !jit_tls) { if (mono_chain_signal (SIG_HANDLER_PARAMS)) @@ -5190,6 +5202,10 @@ mini_init (const char *filename, const char *runtime_version) mono_install_get_class_from_name (mono_aot_get_class_from_name); mono_install_jit_info_find_in_aot (mono_aot_find_jit_info); + if (debug_options.collect_pagefault_stats) { + mono_aot_set_make_unreadable (TRUE); + } + if (runtime_version) domain = mono_init_version (filename, runtime_version); else diff --git a/mono/mini/mini.h b/mono/mini/mini.h index b8aa756f8c4..3246002206e 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -1492,6 +1492,9 @@ char* mono_aot_wrapper_name (MonoMethod *method) MONO_INTERNAL; MonoAotTrampInfo* mono_aot_tramp_info_create (const char *name, guint8 *code, guint32 code_len) MONO_INTERNAL; guint mono_aot_str_hash (gconstpointer v1) MONO_INTERNAL; MonoMethod* mono_aot_get_array_helper_from_wrapper (MonoMethod *method) MONO_INTERNAL; +void mono_aot_set_make_unreadable (gboolean unreadable) MONO_INTERNAL; +gboolean mono_aot_is_pagefault (void *ptr) MONO_INTERNAL; +void mono_aot_handle_pagefault (void *ptr) MONO_INTERNAL; /* This is an exported function */ void mono_aot_register_globals (gpointer *globals); diff --git a/mono/profiler/ChangeLog b/mono/profiler/ChangeLog index 25544b0f8a5..8ee5814f5ad 100644 --- a/mono/profiler/ChangeLog +++ b/mono/profiler/ChangeLog @@ -1,3 +1,9 @@ +2010-02-13 Zoltan Varga + + * mono-profiler-aot.c (output_image): Emit method names instead of tokens so + the info can be used for different versions of the same assembly. Don't append + the assembly guid to the file names. + 2010-01-11 Zoltan Varga * mono-profiler-logging.c (_ProfilerFileWriteBuffer): Use MONO_ZERO_LEN_ARRAY. diff --git a/mono/profiler/mono-profiler-aot.c b/mono/profiler/mono-profiler-aot.c index 9b771525326..92285bbca99 100644 --- a/mono/profiler/mono-profiler-aot.c +++ b/mono/profiler/mono-profiler-aot.c @@ -41,11 +41,14 @@ foreach_method (gpointer data, gpointer user_data) { ForeachData *udata = (ForeachData*)user_data; MonoMethod *method = (MonoMethod*)data; + char *name; if (!mono_method_get_token (method) || mono_class_get_image (mono_method_get_class (method)) != udata->image) return; - fprintf (udata->outfile, "%d\n", mono_method_get_token (method)); + name = mono_method_full_name (method, TRUE); + fprintf (udata->outfile, "%s\n", name); + g_free (name); } static void @@ -75,7 +78,7 @@ output_image (gpointer key, gpointer value, gpointer user_data) i = 0; while (TRUE) { - outfile_name = g_strdup_printf ("%s/%s-%s-%d", tmp, mono_image_get_name (image), mono_image_get_guid (image), i); + outfile_name = g_strdup_printf ("%s/%s-%d", tmp, mono_image_get_name (image), i); if (!g_file_test (outfile_name, G_FILE_TEST_IS_REGULAR)) break; @@ -88,7 +91,7 @@ output_image (gpointer key, gpointer value, gpointer user_data) outfile = fopen (outfile_name, "w+"); g_assert (outfile); - fprintf (outfile, "#VER:%d\n", 1); + fprintf (outfile, "#VER:%d\n", 2); data.prof = prof; data.outfile = outfile; -- cgit v1.2.3