private List <MetadataMapping <MethodDesc> > GenerateStackTraceMetadata(NodeFactory factory)
        {
            var transformed             = MetadataTransform.Run(new NoDefinitionMetadataPolicy(), Array.Empty <ModuleDesc>());
            MetadataTransform transform = transformed.Transform;

            // Generate metadata blob
            var writer = new MetadataWriter();

            // Only emit stack trace metadata for those methods which don't have reflection metadata
            HashSet <MethodDesc> methodInvokeMap = new HashSet <MethodDesc>();

            foreach (var mappingEntry in GetMethodMapping(factory))
            {
                var method = mappingEntry.Entity;
                if (ShouldMethodBeInInvokeMap(method))
                {
                    methodInvokeMap.Add(method);
                }
            }

            // Generate entries in the blob for methods that will be necessary for stack trace purposes.
            var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >();

            foreach (var methodBody in GetCompiledMethodBodies())
            {
                NonExternMethodSymbolNode methodNode = methodBody as NonExternMethodSymbolNode;
                if (methodNode != null && !methodNode.HasCompiledBody)
                {
                    continue;
                }

                MethodDesc method = methodBody.Method;

                if (methodInvokeMap.Contains(method))
                {
                    continue;
                }

                if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method))
                {
                    continue;
                }

                MetadataRecord record = CreateStackTraceRecord(transform, method);

                stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>(
                                          method,
                                          record));

                writer.AdditionalRootRecords.Add(record);
            }

            var ms = new MemoryStream();

            writer.Write(ms);

            _stackTraceBlob = ms.ToArray();

            var result = new List <MetadataMapping <MethodDesc> >();

            // Generate stack trace metadata mapping
            foreach (var stackTraceRecord in stackTraceRecords)
            {
                result.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value)));
            }

            return(result);
        }
Esempio n. 2
0
        private List <MetadataMapping <MethodDesc> > GenerateStackTraceMetadata(NodeFactory factory)
        {
            var transformed             = MetadataTransform.Run(new NoDefinitionMetadataPolicy(), Array.Empty <ModuleDesc>());
            MetadataTransform transform = transformed.Transform;

            // Generate metadata blob
            var writer = new MetadataWriter();

            // Only emit stack trace metadata for those methods which don't have reflection metadata
            HashSet <MethodDesc> methodInvokeMap = new HashSet <MethodDesc>();

            foreach (var mappingEntry in GetMethodMapping(factory))
            {
                var method = mappingEntry.Entity;
                if (ShouldMethodBeInInvokeMap(method))
                {
                    methodInvokeMap.Add(method);
                }
            }

            // Generate entries in the blob for methods that will be necessary for stack trace purposes.
            var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >();

            foreach (var methodBody in GetCompiledMethodBodies())
            {
                NonExternMethodSymbolNode methodNode = methodBody as NonExternMethodSymbolNode;
                if (methodNode != null && !methodNode.HasCompiledBody)
                {
                    continue;
                }

                MethodDesc method = methodBody.Method;

                if (methodInvokeMap.Contains(method))
                {
                    continue;
                }

                if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method))
                {
                    continue;
                }

                // In the metadata, we only represent the generic definition
                MethodDesc     methodToGenerateMetadataFor = method.GetTypicalMethodDefinition();
                MetadataRecord record = transform.HandleQualifiedMethod(methodToGenerateMetadataFor);

                // As a twist, instantiated generic methods appear as if instantiated over their formals.
                if (methodToGenerateMetadataFor.HasInstantiation)
                {
                    var methodInst = new MethodInstantiation
                    {
                        Method = record,
                    };
                    methodInst.GenericTypeArguments.Capacity = methodToGenerateMetadataFor.Instantiation.Length;
                    foreach (EcmaGenericParameter typeArgument in methodToGenerateMetadataFor.Instantiation)
                    {
                        var genericParam = new TypeReference
                        {
                            TypeName = (ConstantStringValue)typeArgument.Name,
                        };
                        methodInst.GenericTypeArguments.Add(genericParam);
                    }
                    record = methodInst;
                }

                stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>(
                                          method,
                                          record));

                writer.AdditionalRootRecords.Add(record);
            }

            var ms = new MemoryStream();

            writer.Write(ms);

            _stackTraceBlob = ms.ToArray();

            var result = new List <MetadataMapping <MethodDesc> >();

            // Generate stack trace metadata mapping
            foreach (var stackTraceRecord in stackTraceRecords)
            {
                result.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value)));
            }

            return(result);
        }