public TypeData this[uint idx] { get { return m_array[idx]; } set { lock (m_writeLock) { Debug.Assert(value.TypeID == idx); if (idx >= m_array.Length) { var newArray = new TypeData[NextPowOf2(idx + 1)]; Array.Copy(m_array, newArray, m_array.Length); m_array = newArray; } Debug.Assert(m_array[idx] == null); m_array[idx] = value; } } }
public bool TryGetValue(Type key, out TypeData value) { var buckets = Volatile.Read(ref m_buckets); int idx = Hash(key, buckets.Length); Pair[] arr = Volatile.Read(ref buckets[idx]); if (arr == null) goto not_found; for (int i = 0; i < arr.Length; ++i) { if (arr[i].Key == key) { value = arr[i].Value; return true; } } not_found: value = null; return false; }
public static void GenerateDeserializerTrampoline(ILGenerator il, Type type, TypeData data) { if (type.IsValueType) { var local = il.DeclareLocal(type); // call deserializer for this typeID if (data.NeedsInstanceParameter) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, local); il.Emit(OpCodes.Call, data.ReaderMethodInfo); // write result object to out object il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Stind_Ref); } else { // call deserializer for this typeID if (data.NeedsInstanceParameter) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Tailcall); il.Emit(OpCodes.Call, data.ReaderMethodInfo); } il.Emit(OpCodes.Ret); }
static Dictionary<Type, TypeData> GenerateTypeData(Type[] types) { var map = new Dictionary<Type, TypeData>(types.Length); // TypeID 0 is reserved for null #if GENERATE_SWITCH ushort caseID = (ushort)(s_Type_caseIDtypeIDMap == null ? 1 : s_Type_caseIDtypeIDMap.Count + 1); #endif foreach (var type in types) { ushort typeID; if (!SerializationID.predefinedID.TryGetValue(type, out typeID)) { typeID = SerializationID.userID++; } MethodInfo writer; MethodInfo reader; bool isStatic = Helpers.GetPrimitives(typeof(Primitives), type, out writer, out reader); if (type.IsPrimitive && isStatic == false) throw new InvalidOperationException(String.Format("Missing primitive read/write methods for {0}", type.FullName)); #if GENERATE_SWITCH var td = new TypeData(typeID, caseID++); #else var td = new TypeData(typeID); #endif if (isStatic) { if (writer.IsGenericMethodDefinition) { Debug.Assert(type.IsGenericType); var genArgs = type.GetGenericArguments(); writer = writer.MakeGenericMethod(genArgs); reader = reader.MakeGenericMethod(genArgs); } td.WriterMethodInfo = writer; td.ReaderMethodInfo = reader; td.IsDynamic = false; } else { if (typeof(System.Runtime.Serialization.ISerializable).IsAssignableFrom(type)) throw new InvalidOperationException(String.Format("Cannot serialize {0}: ISerializable not supported", type.FullName)); td.IsDynamic = true; } map[type] = td; } return map; }
static Dictionary<Type, TypeData> GenerateTypeData(Type[] rootTypes) { var map = new Dictionary<Type, TypeData>(); var stack = new Stack<Type>(PrimitivesSerializer.GetSupportedTypes().Concat(rootTypes)); // TypeID 0 is reserved for null ushort typeID = 1; while (stack.Count > 0) { var type = stack.Pop(); if (map.ContainsKey(type)) continue; if (type.IsAbstract || type.IsInterface) continue; if (type.ContainsGenericParameters) throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); var serializer = s_userTypeSerializers.FirstOrDefault(h => h.Handles(type)); if (serializer == null) serializer = s_typeSerializers.FirstOrDefault(h => h.Handles(type)); if (serializer == null) throw new NotSupportedException(String.Format("No serializer for {0}", type.FullName)); foreach (var t in serializer.GetSubtypes(type)) stack.Push(t); TypeData typeData; if (serializer is IStaticTypeSerializer) { var sts = (IStaticTypeSerializer)serializer; MethodInfo writer; MethodInfo reader; sts.GetStaticMethods(type, out writer, out reader); Debug.Assert(writer != null && reader != null); typeData = new TypeData(typeID++, writer, reader); } else if (serializer is IDynamicTypeSerializer) { var dts = (IDynamicTypeSerializer)serializer; typeData = new TypeData(typeID++, dts); } else { throw new Exception(); } map[type] = typeData; } return map; }
/// <summary> /// Create delegate that calls reader either directly, or via a trampoline /// </summary> public static Delegate CreateDeserializeDelegate(Type paramType, TypeData data) { Type readerType = data.Type; if (paramType != readerType && paramType != typeof(object)) { throw new Exception(); } bool needTypeConv = paramType != readerType; bool needsInstanceParameter = data.ReaderNeedsInstance; var delegateType = typeof(DeserializeDelegate <>).MakeGenericType(paramType); // Can we call the reader directly? if (!needTypeConv && needsInstanceParameter) { if (data.ReaderMethodInfo is DynamicMethod dynamicReader) { return(dynamicReader.CreateDelegate(delegateType)); } else { return(Delegate.CreateDelegate(delegateType, data.ReaderMethodInfo)); } } // Create a trampoline var wrapper = GenerateDynamicDeserializerStub(paramType); var il = wrapper.GetILGenerator(); if (needsInstanceParameter) { il.Emit(OpCodes.Ldarg_0); } if (needTypeConv && readerType.IsValueType) { var local = il.DeclareLocal(readerType); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, local); il.Emit(OpCodes.Call, data.ReaderMethodInfo); // write result object to out object il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Box, readerType); il.Emit(OpCodes.Stind_Ref); } else { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); // XXX tailcall causes slowdowns with large valuetypes //il.Emit(OpCodes.Tailcall); il.Emit(OpCodes.Call, data.ReaderMethodInfo); } il.Emit(OpCodes.Ret); return(wrapper.CreateDelegate(delegateType)); }
public Pair(Type key, TypeData value) { this.Key = key; this.Value = value; }
static void Add(Pair[][] buckets, Type key, TypeData value) { int idx = Hash(key, buckets.Length); Pair[] arr = buckets[idx]; if (arr == null) buckets[idx] = arr = new Pair[InitialListSize]; for (int i = 0; i < arr.Length; ++i) { if (arr[i].Key == null) { arr[i] = new Pair(key, value); return; } } var newArr = new Pair[arr.Length * 2]; Array.Copy(arr, newArr, arr.Length); newArr[arr.Length] = new Pair(key, value); buckets[idx] = newArr; }
/// <summary> /// Create delegate that calls reader either directly, or via a trampoline /// </summary> public static Delegate CreateDeserializeDelegate(Type paramType, TypeData data) { Type readerType = data.Type; if (paramType != readerType && paramType != typeof(object)) throw new Exception(); bool needTypeConv = paramType != readerType; bool needsInstanceParameter = data.ReaderNeedsInstance; var delegateType = typeof(DeserializeDelegate<>).MakeGenericType(paramType); // Can we call the reader directly? if (!needTypeConv && needsInstanceParameter) { var dynamicReader = data.ReaderMethodInfo as DynamicMethod; if (dynamicReader != null) return dynamicReader.CreateDelegate(delegateType); else return Delegate.CreateDelegate(delegateType, data.ReaderMethodInfo); } // Create a trampoline var wrapper = GenerateDynamicDeserializerStub(paramType); var il = wrapper.GetILGenerator(); if (needsInstanceParameter) il.Emit(OpCodes.Ldarg_0); if (needTypeConv && readerType.IsValueType) { var local = il.DeclareLocal(readerType); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, local); il.Emit(OpCodes.Call, data.ReaderMethodInfo); // write result object to out object il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Box, readerType); il.Emit(OpCodes.Stind_Ref); } else { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); // XXX tailcall causes slowdowns with large valuetypes //il.Emit(OpCodes.Tailcall); il.Emit(OpCodes.Call, data.ReaderMethodInfo); } il.Emit(OpCodes.Ret); return wrapper.CreateDelegate(delegateType); }
void AddTypesInternal(Dictionary <Type, uint> typeMap) { AssertLocked(); foreach (var kvp in typeMap) { var type = kvp.Key; uint typeID = kvp.Value; if (type == null) { throw new ArgumentException("Null type in dictionary"); } if (typeID == 0) { throw new ArgumentException("TypeID 0 is reserved"); } if (m_runtimeTypeMap.ContainsKey(type)) { if (m_runtimeTypeMap[type].TypeID != typeID) { throw new ArgumentException(String.Format("Type {0} already added with different TypeID", type.FullName)); } continue; } if (m_runtimeTypeIDList.ContainsTypeID(typeID)) { throw new ArgumentException(String.Format("Type with typeID {0} already added", typeID)); } #if !NET35 && !NET40 if (type.GetTypeInfo().IsAbstract || type.GetTypeInfo().IsInterface) { throw new ArgumentException(String.Format("Type {0} is abstract or interface", type.FullName)); } if (type.GetTypeInfo().ContainsGenericParameters) { throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); } #else if (type.IsAbstract || type.IsInterface) { throw new ArgumentException(String.Format("Type {0} is abstract or interface", type.FullName)); } if (type.ContainsGenericParameters) { throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); } #endif ITypeSerializer serializer = GetTypeSerializer(type); var data = new TypeData(type, typeID, serializer); m_runtimeTypeMap[type] = data; m_runtimeTypeIDList[typeID] = data; } }
Dictionary <Type, uint> AddTypesInternal(IEnumerable <Type> roots) { AssertLocked(); var stack = new Stack <Type>(roots); var addedMap = new Dictionary <Type, uint>(); while (stack.Count > 0) { var type = stack.Pop(); if (m_runtimeTypeMap.ContainsKey(type)) { continue; } #if !NET35 && !NET40 if (type.GetTypeInfo().IsAbstract || type.GetTypeInfo().IsInterface) { continue; } if (type.GetTypeInfo().ContainsGenericParameters) { throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); } #else if (type.IsAbstract || type.IsInterface) { continue; } if (type.ContainsGenericParameters) { throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); } #endif while (m_runtimeTypeIDList.ContainsTypeID(m_nextAvailableTypeID)) { m_nextAvailableTypeID++; } uint typeID = m_nextAvailableTypeID++; ITypeSerializer serializer = GetTypeSerializer(type); var data = new TypeData(type, typeID, serializer); m_runtimeTypeMap[type] = data; m_runtimeTypeIDList[typeID] = data; addedMap[type] = typeID; foreach (var t in serializer.GetSubtypes(type)) { if (m_runtimeTypeMap.ContainsKey(t) == false) { stack.Push(t); } } } return(addedMap); }
public static void GenerateSerializerTrampoline(ILGenerator il, Type type, TypeData data) { if (data.NeedsInstanceParameter) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type); il.Emit(OpCodes.Tailcall); il.Emit(OpCodes.Call, data.WriterMethodInfo); il.Emit(OpCodes.Ret); }
/// <summary> /// Create delegate that calls writer either directly, or via a trampoline /// </summary> public static Delegate CreateSerializeDelegate(Type paramType, TypeData data) { Type writerType = data.Type; if (paramType != writerType && paramType != typeof(object)) throw new Exception(); bool needTypeConv = paramType != writerType; bool needsInstanceParameter = data.WriterNeedsInstance; var delegateType = typeof(SerializeDelegate<>).MakeGenericType(paramType); // Can we call the writer directly? if (!needTypeConv && needsInstanceParameter) { var dynamicWriter = data.WriterMethodInfo as DynamicMethod; if (dynamicWriter != null) return dynamicWriter.CreateDelegate(delegateType); else return Delegate.CreateDelegate(delegateType, data.WriterMethodInfo); } // Create a trampoline var wrapper = Helpers.GenerateDynamicSerializerStub(paramType); var il = wrapper.GetILGenerator(); if (needsInstanceParameter) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); if (needTypeConv) il.Emit(writerType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, writerType); // XXX tailcall causes slowdowns with large valuetypes //il.Emit(OpCodes.Tailcall); il.Emit(OpCodes.Call, data.WriterMethodInfo); il.Emit(OpCodes.Ret); return wrapper.CreateDelegate(delegateType); }
static Dictionary<Type, TypeData> GenerateTypeData(Type[] types) { var map = new Dictionary<Type, TypeData>(types.Length); // TypeID 0 is reserved for null ushort typeID = 1; foreach (var type in types) { MethodInfo writer; MethodInfo reader; bool isStatic = Helpers.GetPrimitives(typeof(Primitives), type, out writer, out reader); if (type.IsPrimitive && isStatic == false) throw new InvalidOperationException(String.Format("Missing primitive read/write methods for {0}", type.FullName)); var td = new TypeData(typeID++); if (isStatic) { if (writer.IsGenericMethodDefinition) { Debug.Assert(type.IsGenericType); var genArgs = type.GetGenericArguments(); writer = writer.MakeGenericMethod(genArgs); reader = reader.MakeGenericMethod(genArgs); } td.WriterMethodInfo = writer; td.ReaderMethodInfo = reader; td.IsDynamic = false; } else { if (typeof(System.Runtime.Serialization.ISerializable).IsAssignableFrom(type)) throw new InvalidOperationException(String.Format("Cannot serialize {0}: ISerializable not supported", type.FullName)); td.IsDynamic = true; } map[type] = td; } return map; }
static Dictionary<Type, TypeData> GenerateTypeData(Type[] types) { var map = new Dictionary<Type, TypeData>(types.Length); // TypeID 0 is reserved for null ushort typeID = 1; foreach (var type in types) { var writer = Primitives.GetWritePrimitive(type); var reader = Primitives.GetReadPrimitive(type); if ((writer != null) != (reader != null)) throw new InvalidOperationException(String.Format("Missing a read or write primitive for {0}", type.FullName)); var isStatic = writer != null; if (type.IsPrimitive && isStatic == false) throw new InvalidOperationException(String.Format("Missing primitive read/write methods for {0}", type.FullName)); var td = new TypeData(typeID++); if (isStatic) { td.WriterMethodInfo = writer; td.ReaderMethodInfo = reader; td.IsDynamic = false; } else { if (typeof(System.Runtime.Serialization.ISerializable).IsAssignableFrom(type)) throw new InvalidOperationException(String.Format("Cannot serialize {0}: ISerializable not supported", type.FullName)); td.IsDynamic = true; } map[type] = td; } return map; }
static Dictionary <Type, TypeData> GenerateTypeData(IEnumerable <Type> rootTypes) { var map = new Dictionary <Type, TypeData>(); var stack = new Stack <Type>(PrimitivesSerializer.GetSupportedTypes().Concat(rootTypes)); // TypeID 0 is reserved for null ushort typeID = 1; while (stack.Count > 0) { var type = stack.Pop(); if (map.ContainsKey(type)) { continue; } if (type.IsAbstract || type.IsInterface) { continue; } if (type.ContainsGenericParameters) { throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); } var serializer = s_userTypeSerializers.FirstOrDefault(h => h.Handles(type)); if (serializer == null) { serializer = s_typeSerializers.FirstOrDefault(h => h.Handles(type)); } if (serializer == null) { throw new NotSupportedException(String.Format("No serializer for {0}", type.FullName)); } foreach (var t in serializer.GetSubtypes(type)) { stack.Push(t); } TypeData typeData; if (serializer is IStaticTypeSerializer) { var sts = (IStaticTypeSerializer)serializer; MethodInfo writer; MethodInfo reader; sts.GetStaticMethods(type, out writer, out reader); Debug.Assert(writer != null && reader != null); typeData = new TypeData(typeID++, writer, reader); } else if (serializer is IDynamicTypeSerializer) { var dts = (IDynamicTypeSerializer)serializer; typeData = new TypeData(typeID++, dts); } else { throw new Exception(); } map[type] = typeData; } return(map); }