private static int GetMostDerivedDictionarySlot(ref TypeDesc nextTypeToExamineForDictionarySlot, out TypeDesc typeWithDictionary) { while (nextTypeToExamineForDictionarySlot != null) { if (nextTypeToExamineForDictionarySlot.GetOrCreateTypeBuilderState().HasDictionarySlotInVTable) { typeWithDictionary = nextTypeToExamineForDictionarySlot; nextTypeToExamineForDictionarySlot = nextTypeToExamineForDictionarySlot.BaseType; return GetDictionarySlotInVTable(typeWithDictionary); } nextTypeToExamineForDictionarySlot = nextTypeToExamineForDictionarySlot.BaseType; } typeWithDictionary = null; return -1; }
/// <summary> /// Get the GC layout of a type when used as a field. /// NOTE: if the fieldtype is a reference type, this function will return GCLayout.None /// Consumers of the api must handle that special case. /// </summary> private unsafe TypeBuilder.GCLayout GetFieldGCLayout(TypeDesc fieldType) { if (!fieldType.IsValueType) { if (fieldType.IsPointer) return TypeBuilder.GCLayout.None; else return TypeBuilder.GCLayout.SingleReference; } // Is this a type that already exists? If so, get its gclayout from the EEType directly if (fieldType.RetrieveRuntimeTypeHandleIfPossible()) { return new TypeBuilder.GCLayout(fieldType.RuntimeTypeHandle); } // The type of the field must be a valuetype that is dynamically being constructed if (fieldType.IsTemplateCanonical()) { // Pull the GC Desc from the canonical instantiation TypeDesc templateType = fieldType.ComputeTemplate(); bool success = templateType.RetrieveRuntimeTypeHandleIfPossible(); Debug.Assert(success); return new TypeBuilder.GCLayout(templateType.RuntimeTypeHandle); } else { // Use the type builder state's computed InstanceGCLayout var instanceGCLayout = fieldType.GetOrCreateTypeBuilderState().InstanceGCLayout; if (instanceGCLayout == null) return TypeBuilder.GCLayout.None; return new TypeBuilder.GCLayout(instanceGCLayout, false /* Always represents a valuetype as the reference type case is handled above with the GCLayout.SingleReference return */); } }
// Get the GC layout of a type. Handles pre-created, universal template, and non-universal template cases // Only to be used for getting the instance layout of non-valuetypes. /// <summary> /// Get the GC layout of a type. Handles pre-created, universal template, and non-universal template cases /// Only to be used for getting the instance layout of non-valuetypes that are used as base types /// </summary> /// <param name="type"></param> /// <returns></returns> private unsafe TypeBuilder.GCLayout GetInstanceGCLayout(TypeDesc type) { Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Any)); Debug.Assert(!type.IsValueType); if (type.RetrieveRuntimeTypeHandleIfPossible()) { return new TypeBuilder.GCLayout(type.RuntimeTypeHandle); } if (type.IsTemplateCanonical()) { var templateType = type.ComputeTemplate(); bool success = templateType.RetrieveRuntimeTypeHandleIfPossible(); Debug.Assert(success && !templateType.RuntimeTypeHandle.IsNull()); return new TypeBuilder.GCLayout(templateType.RuntimeTypeHandle); } else { TypeBuilderState state = type.GetOrCreateTypeBuilderState(); if (state.InstanceGCLayout == null) return TypeBuilder.GCLayout.None; else return new TypeBuilder.GCLayout(state.InstanceGCLayout, true); } }
internal void GetFieldSizeAlignment(TypeDesc fieldType, out int size, out int alignment) { Debug.Assert(!fieldType.IsCanonicalSubtype(CanonicalFormKind.Any)); // All reference and array types are pointer-sized if (!fieldType.IsValueType) { size = IntPtr.Size; alignment = IntPtr.Size; return; } // Is this a type that already exists? If so, get its size from the EEType directly if (fieldType.RetrieveRuntimeTypeHandleIfPossible()) { unsafe { EEType* eeType = fieldType.RuntimeTypeHandle.ToEETypePtr(); size = (int)eeType->ValueTypeSize; alignment = eeType->FieldAlignmentRequirement; return; } } // The type of the field must be a generic valuetype that is dynamically being constructed Debug.Assert(fieldType.IsValueType); DefType fieldDefType = (DefType)fieldType; TypeBuilderState state = fieldType.GetOrCreateTypeBuilderState(); size = fieldDefType.InstanceFieldSize; alignment = fieldDefType.InstanceFieldAlignment; }
private ComputedStaticFieldLayout ParseStaticRegionSizesFromNativeLayout(TypeDesc type) { int nonGcDataSize = 0; int gcDataSize = 0; int threadDataSize = 0; TypeBuilderState state = type.GetOrCreateTypeBuilderState(); NativeParser typeInfoParser = state.GetParserForNativeLayoutInfo(); BagElementKind kind; while ((kind = typeInfoParser.GetBagElementKind()) != BagElementKind.End) { switch (kind) { case BagElementKind.NonGcStaticDataSize: TypeLoaderLogger.WriteLine("Found BagElementKind.NonGcStaticDataSize"); // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later) nonGcDataSize = checked((int)typeInfoParser.GetUnsigned()); break; case BagElementKind.GcStaticDataSize: TypeLoaderLogger.WriteLine("Found BagElementKind.GcStaticDataSize"); // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later) gcDataSize = checked((int)typeInfoParser.GetUnsigned()); break; case BagElementKind.ThreadStaticDataSize: TypeLoaderLogger.WriteLine("Found BagElementKind.ThreadStaticDataSize"); // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later) threadDataSize = checked((int)typeInfoParser.GetUnsigned()); break; default: typeInfoParser.SkipInteger(); break; } } ComputedStaticFieldLayout staticLayout = new ComputedStaticFieldLayout() { GcStatics = new StaticsBlock() { Size = gcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible }, NonGcStatics = new StaticsBlock() { Size = nonGcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible }, Offsets = null, // We're not computing field offsets here, so return null ThreadStatics = new StaticsBlock() { Size = threadDataSize, LargestAlignment = DefType.MaximumAlignmentPossible }, }; return staticLayout; }
public override DefType[] ComputeRuntimeInterfaces(TypeDesc type) { TypeBuilderState state = type.GetOrCreateTypeBuilderState(); int totalInterfaces = RuntimeAugments.GetInterfaceCount(state.TemplateType.RuntimeTypeHandle); TypeLoaderLogger.WriteLine("Building runtime interfaces for type " + type.ToString() + " (total interfaces = " + totalInterfaces.LowLevelToString() + ") ..."); DefType[] interfaces = new DefType[totalInterfaces]; int numInterfaces = 0; // // Copy over all interfaces from base class // if (type.BaseType != null) { foreach (var baseInterface in type.BaseType.RuntimeInterfaces) { // There should be no duplicates Debug.Assert(!InterfaceInSet(interfaces, numInterfaces, baseInterface)); interfaces[numInterfaces++] = baseInterface; TypeLoaderLogger.WriteLine(" -> Added basetype interface " + baseInterface.ToString() + " on type " + type.ToString()); } } NativeParser typeInfoParser = state.GetParserForNativeLayoutInfo(); NativeParser interfaceParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.ImplementedInterfaces); TypeDesc[] implementedInterfaces; if (!interfaceParser.IsNull) implementedInterfaces = state.NativeLayoutInfo.LoadContext.GetTypeSequence(ref interfaceParser); else implementedInterfaces = TypeDesc.EmptyTypes; // Note that the order in which the interfaces are added to the list is same as the order in which the MDIL binder adds them. // It is required for correctness foreach (TypeDesc interfaceType in implementedInterfaces) { DefType interfaceTypeAsDefType = (DefType)interfaceType; // Skip duplicates if (InterfaceInSet(interfaces, numInterfaces, interfaceTypeAsDefType)) continue; interfaces[numInterfaces++] = interfaceTypeAsDefType; TypeLoaderLogger.WriteLine(" -> Added interface " + interfaceTypeAsDefType.ToString() + " on type " + type.ToString()); foreach (var inheritedInterface in interfaceTypeAsDefType.RuntimeInterfaces) { // Skip duplicates if (InterfaceInSet(interfaces, numInterfaces, inheritedInterface)) continue; interfaces[numInterfaces++] = inheritedInterface; TypeLoaderLogger.WriteLine(" -> Added inherited interface " + inheritedInterface.ToString() + " on type " + type.ToString()); } } // TODO: Handle the screwy cases of generic interface folding Debug.Assert(numInterfaces == totalInterfaces, "Unexpected number of interfaces"); return interfaces; }