1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 using System.Diagnostics; 7 using System.Dynamic.Utils; 8 using System.Reflection; 9 using System.Runtime.ExceptionServices; 10 11 namespace System.Linq.Expressions.Interpreter 12 { 13 #if FEATURE_MAKE_RUN_METHODS 14 internal static partial class DelegateHelpers 15 { 16 private const int MaximumArity = 17; 17 18 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] 19 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")] MakeDelegate(Type[] types)20 internal static Type MakeDelegate(Type[] types) 21 { 22 Debug.Assert(types != null && types.Length > 0); 23 24 // Can only used predefined delegates if we have no byref types and 25 // the arity is small enough to fit in Func<...> or Action<...> 26 if (types.Length > MaximumArity || types.Any(t => t.IsByRef)) 27 { 28 throw ContractUtils.Unreachable; 29 } 30 31 Type returnType = types[types.Length - 1]; 32 if (returnType == typeof(void)) 33 { 34 Array.Resize(ref types, types.Length - 1); 35 switch (types.Length) 36 { 37 case 0: return typeof(Action); 38 39 case 1: return typeof(Action<>).MakeGenericType(types); 40 case 2: return typeof(Action<,>).MakeGenericType(types); 41 case 3: return typeof(Action<,,>).MakeGenericType(types); 42 case 4: return typeof(Action<,,,>).MakeGenericType(types); 43 case 5: return typeof(Action<,,,,>).MakeGenericType(types); 44 case 6: return typeof(Action<,,,,,>).MakeGenericType(types); 45 case 7: return typeof(Action<,,,,,,>).MakeGenericType(types); 46 case 8: return typeof(Action<,,,,,,,>).MakeGenericType(types); 47 case 9: return typeof(Action<,,,,,,,,>).MakeGenericType(types); 48 case 10: return typeof(Action<,,,,,,,,,>).MakeGenericType(types); 49 case 11: return typeof(Action<,,,,,,,,,,>).MakeGenericType(types); 50 case 12: return typeof(Action<,,,,,,,,,,,>).MakeGenericType(types); 51 case 13: return typeof(Action<,,,,,,,,,,,,>).MakeGenericType(types); 52 case 14: return typeof(Action<,,,,,,,,,,,,,>).MakeGenericType(types); 53 case 15: return typeof(Action<,,,,,,,,,,,,,,>).MakeGenericType(types); 54 case 16: return typeof(Action<,,,,,,,,,,,,,,,>).MakeGenericType(types); 55 } 56 } 57 else 58 { 59 switch (types.Length) 60 { 61 case 1: return typeof(Func<>).MakeGenericType(types); 62 case 2: return typeof(Func<,>).MakeGenericType(types); 63 case 3: return typeof(Func<,,>).MakeGenericType(types); 64 case 4: return typeof(Func<,,,>).MakeGenericType(types); 65 case 5: return typeof(Func<,,,,>).MakeGenericType(types); 66 case 6: return typeof(Func<,,,,,>).MakeGenericType(types); 67 case 7: return typeof(Func<,,,,,,>).MakeGenericType(types); 68 case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types); 69 case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types); 70 case 10: return typeof(Func<,,,,,,,,,>).MakeGenericType(types); 71 case 11: return typeof(Func<,,,,,,,,,,>).MakeGenericType(types); 72 case 12: return typeof(Func<,,,,,,,,,,,>).MakeGenericType(types); 73 case 13: return typeof(Func<,,,,,,,,,,,,>).MakeGenericType(types); 74 case 14: return typeof(Func<,,,,,,,,,,,,,>).MakeGenericType(types); 75 case 15: return typeof(Func<,,,,,,,,,,,,,,>).MakeGenericType(types); 76 case 16: return typeof(Func<,,,,,,,,,,,,,,,>).MakeGenericType(types); 77 case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types); 78 } 79 } 80 throw ContractUtils.Unreachable; 81 } 82 } 83 #endif 84 85 internal static class ScriptingRuntimeHelpers 86 { Int32ToObject(int i)87 public static object Int32ToObject(int i) 88 { 89 switch (i) 90 { 91 case -1: 92 return Utils.BoxedIntM1; 93 case 0: 94 return Utils.BoxedInt0; 95 case 1: 96 return Utils.BoxedInt1; 97 case 2: 98 return Utils.BoxedInt2; 99 case 3: 100 return Utils.BoxedInt3; 101 } 102 103 return i; 104 } 105 GetPrimitiveDefaultValue(Type type)106 internal static object GetPrimitiveDefaultValue(Type type) 107 { 108 object result; 109 110 switch (type.GetTypeCode()) 111 { 112 case TypeCode.Boolean: 113 result = Utils.BoxedFalse; 114 break; 115 case TypeCode.SByte: 116 result = Utils.BoxedDefaultSByte; 117 break; 118 case TypeCode.Byte: 119 result = Utils.BoxedDefaultByte; 120 break; 121 case TypeCode.Char: 122 result = Utils.BoxedDefaultChar; 123 break; 124 case TypeCode.Int16: 125 result = Utils.BoxedDefaultInt16; 126 break; 127 case TypeCode.Int32: 128 result = Utils.BoxedInt0; 129 break; 130 case TypeCode.Int64: 131 result = Utils.BoxedDefaultInt64; 132 break; 133 case TypeCode.UInt16: 134 result = Utils.BoxedDefaultUInt16; 135 break; 136 case TypeCode.UInt32: 137 result = Utils.BoxedDefaultUInt32; 138 break; 139 case TypeCode.UInt64: 140 result = Utils.BoxedDefaultUInt64; 141 break; 142 case TypeCode.Single: 143 return Utils.BoxedDefaultSingle; 144 case TypeCode.Double: 145 return Utils.BoxedDefaultDouble; 146 case TypeCode.DateTime: 147 return Utils.BoxedDefaultDateTime; 148 case TypeCode.Decimal: 149 return Utils.BoxedDefaultDecimal; 150 default: 151 // Also covers DBNull which is a class. 152 return null; 153 } 154 155 if (type.IsEnum) 156 { 157 result = Enum.ToObject(type, result); 158 } 159 160 return result; 161 } 162 } 163 164 internal static class ExceptionHelpers 165 { 166 /// <summary> 167 /// Updates an exception before it's getting re-thrown so 168 /// we can present a reasonable stack trace to the user. 169 /// </summary> UnwrapAndRethrow(TargetInvocationException exception)170 public static void UnwrapAndRethrow(TargetInvocationException exception) 171 { 172 ExceptionDispatchInfo.Throw(exception.InnerException); 173 } 174 } 175 176 /// <summary> 177 /// A hybrid dictionary which compares based upon object identity. 178 /// </summary> 179 internal class HybridReferenceDictionary<TKey, TValue> where TKey : class 180 { 181 private KeyValuePair<TKey, TValue>[] _keysAndValues; 182 private Dictionary<TKey, TValue> _dict; 183 private const int ArraySize = 10; 184 TryGetValue(TKey key, out TValue value)185 public bool TryGetValue(TKey key, out TValue value) 186 { 187 Debug.Assert(key != null); 188 189 if (_dict != null) 190 { 191 return _dict.TryGetValue(key, out value); 192 } 193 else if (_keysAndValues != null) 194 { 195 for (int i = 0; i < _keysAndValues.Length; i++) 196 { 197 if (_keysAndValues[i].Key == key) 198 { 199 value = _keysAndValues[i].Value; 200 return true; 201 } 202 } 203 } 204 value = default(TValue); 205 return false; 206 } 207 Remove(TKey key)208 public void Remove(TKey key) 209 { 210 Debug.Assert(key != null); 211 212 if (_dict != null) 213 { 214 _dict.Remove(key); 215 } 216 else if (_keysAndValues != null) 217 { 218 for (int i = 0; i < _keysAndValues.Length; i++) 219 { 220 if (_keysAndValues[i].Key == key) 221 { 222 _keysAndValues[i] = new KeyValuePair<TKey, TValue>(); 223 return; 224 } 225 } 226 } 227 } 228 ContainsKey(TKey key)229 public bool ContainsKey(TKey key) 230 { 231 Debug.Assert(key != null); 232 233 if (_dict != null) 234 { 235 return _dict.ContainsKey(key); 236 } 237 238 KeyValuePair<TKey, TValue>[] keysAndValues = _keysAndValues; 239 if (keysAndValues != null) 240 { 241 for (int i = 0; i < keysAndValues.Length; i++) 242 { 243 if (keysAndValues[i].Key == key) 244 { 245 return true; 246 } 247 } 248 } 249 250 return false; 251 } 252 GetEnumerator()253 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 254 { 255 if (_dict != null) 256 { 257 return _dict.GetEnumerator(); 258 } 259 260 return GetEnumeratorWorker(); 261 } 262 GetEnumeratorWorker()263 private IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorWorker() 264 { 265 if (_keysAndValues != null) 266 { 267 for (int i = 0; i < _keysAndValues.Length; i++) 268 { 269 if (_keysAndValues[i].Key != null) 270 { 271 yield return _keysAndValues[i]; 272 } 273 } 274 } 275 } 276 277 public TValue this[TKey key] 278 { 279 get 280 { 281 Debug.Assert(key != null); 282 283 TValue res; 284 if (TryGetValue(key, out res)) 285 { 286 return res; 287 } 288 289 throw new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString())); 290 } 291 set 292 { 293 Debug.Assert(key != null); 294 295 if (_dict != null) 296 { 297 _dict[key] = value; 298 } 299 else 300 { 301 int index; 302 if (_keysAndValues != null) 303 { 304 index = -1; 305 for (int i = 0; i < _keysAndValues.Length; i++) 306 { 307 if (_keysAndValues[i].Key == key) 308 { 309 _keysAndValues[i] = new KeyValuePair<TKey, TValue>(key, value); 310 return; 311 } 312 else if (_keysAndValues[i].Key == null) 313 { 314 index = i; 315 } 316 } 317 } 318 else 319 { 320 _keysAndValues = new KeyValuePair<TKey, TValue>[ArraySize]; 321 index = 0; 322 } 323 324 if (index != -1) 325 { 326 _keysAndValues[index] = new KeyValuePair<TKey, TValue>(key, value); 327 } 328 else 329 { 330 _dict = new Dictionary<TKey, TValue>(); 331 for (int i = 0; i < _keysAndValues.Length; i++) 332 { 333 _dict[_keysAndValues[i].Key] = _keysAndValues[i].Value; 334 } 335 _keysAndValues = null; 336 337 _dict[key] = value; 338 } 339 } 340 } 341 } 342 } 343 344 internal static class Assert 345 { 346 [Conditional("DEBUG")] NotNull(object var)347 public static void NotNull(object var) 348 { 349 Debug.Assert(var != null); 350 } 351 } 352 } 353