PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Microsoft.Scripting/Actions/DynamicSiteHelper.cs

https://bitbucket.org/stefanrusek/xronos
C# | 244 lines | 161 code | 44 blank | 39 comment | 25 complexity | 6ecfc9c313942d22a33b158032fc0670 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if CODEPLEX_40
  16. using System;
  17. #else
  18. using System; using Microsoft;
  19. #endif
  20. using System.Collections.Generic;
  21. using System.Diagnostics;
  22. using System.Runtime.CompilerServices;
  23. #if !CODEPLEX_40
  24. using Microsoft.Runtime.CompilerServices;
  25. #endif
  26. using System.Threading;
  27. using Microsoft.Scripting.Utils;
  28. using System.Reflection.Emit;
  29. using Microsoft.Scripting.Generation;
  30. using System.Reflection;
  31. namespace Microsoft.Scripting.Actions {
  32. // TODO: replace this class with calls to Expression.GetDelegateType
  33. public static class DynamicSiteHelpers {
  34. private delegate object CreateSite(CallSiteBinder binder);
  35. private const int MaximumArity = 17;
  36. private static Dictionary<ICollection<Type>, Type> _DelegateTypes;
  37. private const MethodAttributes CtorAttributes = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public;
  38. private const MethodImplAttributes ImplAttributes = MethodImplAttributes.Runtime | MethodImplAttributes.Managed;
  39. private const MethodAttributes InvokeAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual;
  40. private static readonly Type[] _DelegateCtorSignature = new Type[] { typeof(object), typeof(IntPtr) };
  41. // TODO: remove in favor of Expression.GetDelegateType
  42. internal static Type MakeCallSiteDelegate(params Type[] types) {
  43. Debug.Assert(types != null);
  44. return MakeDelegate(types.AddFirst(typeof(CallSite)));
  45. }
  46. private static Type MakeDelegate(Type[] types) {
  47. return GetStandardDelegateType(types) ?? MakeCustomDelegate(types);
  48. }
  49. public static Type GetStandardDelegateType(Type[] types) {
  50. ContractUtils.RequiresNotEmpty(types, "types");
  51. // Can only used predefined delegates if we have no byref types and
  52. // the arity is small enough to fit in Func<...> or Action<...>
  53. if (types.Length > MaximumArity || Any(types, t => t.IsByRef)) {
  54. return null;
  55. }
  56. Type result;
  57. if (types[types.Length - 1] == typeof(void)) {
  58. result = GetActionType(RemoveLast(types));
  59. } else {
  60. result = GetFuncType(types);
  61. }
  62. Debug.Assert(result != null);
  63. return result;
  64. }
  65. private static Type GetFuncType(Type[] types) {
  66. switch (types.Length) {
  67. #region Generated Delegate Microsoft Scripting Scripting Func Types
  68. // *** BEGIN GENERATED CODE ***
  69. // generated by function: gen_delegate_func from: generate_dynsites.py
  70. case 1: return typeof(Func<>).MakeGenericType(types);
  71. case 2: return typeof(Func<,>).MakeGenericType(types);
  72. case 3: return typeof(Func<,,>).MakeGenericType(types);
  73. case 4: return typeof(Func<,,,>).MakeGenericType(types);
  74. case 5: return typeof(Func<,,,,>).MakeGenericType(types);
  75. case 6: return typeof(Func<,,,,,>).MakeGenericType(types);
  76. case 7: return typeof(Func<,,,,,,>).MakeGenericType(types);
  77. case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types);
  78. case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types);
  79. case 10: return typeof(Func<,,,,,,,,,>).MakeGenericType(types);
  80. case 11: return typeof(Func<,,,,,,,,,,>).MakeGenericType(types);
  81. case 12: return typeof(Func<,,,,,,,,,,,>).MakeGenericType(types);
  82. case 13: return typeof(Func<,,,,,,,,,,,,>).MakeGenericType(types);
  83. case 14: return typeof(Func<,,,,,,,,,,,,,>).MakeGenericType(types);
  84. case 15: return typeof(Func<,,,,,,,,,,,,,,>).MakeGenericType(types);
  85. case 16: return typeof(Func<,,,,,,,,,,,,,,,>).MakeGenericType(types);
  86. case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types);
  87. // *** END GENERATED CODE ***
  88. #endregion
  89. default: return null;
  90. }
  91. }
  92. private static Type GetActionType(Type[] types) {
  93. switch (types.Length) {
  94. case 0: return typeof(Action);
  95. #region Generated Delegate Microsoft Scripting Action Types
  96. // *** BEGIN GENERATED CODE ***
  97. // generated by function: gen_delegate_action from: generate_dynsites.py
  98. case 1: return typeof(Action<>).MakeGenericType(types);
  99. case 2: return typeof(Action<,>).MakeGenericType(types);
  100. case 3: return typeof(Action<,,>).MakeGenericType(types);
  101. case 4: return typeof(Action<,,,>).MakeGenericType(types);
  102. case 5: return typeof(Action<,,,,>).MakeGenericType(types);
  103. case 6: return typeof(Action<,,,,,>).MakeGenericType(types);
  104. case 7: return typeof(Action<,,,,,,>).MakeGenericType(types);
  105. case 8: return typeof(Action<,,,,,,,>).MakeGenericType(types);
  106. case 9: return typeof(Action<,,,,,,,,>).MakeGenericType(types);
  107. case 10: return typeof(Action<,,,,,,,,,>).MakeGenericType(types);
  108. case 11: return typeof(Action<,,,,,,,,,,>).MakeGenericType(types);
  109. case 12: return typeof(Action<,,,,,,,,,,,>).MakeGenericType(types);
  110. case 13: return typeof(Action<,,,,,,,,,,,,>).MakeGenericType(types);
  111. case 14: return typeof(Action<,,,,,,,,,,,,,>).MakeGenericType(types);
  112. case 15: return typeof(Action<,,,,,,,,,,,,,,>).MakeGenericType(types);
  113. case 16: return typeof(Action<,,,,,,,,,,,,,,,>).MakeGenericType(types);
  114. // *** END GENERATED CODE ***
  115. #endregion
  116. default: return null;
  117. }
  118. }
  119. private static T[] AddFirst<T>(this IList<T> list, T item) {
  120. T[] res = new T[list.Count + 1];
  121. res[0] = item;
  122. list.CopyTo(res, 1);
  123. return res;
  124. }
  125. private static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
  126. foreach (T element in source) {
  127. if (predicate(element)) {
  128. return true;
  129. }
  130. }
  131. return false;
  132. }
  133. private static T[] RemoveLast<T>(this T[] array) {
  134. T[] result = new T[array.Length - 1];
  135. Array.Copy(array, 0, result, 0, result.Length);
  136. return result;
  137. }
  138. private static Type MakeCustomDelegate(Type[] types) {
  139. if (_DelegateTypes == null) {
  140. Interlocked.CompareExchange(
  141. ref _DelegateTypes,
  142. new Dictionary<ICollection<Type>, Type>(ListEqualityComparer<Type>.Instance),
  143. null
  144. );
  145. }
  146. bool found;
  147. Type type;
  148. //
  149. // LOCK to retrieve the delegate type, if any
  150. //
  151. lock (_DelegateTypes) {
  152. found = _DelegateTypes.TryGetValue(types, out type);
  153. }
  154. if (!found && type != null) {
  155. return type;
  156. }
  157. //
  158. // Create new delegate type
  159. //
  160. type = MakeNewCustomDelegate(types);
  161. //
  162. // LOCK to insert new delegate into the cache. If we already have one (racing threads), use the one from the cache
  163. //
  164. lock (_DelegateTypes) {
  165. Type conflict;
  166. if (_DelegateTypes.TryGetValue(types, out conflict) && conflict != null) {
  167. type = conflict;
  168. } else {
  169. _DelegateTypes[types] = type;
  170. }
  171. }
  172. return type;
  173. }
  174. private static Type MakeNewCustomDelegate(Type[] types) {
  175. Type returnType = types[types.Length - 1];
  176. Type[] parameters = types.RemoveLast();
  177. TypeBuilder builder = Snippets.Shared.DefineDelegateType("Delegate" + types.Length);
  178. builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _DelegateCtorSignature).SetImplementationFlags(ImplAttributes);
  179. builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
  180. return builder.CreateType();
  181. }
  182. /// <summary>
  183. /// Returns true if the method should not be displayed in the stack frame.
  184. /// </summary>
  185. public static bool IsInvisibleDlrStackFrame(MethodBase mb) {
  186. //This method name is used for the dynamic method created for a delegate type signature.
  187. if (mb.Name == "_Scripting_") {
  188. return true;
  189. }
  190. //Filters out methods in Microsoft.Scripting namespaces.
  191. if (mb.DeclaringType != null &&
  192. mb.DeclaringType.Namespace != null &&
  193. mb.DeclaringType.Namespace.StartsWith("Microsoft.Scripting", StringComparison.Ordinal)) {
  194. return true;
  195. }
  196. //Filters out all the methods generated for DLR rules or used in DLR rules.
  197. return CallSiteHelpers.IsInternalFrame(mb);
  198. }
  199. }
  200. }