public GCStaticsNode(MetadataType type, PreinitializationManager preinitManager) { Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific)); _type = type; if (preinitManager.IsPreinitialized(type)) { _preinitializationInfo = preinitManager.GetPreinitializationInfo(_type); } }
public GCStaticsPreInitDataNode(TypePreinit.PreinitializationInfo preinitializationInfo) { Debug.Assert(!preinitializationInfo.Type.IsCanonicalSubtype(CanonicalFormKind.Specific)); _preinitializationInfo = preinitializationInfo; }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); // If the type has a class constructor, its non-GC statics section is prefixed // by System.Runtime.CompilerServices.StaticClassConstructionContext struct. if (factory.PreinitializationManager.HasLazyStaticConstructor(_type)) { int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment.AsInt, GetClassConstructorContextAlignment(_type.Context.Target)); int classConstructorContextStorageSize = GetClassConstructorContextStorageSize(factory.Target, _type); builder.RequireInitialAlignment(alignmentRequired); Debug.Assert(classConstructorContextStorageSize >= GetClassConstructorContextSize(_type.Context.Target)); // Add padding before the context if alignment forces us to do so builder.EmitZeros(classConstructorContextStorageSize - GetClassConstructorContextSize(_type.Context.Target)); // Emit the actual StaticClassConstructionContext MethodDesc cctorMethod = _type.GetStaticConstructor(); builder.EmitPointerReloc(factory.ExactCallableAddress(cctorMethod)); builder.EmitZeroPointer(); } else { builder.RequireInitialAlignment(_type.NonGCStaticFieldAlignment.AsInt); } if (_preinitializationManager.IsPreinitialized(_type)) { TypePreinit.PreinitializationInfo preinitInfo = _preinitializationManager.GetPreinitializationInfo(_type); int initialOffset = builder.CountBytes; foreach (FieldDesc field in _type.GetFields()) { if (!field.IsStatic || field.HasRva || field.IsLiteral || field.IsThreadStatic || field.HasGCStaticBase) { continue; } int padding = field.Offset.AsInt - builder.CountBytes + initialOffset; Debug.Assert(padding >= 0); builder.EmitZeros(padding); TypePreinit.ISerializableValue val = preinitInfo.GetFieldValue(field); int currentOffset = builder.CountBytes; val.WriteFieldData(ref builder, factory); Debug.Assert(builder.CountBytes - currentOffset == field.FieldType.GetElementSize().AsInt); } int pad = _type.NonGCStaticFieldSize.AsInt - builder.CountBytes + initialOffset; Debug.Assert(pad >= 0); builder.EmitZeros(pad); } else { builder.EmitZeros(_type.NonGCStaticFieldSize.AsInt); } builder.AddSymbol(this); return(builder.ToObjectData()); }