PageRenderTime 57ms CodeModel.GetById 34ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 11ms

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