PageRenderTime 40ms CodeModel.GetById 31ms app.highlight 6ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.Generated.cs

https://github.com/ancailliau/mono
C# | 293 lines | 183 code | 49 blank | 61 comment | 29 complexity | 5cf91570665f955691e305e4689b295a MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. 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  Apache License, Version 2.0, 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 Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16using System;
 17using System.Collections.Generic;
 18using System.Collections.ObjectModel;
 19using System.Diagnostics;
 20using System.Dynamic;
 21using System.Dynamic.Utils;
 22using System.Runtime.CompilerServices;
 23
 24#if !FEATURE_CORE_DLR
 25namespace Microsoft.Scripting.Ast.Compiler {
 26    using Microsoft.Scripting.Utils;
 27#else
 28namespace System.Linq.Expressions.Compiler {
 29#endif
 30    internal static partial class DelegateHelpers {
 31        private static TypeInfo _DelegateCache = new TypeInfo();
 32
 33        #region Generated Maximum Delegate Arity
 34
 35        // *** BEGIN GENERATED CODE ***
 36        // generated by function: gen_max_delegate_arity from: generate_dynsites.py
 37
 38        private const int MaximumArity = 17;
 39
 40        // *** END GENERATED CODE ***
 41
 42        #endregion
 43
 44        internal class TypeInfo {
 45            public Type DelegateType;
 46            public Dictionary<Type, TypeInfo> TypeChain;
 47
 48            public Type MakeDelegateType(Type retType, params Expression[] args) {
 49                return MakeDelegateType(retType, (IList<Expression>)args);
 50            }
 51
 52            public Type MakeDelegateType(Type retType, IList<Expression> args) {
 53                // nope, go ahead and create it and spend the
 54                // cost of creating the array.
 55                Type[] paramTypes = new Type[args.Count + 2];
 56                paramTypes[0] = typeof(CallSite);
 57                paramTypes[paramTypes.Length - 1] = retType;
 58                for (int i = 0; i < args.Count; i++) {
 59                    paramTypes[i + 1] = args[i].Type;
 60                }
 61
 62                return DelegateType = MakeNewDelegate(paramTypes);
 63            }
 64        }
 65
 66
 67        /// <summary>
 68        /// Finds a delegate type using the types in the array. 
 69        /// We use the cache to avoid copying the array, and to cache the
 70        /// created delegate type
 71        /// </summary>
 72        internal static Type MakeDelegateType(Type[] types) {
 73            lock (_DelegateCache) {
 74                TypeInfo curTypeInfo = _DelegateCache;
 75
 76                // arguments & return type
 77                for (int i = 0; i < types.Length; i++) {
 78                    curTypeInfo = NextTypeInfo(types[i], curTypeInfo);
 79                }
 80
 81                // see if we have the delegate already
 82                if (curTypeInfo.DelegateType == null) {
 83                    // clone because MakeCustomDelegate can hold onto the array.
 84                    curTypeInfo.DelegateType = MakeNewDelegate((Type[])types.Clone());
 85                }
 86
 87                return curTypeInfo.DelegateType;
 88            }
 89        }
 90
 91        /// <summary>
 92        /// Finds a delegate type for a CallSite using the types in the ReadOnlyCollection of Expression. 
 93        /// 
 94        /// We take the readonly collection of Expression explicitly to avoid allocating memory (an array 
 95        /// of types) on lookup of delegate types.
 96        /// </summary>
 97        internal static Type MakeCallSiteDelegate(ReadOnlyCollection<Expression> types, Type returnType) {
 98            lock (_DelegateCache) {
 99                TypeInfo curTypeInfo = _DelegateCache;
100
101                // CallSite
102                curTypeInfo = NextTypeInfo(typeof(CallSite), curTypeInfo);
103
104                // arguments
105                for (int i = 0; i < types.Count; i++) {
106                    curTypeInfo = NextTypeInfo(types[i].Type, curTypeInfo);
107                }
108
109                // return type
110                curTypeInfo = NextTypeInfo(returnType, curTypeInfo);
111
112                // see if we have the delegate already
113                if (curTypeInfo.DelegateType == null) {
114                    curTypeInfo.MakeDelegateType(returnType, types);
115                }
116
117                return curTypeInfo.DelegateType;
118            }
119        }
120
121        /// <summary>
122        /// Finds a delegate type for a CallSite using the MetaObject array. 
123        /// 
124        /// We take the array of MetaObject explicitly to avoid allocating memory (an array of types) on
125        /// lookup of delegate types.
126        /// </summary>
127        internal static Type MakeDeferredSiteDelegate(DynamicMetaObject[] args, Type returnType) {
128            lock (_DelegateCache) {
129                TypeInfo curTypeInfo = _DelegateCache;
130
131                // CallSite
132                curTypeInfo = NextTypeInfo(typeof(CallSite), curTypeInfo);
133
134                // arguments
135                for (int i = 0; i < args.Length; i++) {
136                    DynamicMetaObject mo = args[i];
137                    Type paramType = mo.Expression.Type;
138                    if (IsByRef(mo)) {
139                        paramType = paramType.MakeByRefType();
140                    }
141                    curTypeInfo = NextTypeInfo(paramType, curTypeInfo);
142                }
143
144                // return type
145                curTypeInfo = NextTypeInfo(returnType, curTypeInfo);
146
147                // see if we have the delegate already
148                if (curTypeInfo.DelegateType == null) {
149                    // nope, go ahead and create it and spend the
150                    // cost of creating the array.
151                    Type[] paramTypes = new Type[args.Length + 2];
152                    paramTypes[0] = typeof(CallSite);
153                    paramTypes[paramTypes.Length - 1] = returnType;
154                    for (int i = 0; i < args.Length; i++) {
155                        DynamicMetaObject mo = args[i];
156                        Type paramType = mo.Expression.Type;
157                        if (IsByRef(mo)) {
158                            paramType = paramType.MakeByRefType();
159                        }
160                        paramTypes[i + 1] = paramType;
161                    }
162
163                    curTypeInfo.DelegateType = MakeNewDelegate(paramTypes);
164                }
165
166                return curTypeInfo.DelegateType;
167            }
168        }
169
170        private static bool IsByRef(DynamicMetaObject mo) {
171            ParameterExpression pe = mo.Expression as ParameterExpression;
172            return pe != null && pe.IsByRef;
173        }
174
175        internal static TypeInfo NextTypeInfo(Type initialArg) {
176            lock (_DelegateCache) {
177                return NextTypeInfo(initialArg, _DelegateCache);
178            }
179        }
180
181        internal static TypeInfo GetNextTypeInfo(Type initialArg, TypeInfo curTypeInfo) {
182            lock (_DelegateCache) {
183                return NextTypeInfo(initialArg, curTypeInfo);
184            }
185        }
186
187        private static TypeInfo NextTypeInfo(Type initialArg, TypeInfo curTypeInfo) {
188            Type lookingUp = initialArg;
189            TypeInfo nextTypeInfo;
190            if (curTypeInfo.TypeChain == null) {
191                curTypeInfo.TypeChain = new Dictionary<Type, TypeInfo>();
192            }
193
194            if (!curTypeInfo.TypeChain.TryGetValue(lookingUp, out nextTypeInfo)) {
195                nextTypeInfo = new TypeInfo();
196                if (TypeUtils.CanCache(lookingUp)) {
197                    curTypeInfo.TypeChain[lookingUp] = nextTypeInfo;
198                }
199            }
200            return nextTypeInfo;
201        }
202
203        /// <summary>
204        /// Creates a new delegate, or uses a func/action
205        /// Note: this method does not cache
206        /// </summary>
207        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
208        private static Type MakeNewDelegate(Type[] types) {
209            Debug.Assert(types != null && types.Length > 0);
210
211            // Can only used predefined delegates if we have no byref types and
212            // the arity is small enough to fit in Func<...> or Action<...>
213            if (types.Length > MaximumArity || types.Any(t => t.IsByRef)) {
214                return MakeNewCustomDelegate(types);
215            }
216
217            Type result;
218            if (types[types.Length - 1] == typeof(void)) {
219                result = GetActionType(types.RemoveLast());
220            } else {
221                result = GetFuncType(types);
222            }
223            Debug.Assert(result != null);
224            return result;
225        }
226
227        internal static Type GetFuncType(Type[] types) {
228            switch (types.Length) {
229                #region Generated Delegate Func Types
230
231                // *** BEGIN GENERATED CODE ***
232                // generated by function: gen_delegate_func from: generate_dynsites.py
233
234                case 1: return typeof(Func<>).MakeGenericType(types);
235                case 2: return typeof(Func<,>).MakeGenericType(types);
236                case 3: return typeof(Func<,,>).MakeGenericType(types);
237                case 4: return typeof(Func<,,,>).MakeGenericType(types);
238                case 5: return typeof(Func<,,,,>).MakeGenericType(types);
239                case 6: return typeof(Func<,,,,,>).MakeGenericType(types);
240                case 7: return typeof(Func<,,,,,,>).MakeGenericType(types);
241                case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types);
242                case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types);
243                case 10: return typeof(Func<,,,,,,,,,>).MakeGenericType(types);
244                case 11: return typeof(Func<,,,,,,,,,,>).MakeGenericType(types);
245                case 12: return typeof(Func<,,,,,,,,,,,>).MakeGenericType(types);
246                case 13: return typeof(Func<,,,,,,,,,,,,>).MakeGenericType(types);
247                case 14: return typeof(Func<,,,,,,,,,,,,,>).MakeGenericType(types);
248                case 15: return typeof(Func<,,,,,,,,,,,,,,>).MakeGenericType(types);
249                case 16: return typeof(Func<,,,,,,,,,,,,,,,>).MakeGenericType(types);
250                case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types);
251
252                // *** END GENERATED CODE ***
253
254                #endregion
255
256                default: return null;
257            }
258        }
259
260        internal static Type GetActionType(Type[] types) {
261            switch (types.Length) {
262                case 0: return typeof(Action);
263                #region Generated Delegate Action Types
264
265                // *** BEGIN GENERATED CODE ***
266                // generated by function: gen_delegate_action from: generate_dynsites.py
267
268                case 1: return typeof(Action<>).MakeGenericType(types);
269                case 2: return typeof(Action<,>).MakeGenericType(types);
270                case 3: return typeof(Action<,,>).MakeGenericType(types);
271                case 4: return typeof(Action<,,,>).MakeGenericType(types);
272                case 5: return typeof(Action<,,,,>).MakeGenericType(types);
273                case 6: return typeof(Action<,,,,,>).MakeGenericType(types);
274                case 7: return typeof(Action<,,,,,,>).MakeGenericType(types);
275                case 8: return typeof(Action<,,,,,,,>).MakeGenericType(types);
276                case 9: return typeof(Action<,,,,,,,,>).MakeGenericType(types);
277                case 10: return typeof(Action<,,,,,,,,,>).MakeGenericType(types);
278                case 11: return typeof(Action<,,,,,,,,,,>).MakeGenericType(types);
279                case 12: return typeof(Action<,,,,,,,,,,,>).MakeGenericType(types);
280                case 13: return typeof(Action<,,,,,,,,,,,,>).MakeGenericType(types);
281                case 14: return typeof(Action<,,,,,,,,,,,,,>).MakeGenericType(types);
282                case 15: return typeof(Action<,,,,,,,,,,,,,,>).MakeGenericType(types);
283                case 16: return typeof(Action<,,,,,,,,,,,,,,,>).MakeGenericType(types);
284
285                // *** END GENERATED CODE ***
286
287                #endregion
288
289                default: return null;
290            }
291        }
292    }
293}