diff options
Diffstat (limited to 'mcs/class/dlr')
8 files changed, 315 insertions, 11 deletions
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/DebugOptions.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DebugOptions.cs new file mode 100644 index 0000000000..a3aac34473 --- /dev/null +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DebugOptions.cs @@ -0,0 +1,76 @@ +/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * + * ***************************************************************************/ + +using System.Security; +using System; + +namespace Microsoft.Scripting { + + /// <summary> + /// This class holds onto internal debugging options used in this assembly. + /// These options can be set via environment variables DLR_{option-name}. + /// Boolean options map "true" to true and other values to false. + /// + /// These options are for internal debugging only, and should not be + /// exposed through any public APIs. + /// </summary> + internal static class DebugOptions { + + private static bool ReadOption(string name) { +#if SILVERLIGHT + return false; +#else + string envVar = ReadString(name); + return envVar != null && envVar.ToLowerInvariant() == "true"; +#endif + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "name")] + private static bool ReadDebugOption(string name) { +#if DEBUG + return ReadOption(name); +#else + return false; +#endif + } + + private static string ReadString(string name) { +#if FEATURE_PROCESS + try { + return Environment.GetEnvironmentVariable("DLR_" + name); + } catch (SecurityException) { + return null; + } +#else + return null; +#endif + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "name")] + private static string ReadDebugString(string name) { +#if DEBUG + return ReadString(name); +#else + return null; +#endif + } + + private readonly static bool _trackPerformance = ReadDebugOption("TrackPerformance"); + + internal static bool TrackPerformance { + get { return _trackPerformance; } + } + } +}
\ No newline at end of file diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/MultiRuntimeAwareAttribute.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/MultiRuntimeAwareAttribute.cs new file mode 100644 index 0000000000..3b0cc25069 --- /dev/null +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/MultiRuntimeAwareAttribute.cs @@ -0,0 +1,34 @@ +/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * + * ***************************************************************************/ + +using System; +using System.Diagnostics; + +namespace Microsoft.Scripting { + /// <summary> + /// marks a field, class, or struct as being safe to have statics which can be accessed + /// from multiple runtimes. + /// + /// Static fields which are not read-only or marked with this attribute will be flagged + /// by a test which looks for state being shared between runtimes. Before applying this + /// attribute you should ensure that it is safe to share the state. This is typically + /// state which is lazy initialized or state which is caching values which are identical + /// in all runtimes and are immutable. + /// </summary> + [Conditional("DEBUG")] + [AttributeUsage(AttributeTargets.Field)] + public sealed class MultiRuntimeAwareAttribute : Attribute { + } +} diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/PerfTrack.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/PerfTrack.cs new file mode 100644 index 0000000000..622e41d092 --- /dev/null +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/PerfTrack.cs @@ -0,0 +1,185 @@ +/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * + * ***************************************************************************/ + +#if FEATURE_CORE_DLR +using System.Linq.Expressions; +#else +using Microsoft.Scripting.Ast; +#endif + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.Scripting.Utils; +using System.Dynamic; +using System.IO; + +namespace Microsoft.Scripting { + /// <summary> + /// This class is useful for quickly collecting performance counts for expensive + /// operations. Usually this means operations involving either reflection or + /// code gen. Long-term we need to see if this can be plugged better into the + /// standard performance counter architecture. + /// </summary> + public static class PerfTrack { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1717:OnlyFlagsEnumsShouldHavePluralNames")] // TODO: fix + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] // TODO: fix + public enum Categories { + /// <summary> + /// temporary categories for quick investigation, use a custom key if you + /// need to track multiple items, and if you want to keep it then create + /// a new Categories entry and rename all your temporary entries. + /// </summary> + Temporary, + ReflectedTypes, + Exceptions, // exceptions thrown + Properties, // properties got or set + Fields, // fields got or set + Methods, // methods called through MethodBase.Invoke()... + Compiler, // Methods compiled via the ReflectOptimizer + DelegateCreate, // we've created a new method for delegates + DictInvoke, // Dictionary accesses + OperatorInvoke, // Invoking an operator against a type + OverAllocate, // a spot where we have an un-ideal algorithm that needs to allocate more than necessary + Rules, // related to rules / actions. + RuleEvaluation, // a rule was evaluated + Binding, // a rule was bound + BindingSlow, + BindingFast, + BindingTarget, // a rule was bound against a target of a specific type + Count + } + + [MultiRuntimeAware] + private static int totalEvents; + private static readonly Dictionary<Categories, Dictionary<string, int>> _events = MakeEventsDictionary(); + private static readonly Dictionary<Categories, int> summaryStats = new Dictionary<Categories, int>(); + + private static Dictionary<Categories, Dictionary<string, int>> MakeEventsDictionary() { + Dictionary<Categories, Dictionary<string, int>> result = new Dictionary<Categories, Dictionary<string, int>>(); + + // We do not use Enum.GetValues here since it is not available in SILVERLIGHT + for (int i = 0; i <= (int)Categories.Count; i++) { + result[(Categories)i] = new Dictionary<string, int>(); + } + + return result; + } + +#if FEATURE_BASIC_CONSOLE + public static void DumpHistogram<TKey>(IDictionary<TKey, int> histogram) { + DumpHistogram(histogram, Console.Out); + } + + public static void DumpStats() { + DumpStats(Console.Out); + } +#endif + + public static void DumpHistogram<TKey>(IDictionary<TKey, int> histogram, TextWriter output) { + var keys = ArrayUtils.MakeArray(histogram.Keys); + var values = ArrayUtils.MakeArray(histogram.Values); + +#if !WIN8 // TODO: + Array.Sort(values, keys); +#endif + for (int i = 0; i < keys.Length; i++) { + output.WriteLine("{0} {1}", keys[i], values[i]); + } + } + + public static void AddHistograms<TKey>(IDictionary<TKey, int> result, IDictionary<TKey, int> addend) { + foreach (var entry in addend) { + int value; + result[entry.Key] = entry.Value + (result.TryGetValue(entry.Key, out value) ? value : 0); + } + } + + public static void IncrementEntry<TKey>(IDictionary<TKey, int> histogram, TKey key) { + int value; + histogram.TryGetValue(key, out value); + histogram[key] = value + 1; + } + + public static void DumpStats(TextWriter output) { + if (totalEvents == 0) return; + + // numbers from AMD Opteron 244 1.8 Ghz, 2.00GB of ram, + // running on IronPython 1.0 Beta 4 against Whidbey RTM. + const double CALL_TIME = 0.0000051442355; + const double THROW_TIME = 0.000025365656; + const double FIELD_TIME = 0.0000018080093; + + output.WriteLine(); + output.WriteLine("---- Performance Details ----"); + output.WriteLine(); + + foreach (KeyValuePair<Categories, Dictionary<string, int>> kvpCategories in _events) { + if (kvpCategories.Value.Count > 0) { + output.WriteLine("Category : " + kvpCategories.Key); + DumpHistogram(kvpCategories.Value, output); + output.WriteLine(); + } + } + + output.WriteLine(); + output.WriteLine("---- Performance Summary ----"); + output.WriteLine(); + double knownTimes = 0; + foreach (KeyValuePair<Categories, int> kvp in summaryStats) { + switch (kvp.Key) { + case Categories.Exceptions: + output.WriteLine("Total Exception ({0}) = {1} (throwtime = ~{2} secs)", kvp.Key, kvp.Value, kvp.Value * THROW_TIME); + knownTimes += kvp.Value * THROW_TIME; + break; + case Categories.Fields: + output.WriteLine("Total field = {0} (time = ~{1} secs)", kvp.Value, kvp.Value * FIELD_TIME); + knownTimes += kvp.Value * FIELD_TIME; + break; + case Categories.Methods: + output.WriteLine("Total calls = {0} (calltime = ~{1} secs)", kvp.Value, kvp.Value * CALL_TIME); + knownTimes += kvp.Value * CALL_TIME; + break; + //case Categories.Properties: + default: + output.WriteLine("Total {1} = {0}", kvp.Value, kvp.Key); + break; + } + } + + output.WriteLine(); + output.WriteLine("Total Known Times: {0}", knownTimes); + } + + [Conditional("DEBUG")] + public static void NoteEvent(Categories category, object key) { + if (!DebugOptions.TrackPerformance) return; + + Dictionary<string, int> categoryEvents = _events[category]; + totalEvents++; + lock (categoryEvents) { + string name = key.ToString(); + Exception ex = key as Exception; + if (ex != null) name = ex.GetType().ToString(); + int v; + if (!categoryEvents.TryGetValue(name, out v)) categoryEvents[name] = 1; + else categoryEvents[name] = v + 1; + + if (!summaryStats.TryGetValue(category, out v)) summaryStats[category] = 1; + else summaryStats[category] = v + 1; + } + } + } +} diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs index 5667f88973..4d1c235673 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs @@ -19,7 +19,9 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Reflection; +#if FEATURE_REFEMIT using System.Reflection.Emit; +#endif using System.Threading; using System.Runtime.CompilerServices; @@ -61,9 +63,9 @@ namespace System.Linq.Expressions { _delegateType = delegateType; _tailCall = tailCall; } - +#if FEATURE_REFEMIT internal abstract LambdaExpression Accept(StackSpiller spiller); - +#endif /// <summary> /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.) /// </summary> @@ -217,11 +219,11 @@ namespace System.Linq.Expressions { protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitLambda(this); } - +#if FEATURE_REFEMIT internal override LambdaExpression Accept(StackSpiller spiller) { return spiller.Rewrite(this); } - +#endif internal static LambdaExpression Create(Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters) { return new Expression<TDelegate>(body, name, tailCall, parameters); } diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs index 408ae7d99a..9a60fa4428 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs @@ -20,7 +20,7 @@ using System.Diagnostics; using System.Dynamic.Utils; using System.Reflection; using System.Runtime.CompilerServices; -using Microsoft.Scripting.Utils; +//using Microsoft.Scripting.Utils; #if !FEATURE_CORE_DLR namespace Microsoft.Scripting.Ast { @@ -207,7 +207,7 @@ namespace System.Linq.Expressions { } ConstructorInfo ci = null; if (!type.IsValueType) { - ci = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, ReflectionUtils.EmptyTypes, null); + ci = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Microsoft.Scripting.Utils.ReflectionUtils.EmptyTypes, null); if (ci == null) { throw Error.TypeMissingDefaultConstructor(type); } diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs index 95dea78f1f..329928fd80 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs @@ -24,7 +24,9 @@ using System.Linq.Expressions.Compiler; using System; using System.Collections.Generic; using System.Text; +#if FEATURE_REFEMIT using System.Reflection.Emit; +#endif using System.Diagnostics; using System.Diagnostics.SymbolStore; using System.Reflection; @@ -55,6 +57,7 @@ namespace System.Runtime.CompilerServices { /// <param name="sequencePoint">Debug informaton corresponding to the sequence point.</param> public abstract void MarkSequencePoint(LambdaExpression method, int ilOffset, DebugInfoExpression sequencePoint); +#if FEATURE_REFEMIT internal virtual void MarkSequencePoint(LambdaExpression method, MethodBase methodBase, ILGenerator ilg, DebugInfoExpression sequencePoint) { MarkSequencePoint(method, ilg.ILOffset, sequencePoint); } @@ -62,5 +65,6 @@ namespace System.Runtime.CompilerServices { internal virtual void SetLocalName(LocalBuilder localBuilder, string name) { // nop } +#endif } } diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs index d16f40e435..a2e5ca0a4c 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs @@ -16,7 +16,9 @@ using System; using System.Dynamic.Utils; using System.Reflection; +#if FEATURE_REFEMIT using System.Reflection.Emit; +#endif #if !FEATURE_CORE_DLR namespace Microsoft.Scripting.Ast.Compiler { diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs index 78d5226492..5b219237f6 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs @@ -15,7 +15,9 @@ using System.Diagnostics; using System.Reflection; +#if FEATURE_REFEMIT using System.Reflection.Emit; +#endif using System.Text; namespace System.Dynamic.Utils { @@ -28,13 +30,12 @@ namespace System.Dynamic.Utils { /// </summary> internal static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) { Debug.Assert(methodInfo != null && delegateType != null); - +#if FEATURE_REFEMIT var dm = methodInfo as DynamicMethod; - if (dm != null) { + if (dm != null) return dm.CreateDelegate(delegateType, target); - } else { - return Delegate.CreateDelegate(delegateType, target, methodInfo); - } +#endif + return Delegate.CreateDelegate(delegateType, target, methodInfo); } internal static Type GetReturnType(this MethodBase mi) { |