diff options
author | Michal Strehovsky <michals@microsoft.com> | 2017-11-09 10:56:54 +0300 |
---|---|---|
committer | Michal Strehovsky <michals@microsoft.com> | 2017-11-09 10:56:54 +0300 |
commit | 30295b8860586f7d84861856768885dde5a19cfd (patch) | |
tree | 2eb0050b649481f61f365c9a03b98c9f7e719e53 /src/System.Private.StackTraceMetadata | |
parent | 162cead08753e6440d7e90ec4fb453a1a651785a (diff) |
Extend stack trace metadata formatter to support definition records
Definition records don't show up in ProjectN context right now because the existing definitions (generated by the IL2IL toolchain) are not accessible at the stack trace metadata emission time (in NUTC). NUTC only generates reference records (because they're more compact).
In the unified model (CoreRT, and hopefully Project X at some point), a stack trace metadata record can also point to records used for reflection (and those are typically definition records). This can happen if we have browse only metadata for a method with no matching invoke record (because the method was reflection enabled for Browse, but not Invoke). Reusing the definition record saves space.
[tfs-changeset: 1680688]
Diffstat (limited to 'src/System.Private.StackTraceMetadata')
-rw-r--r-- | src/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/src/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs b/src/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs index 2a71373f1..f2c65a842 100644 --- a/src/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs +++ b/src/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs @@ -54,6 +54,10 @@ namespace Internal.StackTraceMetadata case HandleType.MethodInstantiation: EmitMethodInstantiationName(methodHandle.ToMethodInstantiationHandle(_metadataReader)); break; + + case HandleType.QualifiedMethod: + EmitMethodDefinitionName(methodHandle.ToQualifiedMethodHandle(_metadataReader)); + break; default: Debug.Assert(false); @@ -88,6 +92,19 @@ namespace Internal.StackTraceMetadata EmitGenericArguments(methodInst.GenericTypeArguments); EmitMethodParameters(methodSignature); } + + private void EmitMethodDefinitionName(QualifiedMethodHandle qualifiedMethodHandle) + { + QualifiedMethod qualifiedMethod = _metadataReader.GetQualifiedMethod(qualifiedMethodHandle); + Method method = _metadataReader.GetMethod(qualifiedMethod.Method); + MethodSignature methodSignature = _metadataReader.GetMethodSignature(method.Signature); + EmitTypeName(methodSignature.ReturnType, namespaceQualified: false); + _outputBuilder.Append(' '); + EmitTypeName(qualifiedMethod.EnclosingType, namespaceQualified: true); + _outputBuilder.Append('.'); + EmitString(method.Name); + EmitMethodParameters(methodSignature); + } /// <summary> /// Emit containing type and method name and extract the method signature from a method reference. @@ -172,6 +189,10 @@ namespace Internal.StackTraceMetadata case HandleType.ByReferenceSignature: EmitByRefTypeName(typeHandle.ToByReferenceSignatureHandle(_metadataReader)); break; + + case HandleType.TypeDefinition: + EmitTypeDefinitionName(typeHandle.ToTypeDefinitionHandle(_metadataReader), namespaceQualified); + break; default: Debug.Assert(false); @@ -190,12 +211,28 @@ namespace Internal.StackTraceMetadata if (!namespaceRef.ParentScopeOrNamespace.IsNull(_metadataReader) && namespaceRef.ParentScopeOrNamespace.HandleType == HandleType.NamespaceReference) { + int charsWritten = _outputBuilder.Length; EmitNamespaceReferenceName(namespaceRef.ParentScopeOrNamespace.ToNamespaceReferenceHandle(_metadataReader)); - _outputBuilder.Append('.'); + if (_outputBuilder.Length - charsWritten > 0) + _outputBuilder.Append('.'); } EmitString(namespaceRef.Name); } - + + private void EmitNamespaceDefinitionName(NamespaceDefinitionHandle namespaceDefHandle) + { + NamespaceDefinition namespaceDef = _metadataReader.GetNamespaceDefinition(namespaceDefHandle); + if (!namespaceDef.ParentScopeOrNamespace.IsNull(_metadataReader) && + namespaceDef.ParentScopeOrNamespace.HandleType == HandleType.NamespaceDefinition) + { + int charsWritten = _outputBuilder.Length; + EmitNamespaceDefinitionName(namespaceDef.ParentScopeOrNamespace.ToNamespaceDefinitionHandle(_metadataReader)); + if (_outputBuilder.Length - charsWritten > 0) + _outputBuilder.Append('.'); + } + EmitString(namespaceDef.Name); + } + /// <summary> /// Emit type reference. /// </summary> @@ -214,13 +251,34 @@ namespace Internal.StackTraceMetadata } else if (namespaceQualified) { + int charsWritten = _outputBuilder.Length; EmitNamespaceReferenceName(typeRef.ParentNamespaceOrType.ToNamespaceReferenceHandle(_metadataReader)); - _outputBuilder.Append('.'); + if (_outputBuilder.Length - charsWritten > 0) + _outputBuilder.Append('.'); } } EmitString(typeRef.TypeName); } - + + private void EmitTypeDefinitionName(TypeDefinitionHandle typeDefHandle, bool namespaceQualified) + { + TypeDefinition typeDef = _metadataReader.GetTypeDefinition(typeDefHandle); + if (!typeDef.EnclosingType.IsNull(_metadataReader)) + { + // Nested type + EmitTypeName(typeDef.EnclosingType, namespaceQualified); + _outputBuilder.Append('+'); + } + else if (namespaceQualified) + { + int charsWritten = _outputBuilder.Length; + EmitNamespaceDefinitionName(typeDef.NamespaceDefinition); + if (_outputBuilder.Length - charsWritten > 0) + _outputBuilder.Append('.'); + } + EmitString(typeDef.Name); + } + /// <summary> /// Emit an arbitrary type specification. /// </summary> |