public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // Dependencies for this node are tracked by the method code nodes if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Ensure the native layout data has been saved, in order to get valid Vertex offsets for the signature Vertices factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeWriter = new NativeWriter(); VertexHashtable hashtable = new VertexHashtable(); Section nativeSection = nativeWriter.NewSection(); nativeSection.Place(hashtable); foreach (TypeDesc type in factory.MetadataManager.GetTypesWithConstructedEETypes()) { if (!IsEligibleToHaveATemplate(type)) { continue; } if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis) { // If the type does not have fully constructed type, don't track its dependencies. // TODO: Remove the workaround once we stop using the STS dependency analysis. IDependencyNode node = factory.MaximallyConstructableType(type); if (!node.Marked) { continue; } } // Type's native layout info NativeLayoutTemplateTypeLayoutVertexNode templateNode = factory.NativeLayout.TemplateTypeLayout(type); // If this template isn't considered necessary, don't emit it. if (!templateNode.Marked) { continue; } Vertex nativeLayout = templateNode.SavedVertex; // Hashtable Entry Vertex entry = nativeWriter.GetTuple( nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))), nativeWriter.GetUnsignedConstant((uint)nativeLayout.VertexOffset)); // Add to the hash table, hashed by the containing type's hashcode uint hashCode = (uint)type.GetHashCode(); hashtable.Append(hashCode, nativeSection.Place(entry)); } byte[] streamBytes = nativeWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Ensure the native layout blob has been saved factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); var writer = new NativeWriter(); var typeMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(typeMapHashTable); Dictionary <int, HashSet <TypeDesc> > methodsEmitted = new Dictionary <int, HashSet <TypeDesc> >(); // Get a list of all methods that have a method body and metadata from the metadata manager. foreach (var mappingEntry in factory.MetadataManager.GetMethodMapping(factory)) { MethodDesc method = mappingEntry.Entity; // The current format requires us to have an EEType for the owning type. We might want to lift this. if (!factory.MetadataManager.TypeGeneratesEEType(method.OwningType)) { continue; } // We have a method body, we have a metadata token, but we can't get an invoke stub. Bail. if (!factory.MetadataManager.IsReflectionInvokable(method)) { continue; } // Only virtual methods are interesting if (!NeedsVirtualInvokeInfo(method)) { continue; } // // When working with the ProjectN ABI, the entries in the map are based on the definition types. All // instantiations of these definition types will have the same vtable method entries. // On CoreRT, the vtable entries for each instantiated type might not necessarily exist. // Example 1: // If there's a call to Foo<string>.Method1 and a call to Foo<int>.Method2, Foo<string> will // not have Method2 in its vtable and Foo<int> will not have Method1. // Example 2: // If there's a call to Foo<string>.Method1 and a call to Foo<object>.Method2, given that both // of these instantiations share the same canonical form, Foo<__Canon> will have both method // entries, and therefore Foo<string> and Foo<object> will have both entries too. // For this reason, the entries that we write to the map in CoreRT will be based on the canonical form // of the method's containing type instead of the open type definition. // // Similarly, given that we use the open type definition for ProjectN, the slot numbers ignore dictionary // entries in the vtable, and computing the correct slot number in the presence of dictionary entries is // done at runtime. When working with the CoreRT ABI, the correct slot numbers will be written to the map, // and no adjustments will be performed at runtime. // TypeDesc containingTypeKey; if (factory.Target.Abi == TargetAbi.ProjectN) { containingTypeKey = method.OwningType.GetTypeDefinition(); } else { containingTypeKey = method.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); } HashSet <TypeDesc> cache; if (!methodsEmitted.TryGetValue(mappingEntry.MetadataHandle, out cache)) { methodsEmitted[mappingEntry.MetadataHandle] = cache = new HashSet <TypeDesc>(); } // Only one record is needed for any instantiation. if (!cache.Add(containingTypeKey)) { continue; } // Grammar of an entry in the hash table: // Virtual Method uses a normal slot // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1) + slot // OR // Generic Virtual Method // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1 + 1) int parentHierarchyDistance; MethodDesc declaringMethodForSlot = GetDeclaringVirtualMethodAndHierarchyDistance(method, out parentHierarchyDistance); Vertex vertex = null; ISymbolNode containingTypeKeyNode = factory.NecessaryTypeSymbol(containingTypeKey); NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); if (method.HasInstantiation) { vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeKeyNode)), writer.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset), writer.GetUnsignedConstant(((uint)parentHierarchyDistance << 1) + VirtualInvokeTableEntry.GenericVirtualMethod)); } else { // Get the declaring method for slot on the instantiated declaring type int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, declaringMethodForSlot, factory.Target.Abi != TargetAbi.ProjectN); Debug.Assert(slot != -1); vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeKeyNode)), writer.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)parentHierarchyDistance << 1), writer.GetUnsignedConstant((uint)slot)); } int hashCode = containingTypeKey.GetHashCode(); typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } var writer = new NativeWriter(); var fieldMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(fieldMapHashTable); foreach (var fieldMapping in factory.MetadataManager.GetFieldMapping(factory)) { FieldDesc field = fieldMapping.Entity; if (field.IsLiteral || field.HasRva) { continue; } FieldTableFlags flags; if (field.IsThreadStatic) { flags = FieldTableFlags.ThreadStatic; } else if (field.IsStatic) { flags = FieldTableFlags.Static; if (field.HasGCStaticBase) { flags |= FieldTableFlags.IsGcSection; } if (field.OwningType.HasInstantiation) { flags |= FieldTableFlags.FieldOffsetEncodedDirectly; } } else { flags = FieldTableFlags.Instance | FieldTableFlags.FieldOffsetEncodedDirectly; } if (fieldMapping.MetadataHandle != 0) { flags |= FieldTableFlags.HasMetadataHandle; } if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Universal)) { flags |= FieldTableFlags.IsUniversalCanonicalEntry; } // Grammar of a hash table entry: // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset Vertex vertex = writer.GetUnsignedConstant((uint)flags); uint declaringTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(field.OwningType)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(declaringTypeId)); if ((flags & FieldTableFlags.HasMetadataHandle) != 0) { // Only store the offset portion of the metadata handle to get better integer compression vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(fieldMapping.MetadataHandle & MetadataManager.MetadataOffsetMask))); } else { // No metadata handle means we need to store name vertex = writer.GetTuple(vertex, writer.GetStringConstant(field.Name)); } if ((flags & FieldTableFlags.IsUniversalCanonicalEntry) != 0) { // TODO: USG continue; } else { switch (flags & FieldTableFlags.StorageClass) { case FieldTableFlags.ThreadStatic: // TODO: thread statics continue; case FieldTableFlags.Static: { if (field.OwningType.HasInstantiation) { vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(field.Offset.AsInt))); } else { MetadataType metadataType = (MetadataType)field.OwningType; ISymbolNode staticsNode = field.HasGCStaticBase ? factory.TypeGCStaticsSymbol(metadataType) : factory.TypeNonGCStaticsSymbol(metadataType); if (!field.HasGCStaticBase || factory.Target.Abi == TargetAbi.ProjectN) { uint index = _externalReferences.GetIndex(staticsNode, field.Offset.AsInt); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index)); } else { Debug.Assert(field.HasGCStaticBase && factory.Target.Abi == TargetAbi.CoreRT); uint index = _externalReferences.GetIndex(staticsNode); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(field.Offset.AsInt))); } } } break; case FieldTableFlags.Instance: vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)field.Offset.AsInt)); break; } } int hashCode = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific).GetHashCode(); fieldMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Build the GVM table entries from the list of interesting GVMTableEntryNodes foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries()) { foreach (var typeGVMEntryInfo in interestingEntry.ScanForGenericVirtualMethodEntries()) { AddGenericVirtualMethodImplementation(factory, typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationMethod); } } // Ensure the native layout blob has been saved factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeFormatWriter = new NativeWriter(); VertexHashtable gvmHashtable = new VertexHashtable(); Section gvmHashtableSection = nativeFormatWriter.NewSection(); gvmHashtableSection.Place(gvmHashtable); // Emit the GVM target information entries foreach (var gvmEntry in _gvmImplemenations) { Debug.Assert(!gvmEntry.Key.OwningType.IsInterface); foreach (var implementationEntry in gvmEntry.Value) { MethodDesc callingMethod = gvmEntry.Key; TypeDesc implementationType = implementationEntry.Key; MethodDesc implementationMethod = implementationEntry.Value; uint callingTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType)); Vertex vertex = nativeFormatWriter.GetUnsignedConstant(callingTypeId); uint targetTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(targetTypeId)); var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); int hashCode = callingMethod.OwningType.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ implementationType.GetHashCode(); gvmHashtable.Append((uint)hashCode, gvmHashtableSection.Place(vertex)); } } // Zero out the dictionary so that we AV if someone tries to insert after we're done. _gvmImplemenations = null; byte[] streamBytes = nativeFormatWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } var writer = new NativeWriter(); var typeMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(typeMapHashTable); foreach (var structEntry in ((CompilerGeneratedInteropStubManager)factory.InteropStubManager).GetStructMarshallingTypes()) { // the order of data written is as follows: // 0. managed struct type // 1. struct marshalling thunk // 2. struct unmarshalling thunk // 3. struct cleanup thunk // 4. size // 5. NumFields<< 1 | HasInvalidLayout // 6 for each field // a. name // b. offset var structType = structEntry.StructType; var nativeType = structEntry.NativeStructType; Vertex thunks = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.MarshallingThunk))), writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.UnmarshallingThunk))), writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.CleanupThunk)))); uint size = (uint)nativeType.InstanceByteCount.AsInt; uint mask = (uint)(nativeType.Fields.Length << 1) | (uint)(nativeType.HasInvalidLayout ? 1 : 0); Vertex data = writer.GetTuple( thunks, writer.GetUnsignedConstant(size), writer.GetUnsignedConstant(mask) ); for (int i = 0; i < nativeType.Fields.Length; i++) { data = writer.GetTuple( data, writer.GetStringConstant(nativeType.Fields[i].Name), writer.GetUnsignedConstant((uint)nativeType.Fields[i].Offset.AsInt) ); } Vertex vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(structType))), data ); int hashCode = structType.GetHashCode(); typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolNode[] { this })); } var writer = new NativeWriter(); var typeMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(typeMapHashTable); // Get a list of all methods that have a method body and metadata from the metadata manager. foreach (var mappingEntry in factory.MetadataManager.GetMethodMapping(factory)) { MethodDesc method = mappingEntry.Entity; // The current format requires us to have an EEType for the owning type. We might want to lift this. if (!factory.MetadataManager.TypeGeneratesEEType(method.OwningType)) { continue; } // We have a method body, we have a metadata token, but we can't get an invoke stub. Bail. if (!factory.MetadataManager.IsReflectionInvokable(method)) { continue; } InvokeTableFlags flags = 0; if (method.HasInstantiation) { flags |= InvokeTableFlags.IsGenericMethod; } if (method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg()) { flags |= InvokeTableFlags.RequiresInstArg; } if (method.IsDefaultConstructor) { flags |= InvokeTableFlags.IsDefaultConstructor; } // TODO: HasVirtualInvoke if (!method.IsAbstract) { flags |= InvokeTableFlags.HasEntrypoint; } // Once we have a true multi module compilation story, we'll need to start emitting entries where this is not set. flags |= InvokeTableFlags.HasMetadataHandle; if (!factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method)) { flags |= InvokeTableFlags.NeedsParameterInterpretation; } // TODO: native signature for P/Invokes and NativeCallable methods if (method.IsRawPInvoke() || method.IsNativeCallable) { continue; } // Grammar of an entry in the hash table: // Flags + DeclaringType + MetadataHandle/NameAndSig + Entrypoint + DynamicInvokeMethod + [NumGenericArgs + GenericArgs] Vertex vertex = writer.GetUnsignedConstant((uint)flags); if ((flags & InvokeTableFlags.HasMetadataHandle) != 0) { // Only store the offset portion of the metadata handle to get better integer compression vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask))); } else { // TODO: no MD handle case } // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted. IEETypeNode owningTypeSymbol = factory.NecessaryTypeSymbol(method.OwningType); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex(owningTypeSymbol))); if ((flags & InvokeTableFlags.HasEntrypoint) != 0) { bool useUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic; vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex( factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific), useUnboxingStub)))); } // TODO: data to generate the generic dictionary with the type loader if ((flags & InvokeTableFlags.NeedsParameterInterpretation) == 0) { MethodDesc invokeStubMethod = factory.MetadataManager.GetReflectionInvokeStub(method); MethodDesc canonInvokeStubMethod = invokeStubMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); if (invokeStubMethod != canonInvokeStubMethod) { vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.FatFunctionPointer(invokeStubMethod), FatFunctionPointerConstants.Offset) << 1)); } else { vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(invokeStubMethod)) << 1)); } } if ((flags & InvokeTableFlags.IsGenericMethod) != 0) { if ((flags & InvokeTableFlags.RequiresInstArg) == 0 || (flags & InvokeTableFlags.HasEntrypoint) == 0) { VertexSequence args = new VertexSequence(); for (int i = 0; i < method.Instantiation.Length; i++) { uint argId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(method.Instantiation[i])); args.Append(writer.GetUnsignedConstant(argId)); } vertex = writer.GetTuple(vertex, args); } else { uint dictionaryId = _externalReferences.GetIndex(factory.MethodGenericDictionary(method)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(dictionaryId)); } } int hashCode = method.GetCanonMethodTarget(CanonicalFormKind.Specific).OwningType.GetHashCode(); typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Ensure the native layout blob has been saved factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); var writer = new NativeWriter(); var typeMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(typeMapHashTable); // Get a list of all methods that have a method body and metadata from the metadata manager. foreach (var mappingEntry in factory.MetadataManager.GetMethodMapping(factory)) { MethodDesc method = mappingEntry.Entity; if (!factory.MetadataManager.ShouldMethodBeInInvokeMap(method)) { continue; } bool useUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic; InvokeTableFlags flags = 0; if (method.HasInstantiation) { flags |= InvokeTableFlags.IsGenericMethod; } if (MethodRequiresInstArg(method.GetCanonMethodTarget(CanonicalFormKind.Specific), useUnboxingStub)) { flags |= InvokeTableFlags.RequiresInstArg; } if (method.IsDefaultConstructor) { flags |= InvokeTableFlags.IsDefaultConstructor; } if (ReflectionVirtualInvokeMapNode.NeedsVirtualInvokeInfo(method)) { flags |= InvokeTableFlags.HasVirtualInvoke; } if (!method.IsAbstract) { flags |= InvokeTableFlags.HasEntrypoint; } if (mappingEntry.MetadataHandle != 0) { flags |= InvokeTableFlags.HasMetadataHandle; } if (!factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method)) { flags |= InvokeTableFlags.NeedsParameterInterpretation; } if (method.IsCanonicalMethod(CanonicalFormKind.Universal)) { flags |= InvokeTableFlags.IsUniversalCanonicalEntry; } // TODO: native signature for P/Invokes and UnmanagedCallersOnly methods if (method.IsRawPInvoke() || method.IsUnmanagedCallersOnly) { continue; } // Grammar of an entry in the hash table: // Flags + DeclaringType + MetadataHandle/NameAndSig + Entrypoint + DynamicInvokeMethod + [NumGenericArgs + GenericArgs] Vertex vertex = writer.GetUnsignedConstant((uint)flags); if ((flags & InvokeTableFlags.HasMetadataHandle) != 0) { // Only store the offset portion of the metadata handle to get better integer compression vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask))); } else { var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); } // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted. IEETypeNode owningTypeSymbol = factory.NecessaryTypeSymbol(method.OwningType); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex(owningTypeSymbol))); if ((flags & InvokeTableFlags.HasEntrypoint) != 0) { vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex( factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific), useUnboxingStub)))); } if ((flags & InvokeTableFlags.NeedsParameterInterpretation) == 0) { MethodDesc canonInvokeStubMethod = factory.MetadataManager.GetCanonicalReflectionInvokeStub(method); if (canonInvokeStubMethod.IsSharedByGenericInstantiations) { vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(((uint)factory.MetadataManager.DynamicInvokeTemplateData.GetIdForMethod(canonInvokeStubMethod, factory) << 1) | 1)); } else { vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(canonInvokeStubMethod)) << 1)); } } if ((flags & InvokeTableFlags.IsGenericMethod) != 0) { if ((flags & InvokeTableFlags.IsUniversalCanonicalEntry) != 0) { var nameAndSigGenericMethod = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSigGenericMethod.SavedVertex.VertexOffset)); } else if ((flags & InvokeTableFlags.RequiresInstArg) == 0 || (flags & InvokeTableFlags.HasEntrypoint) == 0) { VertexSequence args = new VertexSequence(); for (int i = 0; i < method.Instantiation.Length; i++) { uint argId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(method.Instantiation[i])); args.Append(writer.GetUnsignedConstant(argId)); } vertex = writer.GetTuple(vertex, args); } else { uint dictionaryId = _externalReferences.GetIndex(factory.MethodGenericDictionary(method)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(dictionaryId)); } } int hashCode = method.GetCanonMethodTarget(CanonicalFormKind.Specific).OwningType.GetHashCode(); typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // Dependencies for this node are tracked by the method code nodes if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Ensure the native layout data has been saved, in order to get valid Vertex offsets for the signature Vertices factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeWriter = new NativeWriter(); VertexHashtable hashtable = new VertexHashtable(); Section nativeSection = nativeWriter.NewSection(); nativeSection.Place(hashtable); foreach (MethodDesc method in factory.MetadataManager.GetCompiledMethods()) { if (!IsMethodEligibleForTracking(method)) { continue; } // Get the method pointer vertex bool getUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic; IMethodNode methodEntryPointNode = factory.MethodEntrypoint(method, getUnboxingStub); Vertex methodPointer = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(methodEntryPointNode)); // Get native layout vertices for the declaring type ISymbolNode declaringTypeNode = factory.NecessaryTypeSymbol(method.OwningType); Vertex declaringType = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(declaringTypeNode)); // Get a vertex sequence for the method instantiation args if any VertexSequence arguments = new VertexSequence(); foreach (var arg in method.Instantiation) { ISymbolNode argNode = factory.NecessaryTypeSymbol(arg); arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode))); } // Get the name and sig of the method. // Note: the method name and signature are stored in the NativeLayoutInfo blob, not in the hashtable we build here. NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); Debug.Assert(placedNameAndSig.SavedVertex != null); Vertex placedNameAndSigOffsetSig = nativeWriter.GetOffsetSignature(placedNameAndSig.SavedVertex); // Get the vertex for the completed method signature Vertex methodSignature = nativeWriter.GetTuple(declaringType, placedNameAndSigOffsetSig, arguments); // Make the generic method entry vertex Vertex entry = nativeWriter.GetTuple(methodSignature, methodPointer); // Add to the hash table, hashed by the containing type's hashcode uint hashCode = (uint)method.OwningType.GetHashCode(); hashtable.Append(hashCode, nativeSection.Place(entry)); } byte[] streamBytes = nativeWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Build the GVM table entries from the list of interesting GVMTableEntryNodes foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries()) { foreach (var typeGVMEntryInfo in interestingEntry.ScanForInterfaceGenericVirtualMethodEntries()) { AddGenericVirtualMethodImplementation(factory, typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationType, typeGVMEntryInfo.ImplementationMethod); } } // Ensure the native layout blob has been saved factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeFormatWriter = new NativeWriter(); VertexHashtable gvmHashtable = new VertexHashtable(); Section gvmHashtableSection = nativeFormatWriter.NewSection(); gvmHashtableSection.Place(gvmHashtable); // Emit the interface slot resolution entries foreach (var gvmEntry in _interfaceGvmSlots) { Debug.Assert(gvmEntry.Key.OwningType.IsInterface); MethodDesc callingMethod = gvmEntry.Key; // Emit the method signature and containing type of the current interface method uint typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType)); var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); Vertex vertex = nativeFormatWriter.GetTuple( nativeFormatWriter.GetUnsignedConstant(typeId), nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); // Emit the method name / sig and containing type of each GVM target method for the current interface method entry vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)gvmEntry.Value.Count)); foreach (MethodDesc implementationMethod in gvmEntry.Value) { nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationMethod.OwningType)); vertex = nativeFormatWriter.GetTuple( vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset), nativeFormatWriter.GetUnsignedConstant(typeId)); // Emit the interface GVM slot details for each type that implements the interface methods { Debug.Assert(_interfaceImpls.ContainsKey(implementationMethod)); var ifaceImpls = _interfaceImpls[implementationMethod]; // First, emit how many types have method implementations for this interface method entry vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)ifaceImpls.Count)); // Emit each type that implements the interface method, and the interface signatures for the interfaces implemented by the type foreach (var currentImpl in ifaceImpls) { TypeDesc implementationType = currentImpl.Key; typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(typeId)); // Emit information on which interfaces the current method entry provides implementations for vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)currentImpl.Value.Count)); foreach (var ifaceId in currentImpl.Value) { // Emit the signature of the current interface implemented by the method Debug.Assert(((uint)ifaceId) < implementationType.RuntimeInterfaces.Length); TypeDesc currentInterface = implementationType.RuntimeInterfaces[ifaceId]; var typeSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(currentInterface)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)typeSig.SavedVertex.VertexOffset)); } } } } int hashCode = callingMethod.OwningType.GetHashCode(); gvmHashtable.Append((uint)hashCode, gvmHashtableSection.Place(vertex)); } // Zero out the dictionary so that we AV if someone tries to insert after we're done. _interfaceGvmSlots = null; byte[] streamBytes = nativeFormatWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } NativeWriter writer = new NativeWriter(); VertexHashtable hashtable = new VertexHashtable(); Section section = writer.NewSection(); section.Place(hashtable); foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes()) { if (!type.HasInstantiation || type.IsCanonicalSubtype(CanonicalFormKind.Any) || type.IsGenericDefinition) { continue; } MetadataType metadataType = type as MetadataType; if (metadataType == null) { continue; } VertexBag bag = new VertexBag(); if (metadataType.GCStaticFieldSize.AsInt > 0) { ISymbolNode gcStaticIndirection = factory.Indirection(factory.TypeGCStaticsSymbol(metadataType)); bag.AppendUnsigned(BagElementKind.GcStaticData, _nativeStaticsReferences.GetIndex(gcStaticIndirection)); } if (metadataType.NonGCStaticFieldSize.AsInt > 0 || factory.TypeSystemContext.HasLazyStaticConstructor(type)) { ISymbolNode nonGCStaticIndirection = factory.Indirection(factory.TypeNonGCStaticsSymbol(metadataType)); bag.AppendUnsigned(BagElementKind.NonGcStaticData, _nativeStaticsReferences.GetIndex(nonGCStaticIndirection)); } if (metadataType.ThreadStaticFieldSize.AsInt > 0) { if (factory.Target.Abi == TargetAbi.ProjectN) { UtcNodeFactory utcFactory = (UtcNodeFactory)factory; ISymbolNode threadStaticIndexIndirection = utcFactory.TypeThreadStaticsIndexSymbol(metadataType); bag.AppendUnsigned(BagElementKind.ThreadStaticIndex, _nativeStaticsReferences.GetIndex(threadStaticIndexIndirection)); ISymbolNode threadStaticOffsetIndirection = utcFactory.TypeThreadStaticsOffsetSymbol(metadataType); bag.AppendUnsigned(BagElementKind.ThreadStaticOffset, _nativeStaticsReferences.GetIndex(threadStaticOffsetIndirection)); } // TODO: TLS for CoreRT } if (bag.ElementsCount > 0) { uint typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(type)); Vertex staticsInfo = writer.GetTuple(writer.GetUnsignedConstant(typeId), bag); hashtable.Append((uint)type.GetHashCode(), section.Place(staticsInfo)); } } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolNode[] { this })); } var writer = new NativeWriter(); var fieldMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(fieldMapHashTable); foreach (var fieldMapping in factory.MetadataManager.GetFieldMapping()) { FieldDesc field = fieldMapping.Entity; if (field.IsLiteral || field.HasRva) { continue; } FieldTableFlags flags; if (field.IsThreadStatic) { flags = FieldTableFlags.ThreadStatic; } else if (field.IsStatic) { flags = FieldTableFlags.Static; if (field.HasGCStaticBase) { flags |= FieldTableFlags.IsGcSection; } } else { flags = FieldTableFlags.Instance; } // TODO: support emitting field info without a handle for generics in multifile flags |= FieldTableFlags.HasMetadataHandle; if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Universal)) { flags |= FieldTableFlags.IsUniversalCanonicalEntry; } // Grammar of a hash table entry: // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset Vertex vertex = writer.GetUnsignedConstant((uint)flags); uint declaringTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(field.OwningType)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(declaringTypeId)); if ((flags & FieldTableFlags.HasMetadataHandle) != 0) { // Only store the offset portion of the metadata handle to get better integer compression vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(fieldMapping.MetadataHandle & MetadataManager.MetadataOffsetMask))); } else { throw new NotImplementedException(); } if ((flags & FieldTableFlags.IsUniversalCanonicalEntry) != 0) { throw new NotImplementedException(); } else { switch (flags & FieldTableFlags.StorageClass) { case FieldTableFlags.ThreadStatic: case FieldTableFlags.Static: // TODO: statics and thread statics continue; case FieldTableFlags.Instance: vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)field.Offset)); break; } } int hashCode = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific).GetHashCode(); fieldMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } MemoryStream ms = new MemoryStream(); writer.Save(ms); byte[] hashTableBytes = ms.ToArray(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolNode[] { this })); } // Ensure the native layout data has been saved, in order to get valid Vertex offsets for the signature Vertices factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeWriter = new NativeWriter(); VertexHashtable hashtable = new VertexHashtable(); Section nativeSection = nativeWriter.NewSection(); nativeSection.Place(hashtable); foreach (var dictionaryNode in factory.MetadataManager.GetCompiledGenericDictionaries()) { MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode; if (methodDictionary == null) { continue; } MethodDesc method = methodDictionary.OwningMethod; Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any)); Vertex fullMethodSignature; { // Method's containing type IEETypeNode containingTypeNode = factory.NecessaryTypeSymbol(method.OwningType); Vertex containingType = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeNode)); // Method's instantiation arguments VertexSequence arguments = new VertexSequence(); for (int i = 0; i < method.Instantiation.Length; i++) { IEETypeNode argNode = factory.NecessaryTypeSymbol(method.Instantiation[i]); arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode))); } // Method name and signature NativeLayoutVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); NativeLayoutSavedVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); Vertex placedNameAndSigVertexOffset = nativeWriter.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset); fullMethodSignature = nativeWriter.GetTuple(containingType, placedNameAndSigVertexOffset, arguments); } // Method's dictionary pointer Vertex dictionaryVertex = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(dictionaryNode)); Vertex entry = nativeWriter.GetTuple(dictionaryVertex, fullMethodSignature); hashtable.Append((uint)method.GetHashCode(), nativeSection.Place(entry)); } byte[] streamBytes = nativeWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolNode[] { this, _endSymbol })); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } var writer = new NativeWriter(); var typeMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(typeMapHashTable); foreach (var structType in factory.MetadataManager.GetTypesWithStructMarshalling()) { // the order of data written is as follows: // managed struct type // NumFields<< 2 | (HasInvalidLayout ? (2:0)) | (MarshallingRequired ? (1:0)) // If MarshallingRequired: // size // struct marshalling thunk // struct unmarshalling thunk // struct cleanup thunk // For each field field: // name // offset var nativeType = _interopStateManager.GetStructMarshallingNativeType(structType); Vertex marshallingData = null; if (MarshalHelpers.IsStructMarshallingRequired(structType)) { Vertex thunks = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(_interopStateManager.GetStructMarshallingManagedToNativeThunk(structType)))), writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(_interopStateManager.GetStructMarshallingNativeToManagedThunk(structType)))), writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(_interopStateManager.GetStructMarshallingCleanupThunk(structType))))); uint size = (uint)nativeType.InstanceFieldSize.AsInt; marshallingData = writer.GetTuple(writer.GetUnsignedConstant(size), thunks); } Vertex fieldOffsetData = null; for (int i = 0; i < nativeType.Fields.Length; i++) { var row = writer.GetTuple( writer.GetStringConstant(nativeType.Fields[i].Name), writer.GetUnsignedConstant((uint)nativeType.Fields[i].Offset.AsInt) ); fieldOffsetData = (fieldOffsetData != null) ? writer.GetTuple(fieldOffsetData, row) : row; } uint mask = (uint)((marshallingData != null) ? InteropDataConstants.HasMarshallers : 0) | (uint)(nativeType.HasInvalidLayout ? InteropDataConstants.HasInvalidLayout : 0) | (uint)(nativeType.Fields.Length << InteropDataConstants.FieldCountShift); Vertex data = writer.GetUnsignedConstant(mask); if (marshallingData != null) { data = writer.GetTuple(data, marshallingData); } if (fieldOffsetData != null) { data = writer.GetTuple(data, fieldOffsetData); } Vertex vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(structType))), data ); int hashCode = structType.GetHashCode(); typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }