private void OutputComponentSize(ref ObjectDataBuilder objData) { if (_type.IsArray) { TypeDesc elementType = ((ArrayType)_type).ElementType; if (elementType == elementType.Context.UniversalCanonType) { objData.EmitShort(0); } else { int elementSize = elementType.GetElementSize().AsInt; // We validated that this will fit the short when the node was constructed. No need for nice messages. objData.EmitShort((short)checked ((ushort)elementSize)); } } else if (_type.IsString) { objData.EmitShort(StringComponentSize.Value); } else { objData.EmitShort(0); } }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.EmitZeroPointer(); // Sync block DefType systemStringType = factory.TypeSystemContext.GetWellKnownType(WellKnownType.String); // // The GC requires a direct reference to frozen objects' EETypes. If System.String will be compiled into a separate // binary, it must be cloned into this one. // if (factory.CompilationModuleGroup.ShouldReferenceThroughImportTable(systemStringType)) { dataBuilder.EmitPointerReloc(factory.ConstructedClonedTypeSymbol(systemStringType)); } else { dataBuilder.EmitPointerReloc(factory.ConstructedTypeSymbol(systemStringType)); } dataBuilder.EmitInt(_data.Length); foreach (char c in _data) { dataBuilder.EmitShort((short)c); } // Null-terminate for friendliness with interop dataBuilder.EmitShort(0); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) { flags |= (short)EETypeFlags.ValueTypeFlag; } if (_type.IsInterface) { flags |= (short)EETypeFlags.IsInterfaceFlag; } dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.ModuleManagerIndirection); return(dataBuilder.ToObjectData()); }
private void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { if (!_constructed) { objData.EmitShort(0); objData.EmitShort(0); return; } int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type; while (currentTypeSlice != null) { List <MethodDesc> virtualSlots; factory.VirtualSlots.TryGetValue(currentTypeSlice, out virtualSlots); if (virtualSlots != null) { virtualSlotCount += virtualSlots.Count; } currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked ((short)virtualSlotCount)); objData.EmitShort(checked ((short)_type.RuntimeInterfaces.Length)); }
void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory) { var entryCountReservation = builder.ReserveInt(); int entryCount = 0; for (int interfaceIndex = 0; interfaceIndex < _type.RuntimeInterfaces.Length; interfaceIndex++) { var interfaceType = _type.RuntimeInterfaces[interfaceIndex]; Debug.Assert(interfaceType.IsInterface); IReadOnlyList <MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots; for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++) { MethodDesc declMethod = virtualSlots[interfaceMethodSlot]; var implMethod = _type.GetClosestDefType().ResolveInterfaceMethodToVirtualMethodOnType(declMethod); // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface // dispatch will walk the inheritance chain). if (implMethod != null) { builder.EmitShort(checked ((short)interfaceIndex)); builder.EmitShort(checked ((short)interfaceMethodSlot)); builder.EmitShort(checked ((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod))); entryCount++; } } } builder.EmitInt(entryCountReservation, entryCount); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.EmitZeroPointer(); // Sync block DefType systemStringType = factory.TypeSystemContext.GetWellKnownType(WellKnownType.String); // // The GC requires a direct reference to frozen objects' EETypes. If System.String will be compiled into a separate // binary, it must be cloned into this one. // if (factory.CompilationModuleGroup.ShouldReferenceThroughImportTable(systemStringType)) { dataBuilder.EmitPointerReloc(factory.ConstructedClonedTypeSymbol(systemStringType)); } else { dataBuilder.EmitPointerReloc(factory.ConstructedTypeSymbol(systemStringType)); } dataBuilder.EmitInt(_data.Length); foreach (char c in _data) { dataBuilder.EmitShort((short)c); } // Null-terminate for friendliness with interop dataBuilder.EmitShort(0); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); ComputeOptionalEETypeFields(factory, relocsOnly); OutputGCDesc(ref objData); OutputComponentSize(ref objData); OutputFlags(factory, ref objData); OutputBaseSize(ref objData); OutputRelatedType(factory, ref objData); // Number of vtable slots will be only known later. Reseve the bytes for it. var vtableSlotCountReservation = objData.ReserveShort(); // Number of interfaces will only be known later. Reserve the bytes for it. var interfaceCountReservation = objData.ReserveShort(); objData.EmitInt(_type.GetHashCode()); objData.EmitPointerReloc(factory.TypeManagerIndirection); if (EmitVirtualSlotsAndInterfaces) { // Emit VTable Debug.Assert(objData.CountBytes - ((ISymbolDefinitionNode)this).Offset == GetVTableOffset(objData.TargetPointerSize)); SlotCounter virtualSlotCounter = SlotCounter.BeginCounting(ref /* readonly */ objData); OutputVirtualSlots(factory, ref objData, _type, _type, relocsOnly); // Update slot count int numberOfVtableSlots = virtualSlotCounter.CountSlots(ref /* readonly */ objData); objData.EmitShort(vtableSlotCountReservation, checked ((short)numberOfVtableSlots)); // Emit interface map SlotCounter interfaceSlotCounter = SlotCounter.BeginCounting(ref /* readonly */ objData); OutputInterfaceMap(factory, ref objData); // Update slot count int numberOfInterfaceSlots = interfaceSlotCounter.CountSlots(ref /* readonly */ objData); objData.EmitShort(interfaceCountReservation, checked ((short)numberOfInterfaceSlots)); } else { // If we're not emitting any slots, the number of slots is zero. objData.EmitShort(vtableSlotCountReservation, 0); objData.EmitShort(interfaceCountReservation, 0); } OutputFinalizerMethod(factory, ref objData); OutputOptionalFields(factory, ref objData); OutputNullableTypeParameter(factory, ref objData); OutputGenericInstantiationDetails(factory, ref objData); return(objData.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory, relocsOnly); dataBuilder.RequireInitialPointerAlignment(); dataBuilder.AddSymbol(this); EETypeRareFlags rareFlags = 0; short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) { flags |= (short)EETypeFlags.ValueTypeFlag; } if (_type.IsInterface) { flags |= (short)EETypeFlags.IsInterfaceFlag; } if (factory.TypeSystemContext.HasLazyStaticConstructor(_type)) { rareFlags = rareFlags | EETypeRareFlags.HasCctorFlag; } if (_type.IsByRefLike) { rareFlags |= EETypeRareFlags.IsByRefLikeFlag; } if (rareFlags != 0) { _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, (uint)rareFlags); } if (HasOptionalFields) { flags |= (short)EETypeFlags.OptionalFieldsFlag; } if (_type.IsEnum) { flags |= (short)EETypeBuilderHelpers.ComputeElementTypeFlags(_type); } dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.TypeManagerIndirection); if (HasOptionalFields) { dataBuilder.EmitPointerReloc(_optionalFieldsNode); } return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); bool hasPointers = NumSeries > 0; if (hasPointers) { for (int i = ((_runLengths.Length / 2) * 2) - 1; i >= 0; i--) { if (_targetPointerSize == 4) { dataBuilder.EmitInt(_runLengths[i]); } else { dataBuilder.EmitLong(_runLengths[i]); } } if (_targetPointerSize == 4) { dataBuilder.EmitInt(NumSeries); } else { dataBuilder.EmitLong(NumSeries); } } int totalSize = 0; foreach (int run in _runLengths) { totalSize += run * _targetPointerSize; } dataBuilder.EmitShort(0); // ComponentSize is always 0 if (hasPointers) { dataBuilder.EmitShort(0x20); // TypeFlags.HasPointers } else { dataBuilder.EmitShort(0x00); } totalSize = Math.Max(totalSize, _targetPointerSize * 3); // minimum GC eetype size is 3 pointers dataBuilder.EmitInt(totalSize); return(dataBuilder.ToObjectData()); }
void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory) { var entryCountReservation = builder.ReserveInt(); int entryCount = 0; TypeDesc declType = _type.GetClosestDefType(); // Catch any runtime interface collapsing. We shouldn't have any Debug.Assert(declType.RuntimeInterfaces.Length == declType.GetTypeDefinition().RuntimeInterfaces.Length); for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++) { var interfaceType = declType.RuntimeInterfaces[interfaceIndex]; var interfaceDefinitionType = declType.GetTypeDefinition().RuntimeInterfaces[interfaceIndex]; Debug.Assert(interfaceType.IsInterface); IReadOnlyList <MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots; for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++) { MethodDesc declMethod = virtualSlots[interfaceMethodSlot]; if (!interfaceType.IsTypeDefinition) { declMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(declMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceDefinitionType); } var implMethod = declType.GetTypeDefinition().ResolveInterfaceMethodToVirtualMethodOnType(declMethod); // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface // dispatch will walk the inheritance chain). if (implMethod != null) { TypeDesc implType = declType; while (!implType.HasSameTypeDefinition(implMethod.OwningType)) { implType = implType.BaseType; } MethodDesc targetMethod = implMethod; if (!implType.IsTypeDefinition) { targetMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(implMethod.GetTypicalMethodDefinition(), (InstantiatedType)implType); } builder.EmitShort(checked ((short)interfaceIndex)); builder.EmitShort(checked ((short)(interfaceMethodSlot + (interfaceType.HasGenericDictionarySlot() ? 1 : 0)))); builder.EmitShort(checked ((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, declType))); entryCount++; } } } builder.EmitInt(entryCountReservation, entryCount); }
protected override void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type.GetClosestDefType(); while (currentTypeSlice != null) { virtualSlotCount += factory.VTable(currentTypeSlice).Slots.Count; currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked ((short)virtualSlotCount)); objData.EmitShort(checked ((short)_type.RuntimeInterfaces.Length)); }
private void OutputComponentSize(ref ObjectDataBuilder objData) { if (_type.IsArray) { objData.EmitShort((short)((ArrayType)_type).ElementType.GetElementSize()); } else if (_type.IsString) { objData.EmitShort(2); } else { objData.EmitShort(0); } }
private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) { // Generic array enumerators use special variance rules recognized by the runtime flags |= (UInt16)EETypeFlags.GenericVarianceFlag; } ISymbolNode relatedTypeNode = GetRelatedTypeNode(factory); // If the related type (base type / array element type / pointee type) is not part of this compilation group, and // the output binaries will be multi-file (not multiple object files linked together), indicate to the runtime // that it should indirect through the import address table if (relatedTypeNode != null && relatedTypeNode.RepresentsIndirectionCell) { flags |= (UInt16)EETypeFlags.RelatedTypeViaIATFlag; } // Todo: Generic Type Definition EETypes if (HasOptionalFields) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } objData.EmitShort((short)flags); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.EmitZeroPointer(); // Sync block dataBuilder.EmitPointerReloc(GetEETypeNode(factory)); dataBuilder.EmitInt(_data.Length); foreach (char c in _data) { dataBuilder.EmitShort((short)c); } // Null-terminate for friendliness with interop dataBuilder.EmitShort(0); }
private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) { // Generic array enumerators use special variance rules recognized by the runtime flags |= (UInt16)EETypeFlags.GenericVarianceFlag; } if (factory.TypeSystemContext.IsGenericArrayInterfaceType(_type)) { // Runtime casting logic relies on all interface types implemented on arrays // to have the variant flag set (even if all the arguments are non-variant). // This supports e.g. casting uint[] to ICollection<int> flags |= (UInt16)EETypeFlags.GenericVarianceFlag; } ISymbolNode relatedTypeNode = GetRelatedTypeNode(factory); // If the related type (base type / array element type / pointee type) is not part of this compilation group, and // the output binaries will be multi-file (not multiple object files linked together), indicate to the runtime // that it should indirect through the import address table if (relatedTypeNode != null && relatedTypeNode.RepresentsIndirectionCell) { flags |= (UInt16)EETypeFlags.RelatedTypeViaIATFlag; } if (HasOptionalFields) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } objData.EmitShort((short)flags); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); ComputeOptionalEETypeFields(factory, relocsOnly); OutputGCDesc(ref objData); OutputComponentSize(ref objData); OutputFlags(factory, ref objData); OutputBaseSize(ref objData); OutputRelatedType(factory, ref objData); // Avoid consulting VTable slots until they're guaranteed complete during final data emission if (EmitVirtualSlotsAndInterfaces && !relocsOnly) { OutputVirtualSlotAndInterfaceCount(factory, ref objData); } else { objData.EmitShort(0); objData.EmitShort(0); } objData.EmitInt(_type.GetHashCode()); objData.EmitPointerReloc(factory.TypeManagerIndirection); if (EmitVirtualSlotsAndInterfaces) { // Avoid consulting VTable slots until they're guaranteed complete during final data emission if (!relocsOnly) { OutputVirtualSlots(factory, ref objData, _type, _type); } OutputInterfaceMap(factory, ref objData); } OutputFinalizerMethod(factory, ref objData); OutputOptionalFields(factory, ref objData); OutputNullableTypeParameter(factory, ref objData); OutputGenericInstantiationDetails(factory, ref objData); return(objData.ToObjectData()); }
private void OutputComponentSize(ref ObjectDataBuilder objData) { if (_type.IsArray) { int elementSize = ((ArrayType)_type).ElementType.GetElementSize(); // We validated that this will fit the short when the node was constructed. No need for nice messages. objData.EmitShort((short)checked ((ushort)elementSize)); } else if (_type.IsString) { objData.EmitShort(2); } else { objData.EmitShort(0); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory, relocsOnly); dataBuilder.RequireInitialPointerAlignment(); dataBuilder.AddSymbol(this); // +1 for SyncBlock (static size already includes MethodTable) Debug.Assert(factory.Target.Abi == TargetAbi.NativeAot || factory.Target.Abi == TargetAbi.CppCodegen); int totalSize = (_gcMap.Size + 1) * _target.PointerSize; // We only need to check for containsPointers because ThreadStatics are always allocated // on the GC heap (no matter what "HasGCStaticBase" says). // If that ever changes, we can assume "true" and switch this to an assert. bool containsPointers = _gcMap.NumSeries > 0; if (containsPointers) { GCDescEncoder.EncodeStandardGCDesc(ref dataBuilder, _gcMap, totalSize, 0); } Debug.Assert(dataBuilder.CountBytes == ((ISymbolDefinitionNode)this).Offset); dataBuilder.EmitShort(0); // ComponentSize is always 0 short flags = 0; if (containsPointers) { flags |= (short)EETypeFlags.HasPointersFlag; } dataBuilder.EmitShort(flags); totalSize = Math.Max(totalSize, _target.PointerSize * 3); // minimum GC MethodTable size is 3 pointers dataBuilder.EmitInt(totalSize); // Related type: System.Object. This allows storing an instance of this type in an array of objects. dataBuilder.EmitPointerReloc(factory.NecessaryTypeSymbol(factory.TypeSystemContext.GetWellKnownType(WellKnownType.Object))); return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); // +2 for SyncBlock and EETypePtr field int totalSize = (_gcMap.Size + 2) * _target.PointerSize; // We only need to check for containsPointers because ThreadStatics are always allocated // on the GC heap (no matter what "HasGCStaticBase" says). // If that ever changes, we can assume "true" and switch this to an assert. bool containsPointers = _gcMap.NumSeries > 0; if (containsPointers) { GCDescEncoder.EncodeStandardGCDesc(ref dataBuilder, _gcMap, totalSize, 0); } Debug.Assert(dataBuilder.CountBytes == Offset); dataBuilder.EmitShort(0); // ComponentSize is always 0 short flags = 0; if (containsPointers) { flags |= (short)EETypeFlags.HasPointersFlag; } dataBuilder.EmitShort(flags); totalSize = Math.Max(totalSize, _target.PointerSize * 3); // minimum GC eetype size is 3 pointers dataBuilder.EmitInt(totalSize); // This is just so that EEType::Validate doesn't blow up at runtime dataBuilder.EmitPointerReloc(this); // Related type: itself return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory, relocsOnly); dataBuilder.RequireInitialPointerAlignment(); dataBuilder.AddSymbol(this); EETypeRareFlags rareFlags = 0; ushort flags = EETypeBuilderHelpers.ComputeFlags(_type); if (factory.PreinitializationManager.HasLazyStaticConstructor(_type)) { rareFlags = rareFlags | EETypeRareFlags.HasCctorFlag; } if (_type.IsByRefLike) { rareFlags |= EETypeRareFlags.IsByRefLikeFlag; } if (rareFlags != 0) { _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, (uint)rareFlags); } if (HasOptionalFields) { flags |= (ushort)EETypeFlags.OptionalFieldsFlag; } dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitUShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); OutputTypeManagerIndirection(factory, ref dataBuilder); OutputWritableData(factory, ref dataBuilder); OutputOptionalFields(factory, ref dataBuilder); return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); if (!relocsOnly) { var entries = BuildDispatchMap(factory); objData.EmitInt(entries.Length); foreach (var entry in entries) { objData.EmitShort(entry.InterfaceIndex); objData.EmitShort(entry.InterfaceMethodSlot); objData.EmitShort(entry.ImplementationMethodSlot); } } return(objData.ToObjectData()); }
private void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { if (!_constructed) { objData.EmitShort(0); objData.EmitShort(0); return; } int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type.GetClosestMetadataType(); while (currentTypeSlice != null) { virtualSlotCount += factory.VTable(currentTypeSlice).Slots.Count; currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked ((short)virtualSlotCount)); objData.EmitShort(checked ((short)_type.RuntimeInterfaces.Length)); }
protected virtual void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { Debug.Assert(EmitVirtualSlotsAndInterfaces); int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type.GetClosestDefType(); while (currentTypeSlice != null) { if (currentTypeSlice.HasGenericDictionarySlot()) { virtualSlotCount++; } virtualSlotCount += factory.VTable(currentTypeSlice).Slots.Count; currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked ((short)virtualSlotCount)); objData.EmitShort(checked ((short)_type.RuntimeInterfaces.Length)); }
private void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type; while (currentTypeSlice != null) { List <MethodDesc> virtualSlots; factory.VirtualSlots.TryGetValue(currentTypeSlice, out virtualSlots); if (virtualSlots != null) { virtualSlotCount += virtualSlots.Count; } currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked ((short)virtualSlotCount)); // Todo: Number of slots of EEInterfaceInfo when we add interface support objData.EmitShort(0); }
private void OutputComponentSize(ref ObjectDataBuilder objData) { if (_type.IsArray) { int elementSize = ((ArrayType)_type).ElementType.GetElementSize(); if (elementSize >= 64 * 1024) { // TODO: Array of type 'X' cannot be created because base value type is too large. throw new TypeLoadException(); } objData.EmitShort((short)elementSize); } else if (_type.IsString) { objData.EmitShort(2); } else { objData.EmitShort(0); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) flags |= (short)EETypeFlags.ValueTypeFlag; if (_type.IsInterface) flags |= (short)EETypeFlags.IsInterfaceFlag; dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.ModuleManagerIndirection); return dataBuilder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = dataBuilder.TargetPointerSize; dataBuilder.DefinedSymbols.Add(this); EETypeRareFlags rareFlags = 0; short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) flags |= (short)EETypeFlags.ValueTypeFlag; if (_type.IsInterface) flags |= (short)EETypeFlags.IsInterfaceFlag; if (factory.TypeSystemContext.HasLazyStaticConstructor(_type)) rareFlags = rareFlags | EETypeRareFlags.HasCctorFlag; if (rareFlags != 0) _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, (uint)rareFlags); if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) flags |= (short)EETypeFlags.OptionalFieldsFlag; dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.ModuleManagerIndirection); if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) { dataBuilder.EmitPointerReloc(factory.EETypeOptionalFields(_optionalFieldsBuilder)); } return dataBuilder.ToObjectData(); }
private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); // Todo: RelatedTypeViaIATFlag when we support cross-module EETypes // Todo: GenericVarianceFlag when we support variance // Todo: Generic Type Definition EETypes if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } objData.EmitShort((short)flags); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { bool hasVariance = false; foreach (var argVariance in _details.Variance) { if (argVariance != 0) { hasVariance = true; break; } } var builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); builder.RequirePointerAlignment(); builder.EmitShort((short)checked ((UInt16)_details.Instantiation.Length)); builder.EmitByte((byte)(hasVariance ? 1 : 0)); // TODO: general purpose padding builder.EmitByte(0); if (factory.Target.PointerSize == 8) { builder.EmitInt(0); } foreach (var typeArg in _details.Instantiation) { builder.EmitPointerReloc(factory.NecessaryTypeSymbol(typeArg)); } if (hasVariance) { foreach (var argVariance in _details.Variance) { builder.EmitByte(checked ((byte)argVariance)); } } return(builder.ToObjectData()); }
private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) { // Generic array enumerators use special variance rules recognized by the runtime flags |= (UInt16)EETypeFlags.GenericVarianceFlag; } // Todo: RelatedTypeViaIATFlag when we support cross-module EETypes // Todo: Generic Type Definition EETypes if (HasOptionalFields) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } objData.EmitShort((short)flags); }
private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) { // Generic array enumerators use special variance rules recognized by the runtime flags |= (UInt16)EETypeFlags.GenericVarianceFlag; } TypeDesc relatedType = null; if (_type.IsArray || _type.IsPointer || _type.IsByRef) { relatedType = ((ParameterizedType)_type).ParameterType; } else { relatedType = _type.BaseType; } // If the related type (base type / array element type / pointee type) is not part of this compilation group, and // the output binaries will be multi-file (not multiple object files linked together), indicate to the runtime // that it should indirect through the import address table if (relatedType != null && factory.CompilationModuleGroup.ShouldReferenceThroughImportTable(relatedType)) { flags |= (UInt16)EETypeFlags.RelatedTypeViaIATFlag; } // Todo: Generic Type Definition EETypes if (HasOptionalFields) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } objData.EmitShort((short)flags); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); // +2 for SyncBlock and EETypePtr field int totalSize = (_gcMap.Size + 2) * _target.PointerSize; // We only need to check for containsPointers because ThreadStatics are always allocated // on the GC heap (no matter what "HasGCStaticBase" says). // If that ever changes, we can assume "true" and switch this to an assert. bool containsPointers = _gcMap.NumSeries > 0; if (containsPointers) { GCDescEncoder.EncodeStandardGCDesc(ref dataBuilder, _gcMap, totalSize, 0); } Debug.Assert(dataBuilder.CountBytes == Offset); dataBuilder.EmitShort(0); // ComponentSize is always 0 short flags = 0; if (containsPointers) flags |= (short)EETypeFlags.HasPointersFlag; dataBuilder.EmitShort(flags); totalSize = Math.Max(totalSize, _target.PointerSize * 3); // minimum GC eetype size is 3 pointers dataBuilder.EmitInt(totalSize); // Related type: System.Object. This allows storing an instance of this type in an array of objects. dataBuilder.EmitPointerReloc(factory.NecessaryTypeSymbol(factory.TypeSystemContext.GetWellKnownType(WellKnownType.Object))); return dataBuilder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); bool hasPointers = NumSeries > 0; if (hasPointers) { for (int i = ((_runLengths.Length / 2) * 2) - 1; i >= 0; i--) { if (_targetPointerSize == 4) { dataBuilder.EmitInt(_runLengths[i]); } else { dataBuilder.EmitLong(_runLengths[i]); } } if (_targetPointerSize == 4) { dataBuilder.EmitInt(NumSeries); } else { dataBuilder.EmitLong(NumSeries); } } int totalSize = 0; foreach (int run in _runLengths) { totalSize += run * _targetPointerSize; } dataBuilder.EmitShort(0); // ComponentSize is always 0 if (hasPointers) dataBuilder.EmitShort(0x20); // TypeFlags.HasPointers else dataBuilder.EmitShort(0x00); totalSize = Math.Max(totalSize, _targetPointerSize * 3); // minimum GC eetype size is 3 pointers dataBuilder.EmitInt(totalSize); return dataBuilder.ToObjectData(); }
private void OutputComponentSize(ref ObjectDataBuilder objData) { if (_type.IsArray) { objData.EmitShort((short)((ArrayType)_type).ElementType.GetElementSize()); } else if (_type.IsString) { objData.EmitShort(2); } else { objData.EmitShort(0); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); if (!relocsOnly) { var entries = BuildDispatchMap(factory); objData.EmitInt(entries.Length); foreach (var entry in entries) { objData.EmitShort(entry.InterfaceIndex); objData.EmitShort(entry.InterfaceMethodSlot); objData.EmitShort(entry.ImplementationMethodSlot); } } return objData.ToObjectData(); }
void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory) { var entryCountReservation = builder.ReserveInt(); int entryCount = 0; for (int interfaceIndex = 0; interfaceIndex < _type.RuntimeInterfaces.Length; interfaceIndex++) { var interfaceType = _type.RuntimeInterfaces[interfaceIndex]; Debug.Assert(interfaceType.IsInterface); IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots; for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++) { MethodDesc declMethod = virtualSlots[interfaceMethodSlot]; var implMethod = _type.GetClosestDefType().ResolveInterfaceMethodToVirtualMethodOnType(declMethod); // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface // dispatch will walk the inheritance chain). if (implMethod != null) { builder.EmitShort(checked((short)interfaceIndex)); builder.EmitShort(checked((short)interfaceMethodSlot)); builder.EmitShort(checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod))); entryCount++; } } } builder.EmitInt(entryCountReservation, entryCount); }
private void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { if (!_constructed) { objData.EmitShort(0); objData.EmitShort(0); return; } Debug.Assert(!_type.IsGenericDefinition); int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type.GetClosestMetadataType(); while (currentTypeSlice != null) { virtualSlotCount += factory.VTable(currentTypeSlice).Slots.Count; currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked((short)virtualSlotCount)); objData.EmitShort(checked((short)_type.RuntimeInterfaces.Length)); }
private void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { if (!_constructed) { objData.EmitShort(0); objData.EmitShort(0); return; } int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type; while (currentTypeSlice != null) { List<MethodDesc> virtualSlots; factory.VirtualSlots.TryGetValue(currentTypeSlice, out virtualSlots); if (virtualSlots != null) { virtualSlotCount += virtualSlots.Count; } currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked((short)virtualSlotCount)); objData.EmitShort(checked((short)_type.RuntimeInterfaces.Length)); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); // +2 for SyncBlock and EETypePtr field int totalSize = (_gcMap.Size + 2) * _target.PointerSize; // We only need to check for containsPointers because ThreadStatics are always allocated // on the GC heap (no matter what "HasGCStaticBase" says). // If that ever changes, we can assume "true" and switch this to an assert. bool containsPointers = _gcMap.NumSeries > 0; if (containsPointers) { GCDescEncoder.EncodeStandardGCDesc(ref dataBuilder, _gcMap, totalSize, 0); } Debug.Assert(dataBuilder.CountBytes == ((ISymbolNode)this).Offset); dataBuilder.EmitShort(0); // ComponentSize is always 0 short flags = 0; if (containsPointers) flags |= (short)EETypeFlags.HasPointersFlag; dataBuilder.EmitShort(flags); totalSize = Math.Max(totalSize, _target.PointerSize * 3); // minimum GC eetype size is 3 pointers dataBuilder.EmitInt(totalSize); // This is just so that EEType::Validate doesn't blow up at runtime dataBuilder.EmitPointerReloc(this); // Related type: itself return dataBuilder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.Alignment = factory.Target.PointerSize; builder.DefinedSymbols.Add(this); // Don't bother sorting if we're not emitting the contents if (!relocsOnly) { _items.Sort((x, y) => Comparer <int> .Default.Compare((int)x.Id, (int)y.Id)); } // ReadyToRunHeader.Magic builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature)); // ReadyToRunHeader.MajorVersion builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion)); builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion)); // ReadyToRunHeader.Flags builder.EmitInt(0); // ReadyToRunHeader.NumberOfSections var sectionCountReservation = builder.ReserveShort(); // ReadyToRunHeader.EntrySize builder.EmitByte((byte)(8 + 2 * factory.Target.PointerSize)); // ReadyToRunHeader.EntryType builder.EmitByte(1); int count = 0; foreach (var item in _items) { // Skip empty entries if (item.Node.ShouldSkipEmittingObjectNode(factory)) { continue; } builder.EmitInt((int)item.Id); ModuleInfoFlags flags = 0; if (item.EndSymbol != null) { flags |= ModuleInfoFlags.HasEndPointer; } builder.EmitInt((int)flags); builder.EmitPointerReloc(item.StartSymbol); if (item.EndSymbol != null) { builder.EmitPointerReloc(item.EndSymbol); } else { builder.EmitZeroPointer(); } count++; } builder.EmitShort(sectionCountReservation, checked ((short)count)); return(builder.ToObjectData()); }
protected override void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type.GetClosestDefType(); while (currentTypeSlice != null) { if (currentTypeSlice.HasGenericDictionarySlot()) virtualSlotCount++; virtualSlotCount += factory.VTable(currentTypeSlice).Slots.Count; currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked((short)virtualSlotCount)); objData.EmitShort(checked((short)_type.RuntimeInterfaces.Length)); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.Alignment = factory.Target.PointerSize; builder.DefinedSymbols.Add(this); // Don't bother sorting if we're not emitting the contents if (!relocsOnly) _items.Sort((x, y) => Comparer<int>.Default.Compare((int)x.Id, (int)y.Id)); // ReadyToRunHeader.Magic builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature)); // ReadyToRunHeader.MajorVersion builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion)); builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion)); // ReadyToRunHeader.Flags builder.EmitInt(0); // ReadyToRunHeader.NumberOfSections var sectionCountReservation = builder.ReserveShort(); // ReadyToRunHeader.EntrySize builder.EmitByte((byte)(8 + 2 * factory.Target.PointerSize)); // ReadyToRunHeader.EntryType builder.EmitByte(1); int count = 0; foreach (var item in _items) { // Skip empty entries if (item.Node.ShouldSkipEmittingObjectNode(factory)) continue; builder.EmitInt((int)item.Id); ModuleInfoFlags flags = 0; if (item.EndSymbol != null) { flags |= ModuleInfoFlags.HasEndPointer; } builder.EmitInt((int)flags); builder.EmitPointerReloc(item.StartSymbol); if (item.EndSymbol != null) { builder.EmitPointerReloc(item.EndSymbol); } else { builder.EmitZeroPointer(); } count++; } builder.EmitShort(sectionCountReservation, checked((short)count)); return builder.ToObjectData(); }
protected virtual void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { objData.EmitShort(0); objData.EmitShort(0); }
private void OutputComponentSize(ref ObjectDataBuilder objData) { if (_type.IsArray) { int elementSize = ((ArrayType)_type).ElementType.GetElementSize(); if (elementSize >= 64 * 1024) { // TODO: Array of type 'X' cannot be created because base value type is too large. throw new TypeLoadException(); } objData.EmitShort((short)elementSize); } else if (_type.IsString) { objData.EmitShort(2); } else { objData.EmitShort(0); } }
private void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { int virtualSlotCount = 0; TypeDesc currentTypeSlice = _type; while (currentTypeSlice != null) { List<MethodDesc> virtualSlots; factory.VirtualSlots.TryGetValue(currentTypeSlice, out virtualSlots); if (virtualSlots != null) { virtualSlotCount += virtualSlots.Count; } currentTypeSlice = currentTypeSlice.BaseType; } objData.EmitShort(checked((short)virtualSlotCount)); // Todo: Number of slots of EEInterfaceInfo when we add interface support objData.EmitShort(0); }
protected virtual void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { objData.EmitShort(0); objData.EmitShort(0); }
private void OutputComponentSize(ref ObjectDataBuilder objData) { if (_type.IsArray) { int elementSize = ((ArrayType)_type).ElementType.GetElementSize(); // We validated that this will fit the short when the node was constructed. No need for nice messages. objData.EmitShort((short)checked((ushort)elementSize)); } else if (_type.IsString) { objData.EmitShort(2); } else { objData.EmitShort(0); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); if (_type.IsArray) { objData.EmitShort((short)((ArrayType)_type).ElementType.GetElementSize()); // m_ComponentSize objData.EmitShort(0x4); // m_flags: IsArray(0x4) } else if (_type.IsString) { objData.EmitShort(2); // m_ComponentSize objData.EmitShort(0); // m_flags: 0 } else { objData.EmitShort(0); // m_ComponentSize objData.EmitShort(0); // m_flags: 0 } int pointerSize = _type.Context.Target.PointerSize; int minimumObjectSize = pointerSize * 3; int objectSize; if (_type is MetadataType) { objectSize = pointerSize + ((MetadataType)_type).InstanceByteCount; // +pointerSize for SyncBlock } else if (_type is ArrayType) { objectSize = 3 * pointerSize; // SyncBlock + EETypePtr + Length int rank = ((ArrayType)_type).Rank; if (rank > 1) objectSize += 2 * _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() * rank; } else throw new NotImplementedException(); objectSize = AlignmentHelper.AlignUp(objectSize, pointerSize); objectSize = Math.Max(minimumObjectSize, objectSize); if (_type.IsString) { // If this is a string, throw away objectSize we computed so far. Strings are special. // SyncBlock + EETypePtr + length + firstChar objectSize = 2 * pointerSize + _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() + _type.Context.GetWellKnownType(WellKnownType.Char).GetElementSize(); } objData.EmitInt(objectSize); if (Type.BaseType != null) { if (_constructed) { objData.EmitPointerReloc(factory.ConstructedTypeSymbol(Type.BaseType)); } else { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(Type.BaseType)); } } else { objData.EmitZeroPointer(); } if (_constructed) { OutputVirtualSlots(ref objData, _type, _type, factory); } return objData.ToObjectData(); }
private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); // Todo: RelatedTypeViaIATFlag when we support cross-module EETypes // Todo: GenericVarianceFlag when we support variance // Todo: Generic Type Definition EETypes if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } objData.EmitShort((short)flags); }
private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) { // Generic array enumerators use special variance rules recognized by the runtime flags |= (UInt16)EETypeFlags.GenericVarianceFlag; } // Todo: RelatedTypeViaIATFlag when we support cross-module EETypes // Todo: Generic Type Definition EETypes if (HasOptionalFields) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } objData.EmitShort((short)flags); }