diff --git a/man/mono.1 b/man/mono.1 index c4589ea70c..b6e055473f 100644 --- a/man/mono.1 +++ b/man/mono.1 @@ -844,6 +844,26 @@ The offsets displayed are IL offsets. .PP A more powerful coverage tool is available in the module `monocov'. See the monocov(1) man page for details. +.SH AOT PROFILING +You can improve startup performance by using the AOT profiler. +.PP +Typically the AOT compiler (\fBmono --aot\fR) will not generate code +for generic instantiations. To solve this, you can run Mono with the +AOT profiler to find out all the generic instantiations that are used, +and then instructing the AOT compiler to produce code for these. +.PP +This command will run the specified app.exe and produce the +\fBout.aotprof\fR file with the data describing the generic +instantiations that are needed: +.nf + $ mono --profile=aot:output=out.aotprof app.exe +.fi +.PP +Once you have this data, you can pass this to Mono's AOT compiler to +instruct it to generate code for it: +.nf + $ mono --aot=profile=out.aotprof +.fi .SH DEBUGGING AIDS To debug managed applications, you can use the .B mdb diff --git a/mcs/class/System.Transactions/System.Transactions/Delegates.cs b/mcs/class/System.Transactions/System.Transactions/Delegates.cs index e4994474ee..ad2c95b6bd 100644 --- a/mcs/class/System.Transactions/System.Transactions/Delegates.cs +++ b/mcs/class/System.Transactions/System.Transactions/Delegates.cs @@ -11,9 +11,9 @@ namespace System.Transactions { public delegate Transaction HostCurrentTransactionCallback (); - public delegate void TransactionCompletedEventHandler (object o, + public delegate void TransactionCompletedEventHandler (object sender, TransactionEventArgs e); - public delegate void TransactionStartedEventHandler (object o, + public delegate void TransactionStartedEventHandler (object sender, TransactionEventArgs e); } diff --git a/mcs/class/System.Transactions/System.Transactions/Transaction.cs b/mcs/class/System.Transactions/System.Transactions/Transaction.cs index 4b787e15a8..20c31072d9 100644 --- a/mcs/class/System.Transactions/System.Transactions/Transaction.cs +++ b/mcs/class/System.Transactions/System.Transactions/Transaction.cs @@ -189,6 +189,26 @@ namespace System.Transactions return true; } + public void SetDistributedTransactionIdentifier (IPromotableSinglePhaseNotification promotableNotification, Guid distributedTransactionIdentifier) + { + throw new NotImplementedException (); + } + + public bool EnlistPromotableSinglePhase (IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType) + { + throw new NotImplementedException (); + } + + public byte[] GetPromotedToken () + { + throw new NotImplementedException (); + } + + public Guid PromoterType + { + get { throw new NotImplementedException (); } + } + [MonoTODO ("EnlistmentOptions being ignored")] public Enlistment EnlistVolatile ( IEnlistmentNotification notification, @@ -218,6 +238,17 @@ namespace System.Transactions return new Enlistment (); } + [MonoTODO ("Only Local Transaction Manager supported. Cannot have more than 1 durable resource per transaction.")] + [PermissionSetAttribute (SecurityAction.LinkDemand)] + public Enlistment PromoteAndEnlistDurable ( + Guid manager, + IPromotableSinglePhaseNotification promotableNotification, + ISinglePhaseNotification notification, + EnlistmentOptions options) + { + throw new NotImplementedException ("DTC unsupported, multiple durable resource managers aren't supported."); + } + public override bool Equals (object obj) { return Equals (obj as Transaction); diff --git a/mcs/class/System.Transactions/System.Transactions/TransactionException.cs b/mcs/class/System.Transactions/System.Transactions/TransactionException.cs index d6e3746c66..00212882a7 100644 --- a/mcs/class/System.Transactions/System.Transactions/TransactionException.cs +++ b/mcs/class/System.Transactions/System.Transactions/TransactionException.cs @@ -14,7 +14,7 @@ namespace System.Transactions [Serializable] public class TransactionException : SystemException { - protected TransactionException () + public TransactionException () { } diff --git a/mcs/class/System.Transactions/System.Transactions/TransactionInDoubtException.cs b/mcs/class/System.Transactions/System.Transactions/TransactionInDoubtException.cs index aacc09eb34..552ea00856 100644 --- a/mcs/class/System.Transactions/System.Transactions/TransactionInDoubtException.cs +++ b/mcs/class/System.Transactions/System.Transactions/TransactionInDoubtException.cs @@ -14,7 +14,7 @@ namespace System.Transactions [Serializable] public class TransactionInDoubtException : TransactionException { - protected TransactionInDoubtException () + public TransactionInDoubtException () { } diff --git a/mcs/class/System.Transactions/System.Transactions/TransactionInterop.cs b/mcs/class/System.Transactions/System.Transactions/TransactionInterop.cs index ddfe11f1d8..a764cf6e09 100644 --- a/mcs/class/System.Transactions/System.Transactions/TransactionInterop.cs +++ b/mcs/class/System.Transactions/System.Transactions/TransactionInterop.cs @@ -15,6 +15,8 @@ namespace System.Transactions [MonoTODO] public static class TransactionInterop { + public static readonly Guid PromoterTypeDtc = new Guid ("14229753-FFE1-428D-82B7-DF73045CB8DA"); + [MonoTODO] public static IDtcTransaction GetDtcTransaction (Transaction transaction) { diff --git a/mcs/class/System.Transactions/System.Transactions/TransactionManagerCommunicationException.cs b/mcs/class/System.Transactions/System.Transactions/TransactionManagerCommunicationException.cs index b0e07110bb..2cec4a84a9 100644 --- a/mcs/class/System.Transactions/System.Transactions/TransactionManagerCommunicationException.cs +++ b/mcs/class/System.Transactions/System.Transactions/TransactionManagerCommunicationException.cs @@ -14,7 +14,7 @@ namespace System.Transactions [Serializable] public class TransactionManagerCommunicationException : TransactionException { - protected TransactionManagerCommunicationException () + public TransactionManagerCommunicationException () { } diff --git a/mcs/class/System.Transactions/System.Transactions/TransactionPromotionException.cs b/mcs/class/System.Transactions/System.Transactions/TransactionPromotionException.cs index 5aba17b38a..bcd5f3f193 100644 --- a/mcs/class/System.Transactions/System.Transactions/TransactionPromotionException.cs +++ b/mcs/class/System.Transactions/System.Transactions/TransactionPromotionException.cs @@ -14,7 +14,7 @@ namespace System.Transactions [Serializable] public class TransactionPromotionException : TransactionException { - protected TransactionPromotionException () + public TransactionPromotionException () { } diff --git a/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs b/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs index 167d47e8d3..ac57713b59 100644 --- a/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs +++ b/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs @@ -102,6 +102,26 @@ namespace System.Transactions TransactionManager.DefaultTimeout, TransactionScopeAsyncFlowOption.Suppress); } + public TransactionScope (Transaction transactionToUse, + TransactionScopeAsyncFlowOption asyncFlowOption) + { + throw new NotImplementedException (); + } + + public TransactionScope (Transaction transactionToUse, + TimeSpan scopeTimeout, + TransactionScopeAsyncFlowOption asyncFlowOption) + { + throw new NotImplementedException (); + } + + public TransactionScope (TransactionScopeOption scopeOption, + TransactionOptions transactionOptions, + TransactionScopeAsyncFlowOption asyncFlowOption) + { + throw new NotImplementedException (); + } + void Initialize (TransactionScopeOption scopeOption, Transaction tx, TransactionOptions options, DTCOption interop, TimeSpan timeout, TransactionScopeAsyncFlowOption asyncFlow) diff --git a/mcs/class/corlib/Makefile b/mcs/class/corlib/Makefile index a0f17b0f19..682dc5249d 100644 --- a/mcs/class/corlib/Makefile +++ b/mcs/class/corlib/Makefile @@ -20,6 +20,10 @@ $(error Unknown framework version) endif endif +ifeq ($(PROFILE),build) +CSC_RUNTIME_FLAGS=--profile=aot:output=$(topdir)/class/lib/build/csc.aotprofile +endif + RESOURCE_STRINGS = ../referencesource/mscorlib/mscorlib.txt LIBRARY_COMPILE = $(BOOT_COMPILE) diff --git a/mono/btls/btls-ssl-ctx.c b/mono/btls/btls-ssl-ctx.c index 1f9d43c536..fa56fbd73e 100644 --- a/mono/btls/btls-ssl-ctx.c +++ b/mono/btls/btls-ssl-ctx.c @@ -64,6 +64,15 @@ mono_btls_ssl_ctx_new (void) memset (ctx, 0, sizeof (MonoBtlsSslCtx)); ctx->references = 1; ctx->ctx = SSL_CTX_new (TLS_method ()); + + // enable the default ciphers but disable any RC4 based ciphers + // since they're insecure: RFC 7465 "Prohibiting RC4 Cipher Suites" + SSL_CTX_set_cipher_list (ctx->ctx, "DEFAULT:!RC4"); + + // disable SSLv2 and SSLv3 by default, they are deprecated + // and should generally not be used according to the openssl docs + SSL_CTX_set_options (ctx->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + return ctx; } diff --git a/mono/btls/btls-ssl.c b/mono/btls/btls-ssl.c index dda74ec4b5..eca323ce2a 100644 --- a/mono/btls/btls-ssl.c +++ b/mono/btls/btls-ssl.c @@ -36,8 +36,6 @@ mono_btls_ssl_new (MonoBtlsSslCtx *ctx) ptr->ctx = mono_btls_ssl_ctx_up_ref (ctx); ptr->ssl = SSL_new (mono_btls_ssl_ctx_get_ctx (ptr->ctx)); - SSL_set_options (ptr->ssl, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - return ptr; } diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 25e5d0d5b2..ef861aa899 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1003,16 +1003,16 @@ mono_install_get_cached_class_info (MonoGetCachedClassInfo func); void mono_install_get_class_from_name (MonoGetClassFromName func); -MonoGenericContext* +MONO_PROFILER_API MonoGenericContext* mono_class_get_context (MonoClass *klass); -MonoMethodSignature* +MONO_PROFILER_API MonoMethodSignature* mono_method_signature_checked (MonoMethod *m, MonoError *err); MonoGenericContext* mono_method_get_context_general (MonoMethod *method, gboolean uninflated); -MonoGenericContext* +MONO_PROFILER_API MonoGenericContext* mono_method_get_context (MonoMethod *method); /* Used by monodis, thus cannot be MONO_INTERNAL */ @@ -1296,7 +1296,7 @@ MONO_API void mono_class_describe_statics (MonoClass* klass); /* method debugging functions, for use inside gdb */ MONO_API void mono_method_print_code (MonoMethod *method); -char *mono_signature_full_name (MonoMethodSignature *sig); +MONO_PROFILER_API char *mono_signature_full_name (MonoMethodSignature *sig); /*Enum validation related functions*/ MONO_API gboolean @@ -1305,6 +1305,12 @@ mono_type_is_valid_enum_basetype (MonoType * type); MONO_API gboolean mono_class_is_valid_enum (MonoClass *klass); +MONO_PROFILER_API gboolean +mono_type_is_primitive (MonoType *type); + +MONO_PROFILER_API gboolean +mono_class_is_ginst (MonoClass *klass); + MonoType * mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error); diff --git a/mono/metadata/class.c.REMOVED.git-id b/mono/metadata/class.c.REMOVED.git-id index 531135d009..7454613126 100644 --- a/mono/metadata/class.c.REMOVED.git-id +++ b/mono/metadata/class.c.REMOVED.git-id @@ -1 +1 @@ -a1c77761cdbb42ae1e799cfd298fccf01c6bebeb \ No newline at end of file +ba097864604e44a8d83906ee85bdb3bb4091814b \ No newline at end of file diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index 4966badd21..d8a3d8a647 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -700,5 +700,7 @@ mono_context_init_checked (MonoDomain *domain, MonoError *error); gboolean mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error); +GPtrArray* +mono_domain_get_assemblies (MonoDomain *domain, gboolean refonly); #endif /* __MONO_METADATA_DOMAIN_INTERNALS_H__ */ diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index 315858b14d..009c1a0bba 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -2052,3 +2052,24 @@ mono_domain_unlock (MonoDomain *domain) { mono_locks_coop_release (&domain->lock, DomainLock); } + +GPtrArray* +mono_domain_get_assemblies (MonoDomain *domain, gboolean refonly) +{ + GSList *tmp; + GPtrArray *assemblies; + MonoAssembly *ass; + + assemblies = g_ptr_array_new (); + mono_domain_assemblies_lock (domain); + for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { + ass = (MonoAssembly *)tmp->data; + if (refonly != ass->ref_only) + continue; + if (ass->corlib_internal) + continue; + g_ptr_array_add (assemblies, ass); + } + mono_domain_assemblies_unlock (domain); + return assemblies; +} diff --git a/mono/metadata/icall.c.REMOVED.git-id b/mono/metadata/icall.c.REMOVED.git-id index 7b835a820b..0a17e722be 100644 --- a/mono/metadata/icall.c.REMOVED.git-id +++ b/mono/metadata/icall.c.REMOVED.git-id @@ -1 +1 @@ -4eb9a6416a9d3d3b7e5830b49dd0629e4c81cc9a \ No newline at end of file +cc83f8242571580e8173442bdbb6d4ca671db338 \ No newline at end of file diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 50eaded2e3..31a5e1bd5f 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -1032,6 +1032,103 @@ install_pe_loader (void) mono_install_image_loader (&pe_loader); } +/* +Ignored assemblies. + +There are some assemblies we need to ignore because they include an implementation that doesn't work under mono. +Mono provides its own implementation of those assemblies so it's safe to do so. + +The ignored_assemblies list is generated using tools/nuget-hash-extractor and feeding the problematic nugets to it. + +Right now the list of nugets are the ones that provide the assemblies in $ignored_assemblies_names. + +This is to be removed once a proper fix is shipped through nuget. + +*/ + +typedef enum { + SYS_RT_INTEROP_RUNTIME_INFO = 0, //System.Runtime.InteropServices.RuntimeInformation + SYS_GLOBALIZATION_EXT = 1, //System.Globalization.Extensions + SYS_IO_COMPRESSION = 2, //System.IO.Compression + SYS_NET_HTTP = 3, //System.Net.Http + SYS_TEXT_ENC_CODEPAGES = 4, //System.Text.Encoding.CodePages +} IgnoredAssemblyNames; + +typedef struct { + int hash; + int assembly_name; + const char guid [40]; +} IgnoredAssembly; + +const char *ignored_assemblies_names[] = { + "System.Runtime.InteropServices.RuntimeInformation.dll", + "System.Globalization.Extensions.dll", + "System.IO.Compression.dll", + "System.Net.Http.dll", + "System.Text.Encoding.CodePages.dll" +}; + +#define IGNORED_ASSEMBLY(HASH, NAME, GUID, VER_STR) { .hash = HASH, .assembly_name = NAME, .guid = GUID } + +static const IgnoredAssembly ignored_assemblies [] = { + IGNORED_ASSEMBLY (0x1136045D, SYS_GLOBALIZATION_EXT, "475DBF02-9F68-44F1-8FB5-C9F69F1BD2B1", "4.0.0 net46"), + IGNORED_ASSEMBLY (0x358C9723, SYS_GLOBALIZATION_EXT, "5FCD54F0-4B97-4259-875D-30E481F02EA2", "4.0.1 net46"), + IGNORED_ASSEMBLY (0x450A096A, SYS_GLOBALIZATION_EXT, "E9FCFF5B-4DE1-4BDC-9CE8-08C640FC78CC", "4.3.0 net46"), + IGNORED_ASSEMBLY (0x7A39EA2D, SYS_IO_COMPRESSION, "C665DC9B-D9E5-4D00-98ED-E4F812F23545", "4.0.0 netcore50"), + IGNORED_ASSEMBLY (0x1CBD59A2, SYS_IO_COMPRESSION, "44FCA06C-A510-4B3E-BDBF-D08D697EF65A", "4.1.0 net46"), + IGNORED_ASSEMBLY (0x5E393C29, SYS_IO_COMPRESSION, "3A58A219-266B-47C3-8BE8-4E4F394147AB", "4.3.0 net46"), + IGNORED_ASSEMBLY (0x726C7CC1, SYS_NET_HTTP, "7C0B577F-A4FD-47F1-ADF5-EE65B5A04BB5", "4.0.0 netcore50"), + IGNORED_ASSEMBLY (0x27726A90, SYS_NET_HTTP, "269B562C-CC15-4736-B1B1-68D4A43CAA98", "4.1.0 net46"), + IGNORED_ASSEMBLY (0x10CADA75, SYS_NET_HTTP, "EA2EC6DC-51DD-479C-BFC2-E713FB9E7E47", "4.1.1 net46"), + IGNORED_ASSEMBLY (0x8437178B, SYS_NET_HTTP, "C0E04D9C-70CF-48A6-A179-FBFD8CE69FD0", "4.3.0 net46"), + IGNORED_ASSEMBLY (0x46A4A1C5, SYS_RT_INTEROP_RUNTIME_INFO, "F13660F8-9D0D-419F-BA4E-315693DD26EA", "4.0.0 net45"), + IGNORED_ASSEMBLY (0xD07383BB, SYS_RT_INTEROP_RUNTIME_INFO, "DD91439F-3167-478E-BD2C-BF9C036A1395", "4.3.0 net45"), + IGNORED_ASSEMBLY (0x911D9EC3, SYS_TEXT_ENC_CODEPAGES, "C142254F-DEB5-46A7-AE43-6F10320D1D1F", "4.0.1 net46"), + IGNORED_ASSEMBLY (0xFA686A38, SYS_TEXT_ENC_CODEPAGES, "FD178CD4-EF4F-44D5-9C3F-812B1E25126B", "4.3.0 net46"), +}; + +/* +Equivalent C# code: + static void Main () { + string str = "..."; + int h = 5381; + for (int i = 0; i < str.Length; ++i) + h = ((h << 5) + h) ^ str[i]; + + Console.WriteLine ("{0:X}", h); + } +*/ +static int +hash_guid (const char *str) +{ + int h = 5381; + while (*str) { + h = ((h << 5) + h) ^ *str; + ++str; + } + + return h; +} + +static gboolean +is_problematic_image (MonoImage *image) +{ + int h = hash_guid (image->guid); + + //TODO make this more cache effiecient. + // Either sort by hash and bseach or use SoA and make the linear search more cache efficient. + for (int i = 0; i < G_N_ELEMENTS (ignored_assemblies); ++i) { + if (ignored_assemblies [i].hash == h && !strcmp (image->guid, ignored_assemblies [i].guid)) { + const char *needle = ignored_assemblies_names [ignored_assemblies [i].assembly_name]; + size_t needle_len = strlen (needle); + size_t asm_len = strlen (image->name); + if (asm_len > needle_len && !g_ascii_strcasecmp (image->name + (asm_len - needle_len), needle)) + return TRUE; + } + } + return FALSE; +} + static MonoImage * do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status, gboolean care_about_cli, gboolean care_about_pecoff) @@ -1087,6 +1184,12 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status, if (!mono_image_load_cli_data (image)) goto invalid_image; + if (!image->ref_only && is_problematic_image (image)) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Denying load of problematic image %s", image->name); + *status = MONO_IMAGE_IMAGE_INVALID; + goto invalid_image; + } + if (image->loader == &pe_loader && !image->metadata_only && !mono_verifier_verify_table_data (image, &errors)) goto invalid_image; diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index e19db07350..cabdd0e76d 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -861,7 +861,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.8.0.459/cd26828\"" > version.h + echo "#define FULL_VERSION \"Stable 4.8.0.472/6f90ed1\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index e19db07350..cabdd0e76d 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -861,7 +861,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.8.0.459/cd26828\"" > version.h + echo "#define FULL_VERSION \"Stable 4.8.0.472/6f90ed1\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.in.REMOVED.git-id b/mono/mini/Makefile.in.REMOVED.git-id index 92887ffa09..67d97d4ce5 100644 --- a/mono/mini/Makefile.in.REMOVED.git-id +++ b/mono/mini/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -2009d30f4c7c81d73738eea5151254163a75de36 \ No newline at end of file +433c6642ba1f57db104a712c141ab90d44e55c49 \ No newline at end of file diff --git a/mono/mini/aot-compiler.c.REMOVED.git-id b/mono/mini/aot-compiler.c.REMOVED.git-id index f6d0deeb9b..3d7cae4fb4 100644 --- a/mono/mini/aot-compiler.c.REMOVED.git-id +++ b/mono/mini/aot-compiler.c.REMOVED.git-id @@ -1 +1 @@ -6dca377cb02fbc8588f0c3c97690bde945b3a67c \ No newline at end of file +c4f44c2ecbc5dc6f0532c59ad55c2f46f1ed7f73 \ No newline at end of file diff --git a/mono/mini/aot-runtime.c.REMOVED.git-id b/mono/mini/aot-runtime.c.REMOVED.git-id index 7bed06f95d..cf22d3bc34 100644 --- a/mono/mini/aot-runtime.c.REMOVED.git-id +++ b/mono/mini/aot-runtime.c.REMOVED.git-id @@ -1 +1 @@ -941d5017d0fde6e040cd78412ee8cf2a08ca9376 \ No newline at end of file +2fd57cf8561234d38c90801e15fa271c5a719a82 \ No newline at end of file diff --git a/mono/mini/lldb.c b/mono/mini/lldb.c index c6cfa5454f..8f16e1757a 100644 --- a/mono/mini/lldb.c +++ b/mono/mini/lldb.c @@ -15,6 +15,7 @@ #include #include #include +#include #if !defined(DISABLE_JIT) && !defined(DISABLE_LLDB) @@ -49,10 +50,15 @@ typedef struct guint32 version; /* Align */ guint32 dummy; - /* Keep these as pointers so accessing them is atomic */ DebugEntry *entry; /* List of all entries */ + /* Keep this as a pointer so accessing it is atomic */ DebugEntry *all_entries; + /* The current entry embedded here to reduce the amount of roundtrips */ + guint32 type; + guint32 dummy2; + guint64 size; + guint64 addr; } JitDescriptor; /* @@ -114,6 +120,8 @@ static GHashTable *codegen_regions; static DebugEntry *last_entry; static mono_mutex_t mutex; static GHashTable *dyn_codegen_regions; +static double register_time; +static int num_entries; #define lldb_lock() mono_os_mutex_lock (&mutex) #define lldb_unlock() mono_os_mutex_unlock (&mutex) @@ -291,7 +299,17 @@ add_entry (EntryType type, Buffer *buf) } __mono_jit_debug_descriptor.entry = entry; + + __mono_jit_debug_descriptor.type = entry->type; + __mono_jit_debug_descriptor.size = entry->size; + __mono_jit_debug_descriptor.addr = entry->addr; + mono_memory_barrier (); + + GTimer *timer = mono_time_track_start (); __mono_jit_debug_register_code (); + mono_time_track_end (®ister_time, timer); + num_entries ++; + //printf ("%lf %d %d\n", register_time, num_entries, entry->type); lldb_unlock (); } @@ -395,6 +413,8 @@ mono_lldb_init (const char *options) { enabled = TRUE; mono_os_mutex_init_recursive (&mutex); + + mono_counters_register ("Time spent in LLDB", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, ®ister_time); } typedef struct @@ -600,6 +620,13 @@ mono_lldb_save_trampoline_info (MonoTrampInfo *info) void mono_lldb_save_specific_trampoline_info (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, gpointer code, guint32 code_len) { + /* + * Avoid emitting these for now, + * they slow down execution too much, and they are + * only needed during single stepping which doesn't + * work anyway. + */ +#if 0 TrampolineEntry *entry; UserData udata; int region_id; @@ -635,6 +662,7 @@ mono_lldb_save_specific_trampoline_info (gpointer arg1, MonoTrampolineType tramp add_entry (ENTRY_TRAMPOLINE, buf); buffer_free (buf); +#endif } /* diff --git a/mono/mini/version.h b/mono/mini/version.h index f5deae06a3..9a1d2c172b 100644 --- a/mono/mini/version.h +++ b/mono/mini/version.h @@ -1 +1 @@ -#define FULL_VERSION "Stable 4.8.0.459/cd26828" +#define FULL_VERSION "Stable 4.8.0.472/6f90ed1" diff --git a/mono/profiler/Makefile.am b/mono/profiler/Makefile.am index 4f6c4acb20..ce599e0aba 100644 --- a/mono/profiler/Makefile.am +++ b/mono/profiler/Makefile.am @@ -111,6 +111,7 @@ testlog: $(PLOG_TESTS) check-local: $(check_targets) EXTRA_DIST=mono-profiler-log.h \ + mono-profiler-aot.h \ $(PLOG_TESTS_SRC) \ ptestrunner.pl \ $(suppression_DATA) diff --git a/mono/profiler/Makefile.in b/mono/profiler/Makefile.in index 8486b35bbb..3688f2e069 100644 --- a/mono/profiler/Makefile.in +++ b/mono/profiler/Makefile.in @@ -582,6 +582,7 @@ with_mono_path = MONO_PATH=$(CLASS) RUNTIME = $(with_mono_path) $(top_builddir)/runtime/mono-wrapper MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -unsafe -nowarn:0162 -nowarn:0168 -nowarn:0219 -debug EXTRA_DIST = mono-profiler-log.h \ + mono-profiler-aot.h \ $(PLOG_TESTS_SRC) \ ptestrunner.pl \ $(suppression_DATA) diff --git a/mono/profiler/mono-profiler-aot.c b/mono/profiler/mono-profiler-aot.c index 4cf48bbd1b..05ed0758ed 100644 --- a/mono/profiler/mono-profiler-aot.c +++ b/mono/profiler/mono-profiler-aot.c @@ -13,11 +13,16 @@ */ #include + +#include "mono-profiler-aot.h" + #include #include #include #include #include +#include +#include #include #include #include @@ -29,90 +34,16 @@ #endif struct _MonoProfiler { + GHashTable *classes; GHashTable *images; + GPtrArray *methods; + FILE *outfile; + int id; + char *outfile_name; }; -typedef struct { - GList *methods; -} PerImageData; - -typedef struct ForeachData { - MonoProfiler *prof; - FILE *outfile; - MonoImage *image; - MonoMethod *method; -} ForeachData; - -static void -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; - - name = mono_method_full_name (method, TRUE); - fprintf (udata->outfile, "%s\n", name); - g_free (name); -} - -static void -output_image (gpointer key, gpointer value, gpointer user_data) -{ - MonoImage *image = (MonoImage*)key; - PerImageData *image_data = (PerImageData*)value; - MonoProfiler *prof = (MonoProfiler*)user_data; - char *tmp, *outfile_name; - FILE *outfile; - int i, err; - ForeachData data; - - tmp = g_strdup_printf ("%s/.mono/aot-profile-data", g_get_home_dir ()); - - if (!g_file_test (tmp, G_FILE_TEST_IS_DIR)) { -#ifdef HOST_WIN32 - err = mkdir (tmp); -#else - err = mkdir (tmp, 0777); -#endif - if (err) { - fprintf (stderr, "mono-profiler-aot: Unable to create output directory '%s': %s\n", tmp, g_strerror (errno)); - exit (1); - } - } - - i = 0; - while (TRUE) { - 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; - - i ++; - } - - printf ("Creating output file: %s\n", outfile_name); - - outfile = fopen (outfile_name, "w+"); - g_assert (outfile); - - fprintf (outfile, "#VER:%d\n", 2); - - data.prof = prof; - data.outfile = outfile; - data.image = image; - - g_list_foreach (image_data->methods, foreach_method, &data); -} - -/* called at the end of the program */ -static void -prof_shutdown (MonoProfiler *prof) -{ - g_hash_table_foreach (prof->images, output_image, prof); -} +static mono_mutex_t mutex; +static gboolean verbose; static void prof_jit_enter (MonoProfiler *prof, MonoMethod *method) @@ -123,15 +54,66 @@ static void prof_jit_leave (MonoProfiler *prof, MonoMethod *method, int result) { MonoImage *image = mono_class_get_image (mono_method_get_class (method)); - PerImageData *data; - data = (PerImageData *)g_hash_table_lookup (prof->images, image); - if (!data) { - data = g_new0 (PerImageData, 1); - g_hash_table_insert (prof->images, image, data); + if (!image->assembly || method->wrapper_type) + return; + + mono_os_mutex_lock (&mutex); + g_ptr_array_add (prof->methods, method); + mono_os_mutex_unlock (&mutex); +} + +static void +prof_shutdown (MonoProfiler *prof); + +static void +usage (int do_exit) +{ + printf ("AOT profiler.\n"); + printf ("Usage: mono --profile=aot[:OPTION1[,OPTION2...]] program.exe\n"); + printf ("Options:\n"); + printf ("\thelp show this usage info\n"); + printf ("\toutput=FILENAME write the data to file FILENAME (required)\n"); + printf ("\tverbose print diagnostic info\n"); + if (do_exit) + exit (1); +} + +static const char* +match_option (const char* p, const char *opt, char **rval) +{ + int len = strlen (opt); + if (strncmp (p, opt, len) == 0) { + if (rval) { + if (p [len] == '=' && p [len + 1]) { + const char *opt = p + len + 1; + const char *end = strchr (opt, ','); + char *val; + int l; + if (end == NULL) { + l = strlen (opt); + } else { + l = end - opt; + } + val = (char *) g_malloc (l + 1); + memcpy (val, opt, l); + val [l] = 0; + *rval = val; + return opt + l; + } + if (p [len] == 0 || p [len] == ',') { + *rval = NULL; + return p + len + (p [len] == ','); + } + usage (1); + } else { + if (p [len] == 0) + return p + len; + if (p [len] == ',') + return p + len + 1; + } } - - data->methods = g_list_append (data->methods, method); + return p; } void @@ -142,15 +124,282 @@ void mono_profiler_startup (const char *desc) { MonoProfiler *prof; + const char *p; + const char *opt; + char *outfile_name; + + p = desc; + if (strncmp (p, "aot", 3)) + usage (1); + p += 3; + if (*p == ':') + p++; + for (; *p; p = opt) { + char *val; + if (*p == ',') { + opt = p + 1; + continue; + } + if ((opt = match_option (p, "help", NULL)) != p) { + usage (0); + continue; + } + if ((opt = match_option (p, "verbose", NULL)) != p) { + verbose = TRUE; + continue; + } + if ((opt = match_option (p, "output", &val)) != p) { + outfile_name = val; + continue; + } + fprintf (stderr, "mono-profiler-aot: Unknown option: '%s'.\n", p); + exit (1); + } + + if (!outfile_name) { + fprintf (stderr, "mono-profiler-aot: The 'output' argument is required.\n"); + exit (1); + } prof = g_new0 (MonoProfiler, 1); prof->images = g_hash_table_new (NULL, NULL); + prof->classes = g_hash_table_new (NULL, NULL); + prof->methods = g_ptr_array_new (); + prof->outfile_name = outfile_name; + + mono_os_mutex_init (&mutex); mono_profiler_install (prof, prof_shutdown); - + mono_profiler_install_jit_compile (prof_jit_enter, prof_jit_leave); mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION); } +static void +emit_byte (MonoProfiler *prof, guint8 value) +{ + fwrite (&value, 1, 1, prof->outfile); +} +static void +emit_int32 (MonoProfiler *prof, int value) +{ + // FIXME: Endianness + fwrite (&value, 4, 1, prof->outfile); +} + +static void +emit_string (MonoProfiler *prof, const char *str) +{ + int len = strlen (str); + + emit_int32 (prof, len); + fwrite (str, len, 1, prof->outfile); +} + +static void +emit_record (MonoProfiler *prof, AotProfRecordType type, int id) +{ + emit_byte (prof, type); + emit_int32 (prof, id); +} + +static int +add_image (MonoProfiler *prof, MonoImage *image) +{ + int id = GPOINTER_TO_INT (g_hash_table_lookup (prof->images, image)); + if (id) + return id - 1; + + id = prof->id ++; + emit_record (prof, AOTPROF_RECORD_IMAGE, id); + emit_string (prof, image->assembly->aname.name); + emit_string (prof, image->guid); + g_hash_table_insert (prof->images, image, GINT_TO_POINTER (id + 1)); + return id; +} + +static int +add_class (MonoProfiler *prof, MonoClass *klass); + +static int +add_type (MonoProfiler *prof, MonoType *type) +{ + switch (type->type) { +#if 0 + case MONO_TYPE_SZARRAY: { + int eid = add_type (prof, &type->data.klass->byval_arg); + if (eid == -1) + return -1; + int id = prof->id ++; + emit_record (prof, AOTPROF_RECORD_TYPE, id); + emit_byte (prof, MONO_TYPE_SZARRAY); + emit_int32 (prof, id); + return id; + } +#endif + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + case MONO_TYPE_CLASS: + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_GENERICINST: + return add_class (prof, mono_class_from_mono_type (type)); + default: + return -1; + } +} + +static int +add_ginst (MonoProfiler *prof, MonoGenericInst *inst) +{ + int i, id; + int *ids; + + // FIXME: Cache + ids = g_malloc0 (inst->type_argc * sizeof (int)); + for (i = 0; i < inst->type_argc; ++i) { + MonoType *t = inst->type_argv [i]; + ids [i] = add_type (prof, t); + if (ids [i] == -1) { + g_free (ids); + return -1; + } + } + id = prof->id ++; + emit_record (prof, AOTPROF_RECORD_GINST, id); + emit_int32 (prof, inst->type_argc); + for (i = 0; i < inst->type_argc; ++i) + emit_int32 (prof, ids [i]); + g_free (ids); + + return id; +} + +static int +add_class (MonoProfiler *prof, MonoClass *klass) +{ + int id, inst_id = -1, image_id; + char *name; + + id = GPOINTER_TO_INT (g_hash_table_lookup (prof->classes, klass)); + if (id) + return id - 1; + + image_id = add_image (prof, klass->image); + + if (mono_class_is_ginst (klass)) { + MonoGenericContext *ctx = mono_class_get_context (klass); + inst_id = add_ginst (prof, ctx->class_inst); + if (inst_id == -1) + return -1; + } + + if (klass->nested_in) + name = g_strdup_printf ("%s.%s/%s", klass->nested_in->name_space, klass->nested_in->name, klass->name); + else + name = g_strdup_printf ("%s.%s", klass->name_space, klass->name); + + id = prof->id ++; + emit_record (prof, AOTPROF_RECORD_TYPE, id); + emit_byte (prof, MONO_TYPE_CLASS); + emit_int32 (prof, image_id); + emit_int32 (prof, inst_id); + emit_string (prof, name); + g_free (name); + g_hash_table_insert (prof->classes, klass, GINT_TO_POINTER (id + 1)); + return id; +} + +static void +add_method (MonoProfiler *prof, MonoMethod *m) +{ + MonoError error; + MonoMethodSignature *sig; + char *s; + + sig = mono_method_signature_checked (m, &error); + g_assert (mono_error_ok (&error)); + + int class_id = add_class (prof, m->klass); + if (class_id == -1) + return; + int inst_id = -1; + + if (m->is_inflated) { + MonoGenericContext *ctx = mono_method_get_context (m); + if (ctx->method_inst) + inst_id = add_ginst (prof, ctx->method_inst); + } + int id = prof->id ++; + emit_record (prof, AOTPROF_RECORD_METHOD, id); + emit_int32 (prof, class_id); + emit_int32 (prof, inst_id); + emit_int32 (prof, sig->param_count); + emit_string (prof, m->name); + s = mono_signature_full_name (sig); + emit_string (prof, s); + g_free (s); + if (verbose) + printf ("%s %d\n", mono_method_full_name (m, 1), id); +} + +/* called at the end of the program */ +static void +prof_shutdown (MonoProfiler *prof) +{ + FILE *outfile; + int mindex; + char magic [32]; + + printf ("Creating output file: %s\n", prof->outfile_name); + + outfile = fopen (prof->outfile_name, "w+"); + if (!outfile) { + fprintf (stderr, "Unable to create output file '%s': %s.\n", prof->outfile_name, strerror (errno)); + return; + } + prof->outfile = outfile; + + gint32 version = (AOT_PROFILER_MAJOR_VERSION << 16) | AOT_PROFILER_MINOR_VERSION; + sprintf (magic, AOT_PROFILER_MAGIC); + fwrite (magic, strlen (magic), 1, outfile); + emit_int32 (prof, version); + + GHashTable *all_methods = g_hash_table_new (NULL, NULL); + for (mindex = 0; mindex < prof->methods->len; ++mindex) { + MonoMethod *m = (MonoMethod*)g_ptr_array_index (prof->methods, mindex); + + if (!mono_method_get_token (m)) + continue; + + if (g_hash_table_lookup (all_methods, m)) + continue; + g_hash_table_insert (all_methods, m, m); + + add_method (prof, m); + } + emit_record (prof, AOTPROF_RECORD_NONE, 0); + + fclose (outfile); + + g_hash_table_destroy (all_methods); + g_hash_table_destroy (prof->classes); + g_hash_table_destroy (prof->images); + g_ptr_array_free (prof->methods, TRUE); + g_free (prof->outfile_name); +} diff --git a/mono/profiler/mono-profiler-aot.h b/mono/profiler/mono-profiler-aot.h new file mode 100644 index 0000000000..7663cab70f --- /dev/null +++ b/mono/profiler/mono-profiler-aot.h @@ -0,0 +1,33 @@ +#ifndef __MONO_PROFILER_AOT_H__ +#define __MONO_PROFILER_AOT_H__ + +#include + +/* + * File format: + * - magic + * - major/minor version as an int, i.e. 0x00010001 + * - sequence of records terminated by a record with type TYPE_NONE + * Record format: + * - 1 byte record type (AotProfRecordType) + * - 1 int record id + * - record specific data + * Encoding rules: + * - int - 4 bytes little endian + * - string - int length followed by data + */ + +typedef enum { + AOTPROF_RECORD_NONE, + AOTPROF_RECORD_IMAGE, + AOTPROF_RECORD_TYPE, + AOTPROF_RECORD_GINST, + AOTPROF_RECORD_METHOD +} AotProfRecordType; + +#define AOT_PROFILER_MAGIC "AOTPROFILE" + +#define AOT_PROFILER_MAJOR_VERSION 1 +#define AOT_PROFILER_MINOR_VERSION 0 + +#endif /* __MONO_PROFILER_AOT_H__ */ diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index 5c942e06fa..4105b7920e 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -275,6 +275,9 @@ typedef SSIZE_T ssize_t; #define MONO_LLVM_INTERNAL #endif +/* Used to mark internal functions used by the profiler modules */ +#define MONO_PROFILER_API MONO_API + #ifdef __GNUC__ #define MONO_ALWAYS_INLINE __attribute__((always_inline)) #elif defined(_MSC_VER) diff --git a/po/mcs/de.gmo b/po/mcs/de.gmo index ca42eac031..946297827c 100644 Binary files a/po/mcs/de.gmo and b/po/mcs/de.gmo differ diff --git a/po/mcs/de.po.REMOVED.git-id b/po/mcs/de.po.REMOVED.git-id index a65bd66b97..29ed4e47e8 100644 --- a/po/mcs/de.po.REMOVED.git-id +++ b/po/mcs/de.po.REMOVED.git-id @@ -1 +1 @@ -0b495da280aeb0edcc452a19ef2728a220e29836 \ No newline at end of file +06d95eb77e22edab191d4d09927b233c5d2de3cb \ No newline at end of file diff --git a/po/mcs/es.gmo b/po/mcs/es.gmo index 00f7e00b04..1c01809711 100644 Binary files a/po/mcs/es.gmo and b/po/mcs/es.gmo differ diff --git a/po/mcs/es.po.REMOVED.git-id b/po/mcs/es.po.REMOVED.git-id index deb4974bfe..ca1acbd13b 100644 --- a/po/mcs/es.po.REMOVED.git-id +++ b/po/mcs/es.po.REMOVED.git-id @@ -1 +1 @@ -c1046188be652d3ba506a743ccd1edd5d769f03a \ No newline at end of file +c414cbd1a565f26f5628939e9a70676d3653d428 \ No newline at end of file diff --git a/po/mcs/ja.gmo b/po/mcs/ja.gmo index 333b78fa72..04bb854ccc 100644 Binary files a/po/mcs/ja.gmo and b/po/mcs/ja.gmo differ diff --git a/po/mcs/ja.po.REMOVED.git-id b/po/mcs/ja.po.REMOVED.git-id index f913e38604..2a0701fea5 100644 --- a/po/mcs/ja.po.REMOVED.git-id +++ b/po/mcs/ja.po.REMOVED.git-id @@ -1 +1 @@ -15cfccc89d5d9835e017c1a4fe825b3685724c8d \ No newline at end of file +5030d72210cdffe84371eb3e9f1e89261daf28da \ No newline at end of file diff --git a/po/mcs/mcs.pot b/po/mcs/mcs.pot index 921b3bdefc..d3c4c1c444 100644 --- a/po/mcs/mcs.pot +++ b/po/mcs/mcs.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mono 4.8.0\n" "Report-Msgid-Bugs-To: http://www.mono-project.com/Bugs\n" -"POT-Creation-Date: 2017-01-19 13:16+0000\n" +"POT-Creation-Date: 2017-01-24 10:53+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/po/mcs/pt_BR.gmo b/po/mcs/pt_BR.gmo index f7439f4151..9feeef807a 100644 Binary files a/po/mcs/pt_BR.gmo and b/po/mcs/pt_BR.gmo differ diff --git a/po/mcs/pt_BR.po.REMOVED.git-id b/po/mcs/pt_BR.po.REMOVED.git-id index 953ae7f380..35cecf0fb3 100644 --- a/po/mcs/pt_BR.po.REMOVED.git-id +++ b/po/mcs/pt_BR.po.REMOVED.git-id @@ -1 +1 @@ -3b041571f966e8ba5599018c48ef0a1ec7219b3e \ No newline at end of file +c9139a77cfe82ac0c042be33e9c22a6461d370c6 \ No newline at end of file