Exemplo n.º 1
0
        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);

            foreach (var delegateEntry in factory.MetadataManager.DelegateMarshalingThunks)
            {
                Internal.TypeSystem.TypeDesc delegateType = delegateEntry.Value.DelegateType;
                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(delegateType))),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(delegateEntry.Value)))
                    );

                int hashCode = delegateType.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 }));
        }
Exemplo n.º 2
0
        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)
                {
                    // If the type does not have fully constructed type, don't emit it.
                    // TODO: Remove the workaround once we stop using the STS dependency analysis.
                    if (!factory.ConstructedTypeSymbol(type).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 }));
        }
Exemplo n.º 3
0
        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.PreinitializationManager.HasLazyStaticConstructor(type))
                {
                    ISymbolNode nonGCStaticIndirection = factory.Indirection(factory.TypeNonGCStaticsSymbol(metadataType));
                    bag.AppendUnsigned(BagElementKind.NonGcStaticData, _nativeStaticsReferences.GetIndex(nonGCStaticIndirection));
                }
                if (metadataType.ThreadGcStaticFieldSize.AsInt > 0)
                {
                    ISymbolNode threadStaticsIndirection = factory.Indirection(factory.TypeThreadStaticIndex(metadataType));
                    bag.AppendUnsigned(BagElementKind.ThreadStaticIndex, _nativeStaticsReferences.GetIndex(threadStaticsIndirection));
                }

                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 }));
        }
Exemplo n.º 4
0
        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 }));
            }

            NativeWriter    nativeWriter  = new NativeWriter();
            VertexHashtable hashtable     = new VertexHashtable();
            Section         nativeSection = nativeWriter.NewSection();

            nativeSection.Place(hashtable);

            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                // If this is an instantiated non-canonical generic type, add it to the generic instantiations hashtable
                if (!type.HasInstantiation || type.IsGenericDefinition || type.IsCanonicalSubtype(CanonicalFormKind.Any))
                {
                    continue;
                }

                var    typeSymbol      = factory.NecessaryTypeSymbol(type);
                uint   instantiationId = _externalReferences.GetIndex(typeSymbol);
                Vertex hashtableEntry  = nativeWriter.GetUnsignedConstant(instantiationId);

                hashtable.Append((uint)type.GetHashCode(), nativeSection.Place(hashtableEntry));
            }

            byte[] streamBytes = nativeWriter.Save();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolNode[] { this, _endSymbol }));
        }
        /// <summary>
        /// Builds a native hashtable containing data about each manifest resource
        /// </summary>
        /// <returns></returns>
        private byte[] GenerateIndexBlob(NodeFactory factory)
        {
            NativeWriter    nativeWriter          = new NativeWriter();
            Section         indexHashtableSection = nativeWriter.NewSection();
            VertexHashtable indexHashtable        = new VertexHashtable();

            indexHashtableSection.Place(indexHashtable);

            // Build a table with a tuple of Assembly Full Name, Resource Name, Offset within the resource data blob, Length
            // for each resource.
            // This generates a hashtable for the convenience of managed code since there's
            // a reader for VertexHashtable, but not for VertexSequence.

            foreach (ResourceIndexData indexData in _resourceDataNode.GetOrCreateIndexData(factory))
            {
                Vertex asmName      = nativeWriter.GetStringConstant(indexData.AssemblyName);
                Vertex resourceName = nativeWriter.GetStringConstant(indexData.ResourceName);
                Vertex offsetVertex = nativeWriter.GetUnsignedConstant((uint)indexData.NativeOffset);
                Vertex lengthVertex = nativeWriter.GetUnsignedConstant((uint)indexData.Length);

                Vertex indexVertex = nativeWriter.GetTuple(asmName, resourceName);
                indexVertex = nativeWriter.GetTuple(indexVertex, offsetVertex);
                indexVertex = nativeWriter.GetTuple(indexVertex, lengthVertex);

                int hashCode = TypeHashingAlgorithms.ComputeNameHashCode(indexData.AssemblyName);
                indexHashtable.Append((uint)hashCode, indexHashtableSection.Place(indexVertex));
            }

            byte[] blob = nativeWriter.Save();
            _endSymbol.SetSymbolOffset(blob.Length);
            return(blob);
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            PgoValueEmitter pgoEmitter      = new PgoValueEmitter(_factory.CompilationModuleGroup, _symbolNodeFactory, true);
            NativeWriter    hashtableWriter = new NativeWriter();

            Section         hashtableSection = hashtableWriter.NewSection();
            VertexHashtable vertexHashtable  = new VertexHashtable();

            hashtableSection.Place(vertexHashtable);

            Dictionary <byte[], BlobVertex> uniqueInstrumentationData = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            foreach (MethodDesc method in _instrumentationDataMethods)
            {
                pgoEmitter.Clear();
                PgoProcessor.EncodePgoData(_profileDataManager[method].SchemaData, pgoEmitter, false);

                // In composite R2R format, always enforce owning type to let us share generic instantiations among modules
                EcmaMethod  typicalMethod = (EcmaMethod)method.GetTypicalMethodDefinition();
                ModuleToken moduleToken   = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);

                ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
                signatureBuilder.EmitMethodSignature(
                    new MethodWithToken(method, moduleToken, constrainedType: null, unboxing: false, context: null),
                    enforceDefEncoding: true,
                    enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module),
                    factory.SignatureContext,
                    isInstantiatingStub: false);
                byte[]     signature     = signatureBuilder.ToArray();
                BlobVertex signatureBlob = new BlobVertex(signature);

                byte[]     encodedInstrumentationData = pgoEmitter.ToByteArray();
                BlobVertex instrumentationDataBlob    = null;
                if (!uniqueInstrumentationData.TryGetValue(encodedInstrumentationData, out instrumentationDataBlob))
                {
                    instrumentationDataBlob = new BlobVertex(encodedInstrumentationData);
                    hashtableSection.Place(instrumentationDataBlob);
                    uniqueInstrumentationData.Add(encodedInstrumentationData, instrumentationDataBlob);
                }

                PgoInstrumentedDataWithSignatureBlobVertex pgoDataVertex = new PgoInstrumentedDataWithSignatureBlobVertex(signatureBlob, 0, instrumentationDataBlob);
                hashtableSection.Place(pgoDataVertex);
                vertexHashtable.Append(unchecked ((uint)ReadyToRunHashCode.MethodHashCode(method)), pgoDataVertex);
            }

            MemoryStream hashtableContent = new MemoryStream();

            hashtableWriter.Save(hashtableContent);
            return(new ObjectData(
                       data: hashtableContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Exemplo n.º 7
0
        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);

            foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping())
            {
                if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity))
                {
                    continue;
                }

                // We are looking for any EEType - constructed or not, it has to be in the mapping
                // table so that we can map it to metadata.
                EETypeNode node = null;

                if (!mappingEntry.Entity.IsGenericDefinition)
                {
                    node = factory.ConstructedTypeSymbol(mappingEntry.Entity) as EETypeNode;
                }

                if (node == null || !node.Marked)
                {
                    // This might have been a typeof() expression.
                    node = factory.NecessaryTypeSymbol(mappingEntry.Entity) as EETypeNode;
                }

                if (node.Marked)
                {
                    Vertex vertex = writer.GetTuple(
                        writer.GetUnsignedConstant(_externalReferences.GetIndex(node)),
                        writer.GetUnsignedConstant((uint)mappingEntry.MetadataHandle)
                        );

                    int hashCode = node.Type.GetHashCode();
                    typeMapHashTable.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 }));
        }
Exemplo n.º 8
0
        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 reflectionBlockTypeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();

            hashTableSection.Place(reflectionBlockTypeMapHashTable);

            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                if (!type.IsTypeDefinition)
                {
                    continue;
                }

                var mdType = type as MetadataType;
                if (mdType == null)
                {
                    continue;
                }

                if (!factory.MetadataManager.IsReflectionBlocked(mdType))
                {
                    continue;
                }

                if (!factory.CompilationModuleGroup.ContainsType(mdType))
                {
                    continue;
                }

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode typeSymbol = factory.NecessaryTypeSymbol(type);

                Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(typeSymbol));

                int hashCode = typeSymbol.Type.GetHashCode();
                reflectionBlockTypeMapHashTable.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 }));
        }
Exemplo n.º 9
0
        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 (!IsEligibleToBeATemplate(method))
                {
                    continue;
                }

                var methodEntryNode = factory.NativeLayout.TemplateMethodEntry(method);

                if (!methodEntryNode.Marked)
                {
                    continue;
                }

                // Method entry
                Vertex methodEntry = methodEntryNode.SavedVertex;

                // Method's native layout info
                Vertex nativeLayout = factory.NativeLayout.TemplateMethodLayout(method).SavedVertex;

                // Hashtable Entry
                Vertex entry = nativeWriter.GetTuple(
                    nativeWriter.GetUnsignedConstant((uint)methodEntry.VertexOffset),
                    nativeWriter.GetUnsignedConstant((uint)nativeLayout.VertexOffset));

                // Add to the hash table, hashed by the containing type's hashcode
                uint hashCode = (uint)method.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 }));
        }
Exemplo n.º 10
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            NativeWriter hashtableWriter = new NativeWriter();

            Section         hashtableSection = hashtableWriter.NewSection();
            VertexHashtable vertexHashtable  = new VertexHashtable();

            hashtableSection.Place(vertexHashtable);

            Dictionary <byte[], BlobVertex> uniqueFixups     = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);
            Dictionary <byte[], BlobVertex> uniqueSignatures = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            foreach (MethodWithGCInfo method in factory.EnumerateCompiledMethods(null, CompiledMethodCategory.Instantiated))
            {
                Debug.Assert(method.Method.HasInstantiation || method.Method.OwningType.HasInstantiation);

                int methodIndex = factory.RuntimeFunctionsTable.GetIndex(method);

                ArraySignatureBuilder signatureBuilder = BuildSignatureForMethod(method, factory);
                byte[]     signature = signatureBuilder.ToArray();
                BlobVertex signatureBlob;
                if (!uniqueSignatures.TryGetValue(signature, out signatureBlob))
                {
                    signatureBlob = new BlobVertex(signature);
                    uniqueSignatures.Add(signature, signatureBlob);
                }

                byte[]     fixup     = method.GetFixupBlob(factory);
                BlobVertex fixupBlob = null;
                if (fixup != null && !uniqueFixups.TryGetValue(fixup, out fixupBlob))
                {
                    fixupBlob = new BlobVertex(fixup);
                    uniqueFixups.Add(fixup, fixupBlob);
                }

                EntryPointVertex entryPointVertex = new EntryPointWithBlobVertex((uint)methodIndex, fixupBlob, signatureBlob);
                hashtableSection.Place(entryPointVertex);
                vertexHashtable.Append(unchecked ((uint)ReadyToRunHashCode.MethodHashCode(method.Method)), entryPointVertex);
            }

            MemoryStream hashtableContent = new MemoryStream();

            hashtableWriter.Save(hashtableContent);
            return(new ObjectData(
                       data: hashtableContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Exemplo n.º 11
0
        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);

            foreach (var node in factory.MetadataManager.GetCctorContextMapping())
            {
                MetadataType type = node.Type;

                Debug.Assert(factory.TypeSystemContext.HasLazyStaticConstructor(type));

                // If this type doesn't generate an EEType in the current compilation, don't report it in the table.
                // If nobody can get to the EEType, they can't ask to run the cctor. We don't need to force generate it.
                if (!factory.MetadataManager.TypeGeneratesEEType(type))
                {
                    continue;
                }

                // Hash table is hashed by the hashcode of the owning type.
                // Each entry has: the EEType of the type, followed by the non-GC static base.
                // The non-GC static base is prefixed by the class constructor context.

                // Unfortunately we need to adjust for the cctor context just so that we can subtract it again at runtime...
                int delta = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.TypeSystemContext.Target, type);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(node, delta))
                    );

                int hashCode = type.GetHashCode();
                typeMapHashTable.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 }));
        }
Exemplo n.º 12
0
        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 defaultConstructorHashtable = new VertexHashtable();

            Section defaultConstructorHashtableSection = writer.NewSection();

            defaultConstructorHashtableSection.Place(defaultConstructorHashtable);

            foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                MethodDesc defaultCtor = type.GetDefaultConstructor();
                if (defaultCtor == null)
                {
                    continue;
                }

                // We only place default constructors of reflection-blocked types in this table.
                // At runtime, the type loader will search both this table and the invoke map
                // for default constructor info. If the ctor is reflectable, we would have
                // expected dataflow analysis to ensure there's a reflectable method for it.
                // If we don't find a reflectable method for the ctor of a non-blocked type
                // there would have to be a dataflow analysis warning.
                if (!factory.MetadataManager.IsReflectionBlocked(defaultCtor))
                {
                    continue;
                }

                defaultCtor = defaultCtor.GetCanonMethodTarget(CanonicalFormKind.Specific);

                ISymbolNode typeNode        = factory.NecessaryTypeSymbol(type);
                ISymbolNode defaultCtorNode = factory.MethodEntrypoint(defaultCtor, false);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(typeNode)),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(defaultCtorNode)));

                int hashCode = type.GetHashCode();
                defaultConstructorHashtable.Append((uint)hashCode, defaultConstructorHashtableSection.Place(vertex));
            }

            byte[] hashTableBytes = writer.Save();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }));
        }
Exemplo n.º 13
0
        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);

            foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping())
            {
                if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity))
                {
                    continue;
                }

                // Types that don't have EETypes don't need mapping table entries because there's no risk of them
                // not unifying to the same System.Type at runtime.
                if (!factory.MetadataManager.TypeGeneratesEEType(mappingEntry.Entity))
                {
                    continue;
                }

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode typeSymbol = factory.NecessaryTypeSymbol(mappingEntry.Entity);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(typeSymbol)),
                    writer.GetUnsignedConstant((uint)mappingEntry.MetadataHandle)
                    );

                int hashCode = typeSymbol.Type.GetHashCode();
                typeMapHashTable.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 }));
        }
Exemplo n.º 14
0
        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 type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                if (!type.IsSzArray)
                {
                    continue;
                }

                var arrayType = (ArrayType)type;

                // This optimization is not compatible with canInlineTypeCheck on JIT/EE interface returning
                // CORINFO_INLINE_TYPECHECK_PASS unconditionally.
                //
                // If we're generating a template for this type, we can skip generating the hashtable entry
                // since the type loader can just create this type at runtime if something needs it. It's
                // okay to have multiple EETypes for the same array type.
                // var canonArrayType = arrayType.ConvertToCanonForm(CanonicalFormKind.Specific);
                // if (arrayType != canonArrayType && factory.NativeLayout.TemplateTypeLayout(canonArrayType).Marked)
                //     continue;

                // Look at the constructed type symbol. If a constructed type wasn't emitted, then the array map entry isn't valid for use
                IEETypeNode arrayTypeSymbol = factory.ConstructedTypeSymbol(arrayType);

                Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));

                int hashCode = arrayType.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)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            PgoValueEmitter pgoEmitter      = new PgoValueEmitter(_factory.CompilationModuleGroup, _symbolNodeFactory, true);
            NativeWriter    hashtableWriter = new NativeWriter();

            Section         hashtableSection = hashtableWriter.NewSection();
            VertexHashtable vertexHashtable  = new VertexHashtable();

            hashtableSection.Place(vertexHashtable);

            Dictionary <byte[], BlobVertex> uniqueInstrumentationData = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            foreach (MethodDesc method in _instrumentationDataMethods)
            {
                pgoEmitter.Clear();
                PgoProcessor.EncodePgoData(CorInfoImpl.ConvertTypeHandleHistogramsToCompactTypeHistogramFormat(_profileDataManager[method].SchemaData, factory.CompilationModuleGroup), pgoEmitter, false);

                byte[]     signature     = InstanceEntryPointTableNode.BuildSignatureForMethodDefinedInModule(method, factory);
                BlobVertex signatureBlob = new BlobVertex(signature);

                byte[]     encodedInstrumentationData = pgoEmitter.ToByteArray();
                BlobVertex instrumentationDataBlob    = null;
                if (!uniqueInstrumentationData.TryGetValue(encodedInstrumentationData, out instrumentationDataBlob))
                {
                    instrumentationDataBlob = new BlobVertex(encodedInstrumentationData);
                    hashtableSection.Place(instrumentationDataBlob);
                    uniqueInstrumentationData.Add(encodedInstrumentationData, instrumentationDataBlob);
                }

                PgoInstrumentedDataWithSignatureBlobVertex pgoDataVertex = new PgoInstrumentedDataWithSignatureBlobVertex(signatureBlob, 0, instrumentationDataBlob);
                hashtableSection.Place(pgoDataVertex);
                vertexHashtable.Append(unchecked ((uint)ReadyToRunHashCode.MethodHashCode(method)), pgoDataVertex);
            }

            MemoryStream hashtableContent = new MemoryStream();

            hashtableWriter.Save(hashtableContent);
            return(new ObjectData(
                       data: hashtableContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Exemplo n.º 16
0
        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);

            foreach (var node in factory.MetadataManager.GetCctorContextMapping())
            {
                MetadataType type = node.Type;

                Debug.Assert(factory.TypeSystemContext.HasLazyStaticConstructor(type));

                // If this type doesn't generate an EEType in the current compilation, don't report it in the table.
                // If nobody can get to the EEType, they can't ask to run the cctor. We don't need to force generate it.
                if (!factory.MetadataManager.TypeGeneratesEEType(type))
                    continue;

                // Hash table is hashed by the hashcode of the owning type.
                // Each entry has: the EEType of the type, followed by the non-GC static base.
                // The non-GC static base is prefixed by the class constructor context.

                // Unfortunately we need to adjust for the cctor context just so that we can subtract it again at runtime...
                int delta = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.TypeSystemContext.Target, type);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(node, delta))
                    );

                int hashCode = type.GetHashCode();
                typeMapHashTable.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 });
        }
Exemplo n.º 17
0
        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 arrayType in factory.MetadataManager.GetArrayTypeMapping())
            {
                if (!arrayType.IsSzArray)
                {
                    continue;
                }

                if (!factory.MetadataManager.TypeGeneratesEEType(arrayType))
                {
                    continue;
                }

                if (!arrayType.ElementType.IsValueType)
                {
                    continue;
                }

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode arrayTypeSymbol = factory.NecessaryTypeSymbol(arrayType);

                Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));

                int hashCode = arrayType.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 }));
        }
Exemplo n.º 18
0
        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 node in factory.MetadataManager.GetCctorContextMapping())
            {
                MetadataType type = node.Type;

                Debug.Assert(factory.PreinitializationManager.HasLazyStaticConstructor(type));

                // If this type doesn't generate an MethodTable in the current compilation, don't report it in the table.
                // If nobody can get to the MethodTable, they can't ask to run the cctor. We don't need to force generate it.
                if (!factory.MetadataManager.TypeGeneratesEEType(type))
                {
                    continue;
                }

                // Hash table is hashed by the hashcode of the owning type.
                // Each entry has: the MethodTable of the type, followed by the non-GC static base.
                // The non-GC static base is prefixed by the class constructor context.
                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(node))
                    );

                int hashCode = type.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 }));
        }
Exemplo n.º 19
0
        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 type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                if (!type.IsSzArray)
                {
                    continue;
                }

                var arrayType = (ArrayType)type;

                if (!arrayType.ElementType.IsValueType)
                {
                    continue;
                }

                // Look at the constructed type symbol. If a constructed type wasn't emitted, then the array map entry isn't valid for use
                IEETypeNode arrayTypeSymbol = factory.ConstructedTypeSymbol(arrayType);

                Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));

                int hashCode = arrayType.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 }));
        }
Exemplo n.º 20
0
        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);

            foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping())
            {
                if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity))
                    continue;

                // Types that don't have EETypes don't need mapping table entries because there's no risk of them
                // not unifying to the same System.Type at runtime.
                if (!factory.MetadataManager.TypeGeneratesEEType(mappingEntry.Entity))
                    continue;
                
                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode typeSymbol = factory.NecessaryTypeSymbol(mappingEntry.Entity);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(typeSymbol)),
                    writer.GetUnsignedConstant((uint)mappingEntry.MetadataHandle)
                    );

                int hashCode = typeSymbol.Type.GetHashCode();
                typeMapHashTable.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 });
        }
Exemplo n.º 21
0
        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 defaultConstructorHashtable = new VertexHashtable();

            Section defaultConstructorHashtableSection = writer.NewSection();

            defaultConstructorHashtableSection.Place(defaultConstructorHashtable);

            foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                MethodDesc defaultCtor = type.GetDefaultConstructor();
                if (defaultCtor == null)
                {
                    continue;
                }

                defaultCtor = defaultCtor.GetCanonMethodTarget(CanonicalFormKind.Specific);

                ISymbolNode typeNode        = factory.NecessaryTypeSymbol(type);
                ISymbolNode defaultCtorNode = factory.MethodEntrypoint(defaultCtor, false);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(typeNode)),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(defaultCtorNode)));

                int hashCode = type.GetHashCode();
                defaultConstructorHashtable.Append((uint)hashCode, defaultConstructorHashtableSection.Place(vertex));
            }

            byte[] hashTableBytes = writer.Save();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }));
        }
Exemplo n.º 22
0
        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    nativeWriter  = new NativeWriter();
            VertexHashtable hashtable     = new VertexHashtable();
            Section         nativeSection = nativeWriter.NewSection();

            nativeSection.Place(hashtable);

            // We go over constructed EETypes only. The places that need to consult this hashtable at runtime
            // all need constructed EETypes. Placing unconstructed EETypes into this hashtable could make us
            // accidentally satisfy e.g. MakeGenericType for something that was only used in a cast. Those
            // should throw MissingRuntimeArtifact instead.
            //
            // We already make sure "necessary" EETypes that could potentially be loaded at runtime through
            // the dynamic type loader get upgraded to constructed EETypes at AOT compile time.
            foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                // If this is an instantiated non-canonical generic type, add it to the generic instantiations hashtable
                if (!type.HasInstantiation || type.IsGenericDefinition || type.IsCanonicalSubtype(CanonicalFormKind.Any))
                {
                    continue;
                }

                var    typeSymbol      = factory.NecessaryTypeSymbol(type);
                uint   instantiationId = _externalReferences.GetIndex(typeSymbol);
                Vertex hashtableEntry  = nativeWriter.GetUnsignedConstant(instantiationId);

                hashtable.Append((uint)type.GetHashCode(), nativeSection.Place(hashtableEntry));
            }

            byte[] streamBytes = nativeWriter.Save();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }));
        }
Exemplo n.º 23
0
        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);

            foreach (var arrayType in factory.MetadataManager.GetArrayTypeMapping())
            {
                if (!arrayType.IsSzArray)
                    continue;

                if (!factory.MetadataManager.TypeGeneratesEEType(arrayType))
                    continue;

                // TODO: This should only be emitted for arrays of value types. The type loader builds everything else.

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode arrayTypeSymbol = factory.NecessaryTypeSymbol(arrayType);

                Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));

                int hashCode = arrayType.GetHashCode();
                typeMapHashTable.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 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 }));
        }
Exemplo n.º 25
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory;
            NativeWriter hashtableWriter            = new NativeWriter();

            Section         hashtableSection = hashtableWriter.NewSection();
            VertexHashtable vertexHashtable  = new VertexHashtable();

            hashtableSection.Place(vertexHashtable);

            Dictionary <byte[], BlobVertex> uniqueFixups     = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);
            Dictionary <byte[], BlobVertex> uniqueSignatures = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            foreach (MethodWithGCInfo method in r2rFactory.EnumerateCompiledMethods())
            {
                if (method.Method.HasInstantiation || method.Method.OwningType.HasInstantiation)
                {
                    int methodIndex = r2rFactory.RuntimeFunctionsTable.GetIndex(method);

                    bool        enforceOwningType = false;
                    ModuleToken moduleToken       = method.SignatureContext.GetModuleTokenForMethod(method.Method.GetTypicalMethodDefinition());
                    if (moduleToken.Module != r2rFactory.InputModuleContext.GlobalContext)
                    {
                        enforceOwningType = true;
                    }

                    ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
                    signatureBuilder.EmitMethodSignature(
                        new MethodWithToken(method.Method, moduleToken, constrainedType: null),
                        enforceDefEncoding: true,
                        enforceOwningType,
                        method.SignatureContext,
                        isUnboxingStub: false,
                        isInstantiatingStub: false);
                    byte[]     signature = signatureBuilder.ToArray();
                    BlobVertex signatureBlob;
                    if (!uniqueSignatures.TryGetValue(signature, out signatureBlob))
                    {
                        signatureBlob = new BlobVertex(signature);
                        hashtableSection.Place(signatureBlob);
                        uniqueSignatures.Add(signature, signatureBlob);
                    }

                    byte[]     fixup     = method.GetFixupBlob(factory);
                    BlobVertex fixupBlob = null;
                    if (fixup != null && !uniqueFixups.TryGetValue(fixup, out fixupBlob))
                    {
                        fixupBlob = new BlobVertex(fixup);
                        hashtableSection.Place(fixupBlob);
                        uniqueFixups.Add(fixup, fixupBlob);
                    }

                    EntryPointVertex entryPointVertex = new EntryPointWithBlobVertex((uint)methodIndex, fixupBlob, signatureBlob);
                    hashtableSection.Place(entryPointVertex);
                    vertexHashtable.Append(unchecked ((uint)ReadyToRunHashCode.MethodHashCode(method.Method)), entryPointVertex);
                }
            }

            MemoryStream hashtableContent = new MemoryStream();

            hashtableWriter.Save(hashtableContent);
            return(new ObjectData(
                       data: hashtableContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Exemplo n.º 26
0
        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 }));
            }

            Dictionary <EcmaMethod, HashSet <EcmaMethod> > inlineeToInliners = new Dictionary <EcmaMethod, HashSet <EcmaMethod> >();

            // Build a map from inlinee to the list of inliners
            // We are only interested in the generic definitions of these.
            foreach (MethodWithGCInfo methodNode in factory.EnumerateCompiledMethods())
            {
                MethodDesc[] inlinees          = methodNode.InlinedMethods;
                MethodDesc   inliner           = methodNode.Method;
                MethodDesc   inlinerDefinition = inliner.GetTypicalMethodDefinition();

                foreach (MethodDesc inlinee in inlinees)
                {
                    MethodDesc inlineeDefinition = inlinee.GetTypicalMethodDefinition();
                    if (!(inlineeDefinition is EcmaMethod ecmaInlineeDefinition))
                    {
                        // We don't record non-ECMA methods because they don't have tokens that
                        // diagnostic tools could reason about anyway.
                        continue;
                    }

                    if (!inlineeToInliners.TryGetValue(ecmaInlineeDefinition, out HashSet <EcmaMethod> inliners))
                    {
                        inliners = new HashSet <EcmaMethod>();
                        inlineeToInliners.Add(ecmaInlineeDefinition, inliners);
                    }
                    inliners.Add((EcmaMethod)inlinerDefinition);
                }
            }

            // Serialize the map as a hash table
            NativeWriter writer  = new NativeWriter();
            Section      section = writer.NewSection();

            VertexHashtable hashtable = new VertexHashtable();

            section.Place(hashtable);

            foreach (var inlineeWithInliners in inlineeToInliners)
            {
                EcmaMethod inlinee    = inlineeWithInliners.Key;
                int        inlineeRid = MetadataTokens.GetRowNumber(inlinee.Handle);
                int        hashCode   = ReadyToRunHashCode.ModuleNameHashCode(inlinee.Module);
                hashCode ^= inlineeRid;

                // Format of the sequence:
                // Inlinee RID with flag in the lowest bit
                // - if flag is set, followed by module ID
                // Followed by inliner RIDs deltas with flag in the lowest bit
                // - if flag is set, followed by module ID

                var sig = new VertexSequence();

                bool isForeignInlinee = inlinee.Module != _globalContext;
                sig.Append(new UnsignedConstant((uint)(inlineeRid << 1 | (isForeignInlinee ? 1 : 0))));
                if (isForeignInlinee)
                {
                    sig.Append(new UnsignedConstant((uint)factory.ManifestMetadataTable.ModuleToIndex(inlinee.Module)));
                }

                List <EcmaMethod> sortedInliners = new List <EcmaMethod>(inlineeWithInliners.Value);
                sortedInliners.Sort((a, b) =>
                {
                    if (a == b)
                    {
                        return(0);
                    }

                    int aRid = MetadataTokens.GetRowNumber(a.Handle);
                    int bRid = MetadataTokens.GetRowNumber(b.Handle);
                    if (aRid < bRid)
                    {
                        return(-1);
                    }
                    else if (aRid > bRid)
                    {
                        return(1);
                    }

                    int result = a.Module.CompareTo(b.Module);
                    Debug.Assert(result != 0);
                    return(result);
                });

                int baseRid = 0;
                foreach (EcmaMethod inliner in sortedInliners)
                {
                    int inlinerRid = MetadataTokens.GetRowNumber(inliner.Handle);
                    int ridDelta   = inlinerRid - baseRid;
                    baseRid = inlinerRid;
                    Debug.Assert(ridDelta >= 0);
                    bool isForeignInliner = inliner.Module != _globalContext;
                    sig.Append(new UnsignedConstant((uint)(ridDelta << 1 | (isForeignInliner ? 1 : 0))));
                    if (isForeignInliner)
                    {
                        sig.Append(new UnsignedConstant((uint)factory.ManifestMetadataTable.ModuleToIndex(inliner.Module)));
                    }
                }

                hashtable.Append((uint)hashCode, section.Place(sig));
            }

            MemoryStream writerContent = new MemoryStream();

            writer.Save(writerContent);

            return(new ObjectData(
                       data: writerContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Exemplo n.º 27
0
        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;

                // 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;
                }

                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 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
                {
                    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)
                {
                    bool useUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic;
                    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) << 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 }));
        }
Exemplo n.º 28
0
        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);

            foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping())
            {
                if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity))
                    continue;

                // We are looking for any EEType - constructed or not, it has to be in the mapping
                // table so that we can map it to metadata.
                EETypeNode node = null;
                
                if (!mappingEntry.Entity.IsGenericDefinition)
                {
                    node = factory.ConstructedTypeSymbol(mappingEntry.Entity) as EETypeNode;
                }
                
                if (node == null || !node.Marked)
                {
                    // This might have been a typeof() expression.
                    node = factory.NecessaryTypeSymbol(mappingEntry.Entity) as EETypeNode;
                }

                if (node.Marked)
                {
                    Vertex vertex = writer.GetTuple(
                        writer.GetUnsignedConstant(_externalReferences.GetIndex(node)),
                        writer.GetUnsignedConstant((uint)mappingEntry.MetadataHandle)
                        );

                    int hashCode = node.Type.GetHashCode();
                    typeMapHashTable.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 });
        }
Exemplo n.º 29
0
        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 }));
            }

            // 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 }));
        }
Exemplo n.º 31
0
        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 }));
        }
Exemplo n.º 32
0
        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())
            {
                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.HasReflectionInvokeStub(method))
                    continue;

                InvokeTableFlags flags = 0;

                if (method.HasInstantiation)
                    flags |= InvokeTableFlags.IsGenericMethod;

                if (method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg())
                    flags |= InvokeTableFlags.RequiresInstArg;

                // TODO: better check for default public(!) constructor
                if (method.IsConstructor && method.Signature.Length == 0)
                    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;

                // 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 & MetadataGeneration.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)
                {
                    vertex = writer.GetTuple(vertex,
                        writer.GetUnsignedConstant(_externalReferences.GetIndex(
                            factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))));
                }

                // TODO: data to generate the generic dictionary with the type loader
                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));
            }

            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)
        {
            // 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 }));
        }
Exemplo n.º 34
0
        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 & MetadataGeneration.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 });
        }
Exemplo n.º 35
0
        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();
            Section      section = writer.NewSection();

            VertexHashtable typesHashtable = new VertexHashtable();

            section.Place(typesHashtable);

            ReadyToRunTableManager r2rManager = (ReadyToRunTableManager)factory.MetadataManager;

            foreach (TypeInfo <TypeDefinitionHandle> defTypeInfo in r2rManager.GetDefinedTypes())
            {
                TypeDefinitionHandle defTypeHandle = defTypeInfo.Handle;
                int hashCode = 0;
                for (; ;)
                {
                    TypeDefinition defType       = defTypeInfo.MetadataReader.GetTypeDefinition(defTypeHandle);
                    string         namespaceName = defTypeInfo.MetadataReader.GetString(defType.Namespace);
                    string         typeName      = defTypeInfo.MetadataReader.GetString(defType.Name);
                    hashCode ^= ReadyToRunHashCode.NameHashCode(namespaceName, typeName);
                    if (!defType.Attributes.IsNested())
                    {
                        break;
                    }
                    defTypeHandle = defType.GetDeclaringType();
                }
                typesHashtable.Append(unchecked ((uint)hashCode), section.Place(new UnsignedConstant(((uint)MetadataTokens.GetRowNumber(defTypeInfo.Handle) << 1) | 0)));
            }

            foreach (TypeInfo <ExportedTypeHandle> expTypeInfo in r2rManager.GetExportedTypes())
            {
                ExportedTypeHandle expTypeHandle = expTypeInfo.Handle;
                int hashCode = 0;
                for (; ;)
                {
                    ExportedType expType       = expTypeInfo.MetadataReader.GetExportedType(expTypeHandle);
                    string       namespaceName = expTypeInfo.MetadataReader.GetString(expType.Namespace);
                    string       typeName      = expTypeInfo.MetadataReader.GetString(expType.Name);
                    hashCode ^= ReadyToRunHashCode.NameHashCode(namespaceName, typeName);
                    if (expType.Implementation.Kind != HandleKind.ExportedType)
                    {
                        // Not a nested class
                        break;
                    }
                    expTypeHandle = (ExportedTypeHandle)expType.Implementation;
                }
                typesHashtable.Append(unchecked ((uint)hashCode), section.Place(new UnsignedConstant(((uint)MetadataTokens.GetRowNumber(expTypeInfo.Handle) << 1) | 1)));
            }

            MemoryStream writerContent = new MemoryStream();

            writer.Save(writerContent);

            return(new ObjectData(
                       data: writerContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Exemplo n.º 36
0
        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 }));
        }