提交 2c991f8e 编写于 作者: T Tomas Matousek

Move the document of the first sequence point from sequence point blob header to MethodBody table.

上级 571ea520
......@@ -97,11 +97,12 @@ The representation is optimized for an efficient deserialization of the name int
MethodBody table is either empty (missing) or has exactly as many rows as MethodDef table and the following column:
* _SequencePoints_ (Blob heap index, 0 if the method doesn’t have a body, encoding: [sequence points blob](#SequencePointsBlob))
* _Document_ (The row id of the document containing the first sequence point of the method, or 0 if the method doesn't have sequence points)
* _SequencePoints_ (Blob heap index, 0 if the method doesn’t have sequence points, encoding: [sequence points blob](#SequencePointsBlob))
The table is a logical extension of MethodDef table (adding a column to the table) and as such can be indexed by MethodDef row id.
#### <a name="MethodBodyBlob"></a>Method Body Blob
#### <a name="SequencePointsBlob"></a>Sequence Points Blob
Sequence point is a quintuple of integers and a document reference:
* IL Offset
......@@ -133,7 +134,6 @@ _Method body blob_ has the following structure:
| component | value stored | integer representation |
|:-----------------|:------------------------------|:-----------------------|
| _LocalSignature_ | StandAloneSig table row id | unsigned compressed |
| _Document_ | Document table row id | unsigned compressed |
_LocalSignature_ stores the row id of the local signature of the method. This information is somewhat redundant since it can be retrieved from the IL stream. However in some scenarios the IL stream is not available or loading it would unnecessary page in memory that might not otherwise be needed.
......@@ -164,7 +164,7 @@ _LocalSignature_ stores the row id of the local signature of the method. This in
| _δILOffset_ | 0 | unsigned compressed |
| _Document_ | Document row id | unsigned compressed |
Each _SequencePointRecord_ represents a single sequence point. The sequence point inherits the value of _Document_ property from the previous record (_SequencePointRecord_ or _document-record_) or from the _header_ if its the first sequence point. The value of _IL Offset_ is calculated using the value of the previous sequence point (if any) and the value stored in the record.
Each _SequencePointRecord_ represents a single sequence point. The sequence point inherits the value of _Document_ property from the previous record (_SequencePointRecord_ or _document-record_) or from the _Document_ field of the _MethodBody_ table if it's the first sequence point. The value of _IL Offset_ is calculated using the value of the previous sequence point (if any) and the value stored in the record.
The values of _Start Line_, _Start Column_, _End Line_ and _End Column_ of a non-hidden sequence point are calculated based upon the values of the previous non-hidden sequence point (if any) and the data stored in the record.
......
......@@ -49,7 +49,7 @@ public static void Main()
var name = mdReader.GetString(method.Name);
var spReader = pdbReader.GetSequencePointsReader(methodBody.SequencePoints);
var spReader = methodBody.GetSequencePointsReader();
TextWriter writer = new StringWriter();
while (spReader.MoveNext())
......@@ -83,7 +83,6 @@ public static void Main()
AssertEx.Equal(new byte[]
{
0x01, // local signature
0x01, // document
0x00, // IL offset
0x00, // Delta Lines
......@@ -132,7 +131,6 @@ public static void Main()
AssertEx.Equal(new byte[]
{
0x00, // local signature
0x01, // document
0x00, // delta IL offset
0x00, // Delta Lines
......
......@@ -51,6 +51,7 @@ internal sealed class MetadataSizes
public readonly byte TypeDefOrRefCodedIndexSize;
public readonly byte TypeOrMethodDefCodedIndexSize;
public readonly byte DocumentIndexSize;
public readonly byte LocalVariableIndexSize;
public readonly byte LocalConstantIndexSize;
public readonly byte ImportScopeIndexSize;
......@@ -211,6 +212,7 @@ internal sealed class MetadataSizes
this.TypeDefOrRefCodedIndexSize = this.GetReferenceByteSize(2, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.TypeSpec);
this.TypeOrMethodDefCodedIndexSize = this.GetReferenceByteSize(1, TableIndex.TypeDef, TableIndex.MethodDef);
this.DocumentIndexSize = this.GetReferenceByteSize(0, TableIndex.Document);
this.LocalVariableIndexSize = this.GetReferenceByteSize(0, TableIndex.LocalVariable);
this.LocalConstantIndexSize = this.GetReferenceByteSize(0, TableIndex.LocalConstant);
this.ImportScopeIndexSize = this.GetReferenceByteSize(0, TableIndex.ImportScope);
......@@ -293,7 +295,7 @@ internal sealed class MetadataSizes
size += GetTableSize(TableIndex.GenericParamConstraint, this.GenericParamIndexSize + this.TypeDefOrRefCodedIndexSize);
size += GetTableSize(TableIndex.Document, this.BlobIndexSize + this.GuidIndexSize + this.BlobIndexSize + this.GuidIndexSize);
size += GetTableSize(TableIndex.MethodBody, this.BlobIndexSize);
size += GetTableSize(TableIndex.MethodBody, this.DocumentIndexSize + this.BlobIndexSize);
size += GetTableSize(TableIndex.LocalScope, this.MethodDefIndexSize + this.ImportScopeIndexSize + this.LocalVariableIndexSize + this.LocalConstantIndexSize + 4 + 4);
size += GetTableSize(TableIndex.LocalVariable, 2 + 2 + this.StringIndexSize);
size += GetTableSize(TableIndex.LocalConstant, this.StringIndexSize + this.BlobIndexSize);
......
......@@ -21,6 +21,7 @@ private struct DocumentRow
private struct MethodBodyRow
{
public uint Document; // DocumentRid
public BlobIdx SequencePoints;
}
......@@ -99,8 +100,9 @@ private void SerializeMethodDebugInfo(IMethodBody bodyOpt, int methodRid, int lo
int importScopeRid = (bodyImportScope != null) ? GetImportScopeIndex(bodyImportScope, _scopeIndex) : 0;
// documents & sequence points:
BlobIdx sequencePointsBlob = SerializeSequencePoints(localSignatureRowId, bodyOpt.GetSequencePoints(), _documentIndex);
_methodBodyTable.Add(new MethodBodyRow { SequencePoints = sequencePointsBlob });
int firstDocumentRowId;
BlobIdx sequencePointsBlob = SerializeSequencePoints(localSignatureRowId, bodyOpt.GetSequencePoints(), _documentIndex, out firstDocumentRowId);
_methodBodyTable.Add(new MethodBodyRow { Document = (uint)firstDocumentRowId, SequencePoints = sequencePointsBlob });
// Unlike native PDB we don't emit an empty root scope.
// scopes are already ordered by StartOffset ascending then by EndOffset descending (the longest scope first).
......@@ -557,10 +559,15 @@ private void SerializeStateMachineLocalScopes(IMethodBody methodBody, int method
#region Sequence Points
private BlobIdx SerializeSequencePoints(int localSignatureRowId, ImmutableArray<SequencePoint> sequencePoints, Dictionary<DebugSourceDocument, int> documentIndex)
private BlobIdx SerializeSequencePoints(
int localSignatureRowId,
ImmutableArray<SequencePoint> sequencePoints,
Dictionary<DebugSourceDocument, int> documentIndex,
out int firstDocumentRowId)
{
if (sequencePoints.Length == 0)
{
firstDocumentRowId = 0;
return default(BlobIdx);
}
......@@ -569,20 +576,20 @@ private BlobIdx SerializeSequencePoints(int localSignatureRowId, ImmutableArray<
int previousNonHiddenStartLine = -1;
int previousNonHiddenStartColumn = -1;
uint currentDocumentRowId = GetOrAddDocument(sequencePoints[0].Document, documentIndex);
firstDocumentRowId = GetOrAddDocument(sequencePoints[0].Document, documentIndex);
// header:
writer.WriteCompressedInteger((uint)localSignatureRowId);
writer.WriteCompressedInteger(currentDocumentRowId);
int currentDocumentRowId = firstDocumentRowId;
for (int i = 0; i < sequencePoints.Length; i++)
{
uint documentRowId = GetOrAddDocument(sequencePoints[i].Document, documentIndex);
int documentRowId = GetOrAddDocument(sequencePoints[i].Document, documentIndex);
if (documentRowId != currentDocumentRowId)
{
// document record:
writer.WriteCompressedInteger(0);
writer.WriteCompressedInteger(documentRowId);
writer.WriteCompressedInteger((uint)documentRowId);
currentDocumentRowId = documentRowId;
}
......@@ -649,7 +656,7 @@ private void SerializeDeltaLinesAndColumns(BlobBuilder writer, SequencePoint seq
#region Documents
private uint GetOrAddDocument(DebugSourceDocument document, Dictionary<DebugSourceDocument, int> index)
private int GetOrAddDocument(DebugSourceDocument document, Dictionary<DebugSourceDocument, int> index)
{
int documentRowId;
if (!index.TryGetValue(document, out documentRowId))
......@@ -667,7 +674,7 @@ private uint GetOrAddDocument(DebugSourceDocument document, Dictionary<DebugSour
});
}
return (uint)documentRowId;
return documentRowId;
}
private static readonly char[] Separator1 = { '/' };
......@@ -765,6 +772,7 @@ private void SerializeMethodBodyTable(BlobBuilder writer, MetadataSizes metadata
{
foreach (var row in _methodBodyTable)
{
writer.WriteReference(row.Document, metadataSizes.DocumentIndexSize);
writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.SequencePoints), metadataSizes.BlobIndexSize);
}
}
......
csc /target:library /debug+ /features:pdb=portable /optimize- /features:deterministic Async.cs
csc /target:library /debug:portable /optimize- /deterministic Async.cs
copy /y Async.pdb Async.pdbx
copy /y Async.dll Async.dllx
csc /target:library /debug+ /optimize- /features:deterministic Async.cs
csc /target:library /debug+ /optimize- /deterministic Async.cs
csc /target:library /debug+ /features:pdb=portable /optimize- /features:deterministic Documents.cs
csc /target:library /debug:portable /optimize- /deterministic Documents.cs
copy /y Documents.pdb Documents.pdbx
copy /y Documents.dll Documents.dllx
csc /target:library /debug+ /optimize- /features:deterministic Documents.cs
csc /target:library /debug+ /optimize- /deterministic Documents.cs
csc /target:library /debug+ /optimize- /features:pdb=portable /features:deterministic MethodBoundaries.cs
csc /target:library /debug:portable /optimize- /deterministic MethodBoundaries.cs
copy /y MethodBoundaries.pdb MethodBoundaries.pdbx
copy /y MethodBoundaries.dll MethodBoundaries.dllx
csc /target:library /debug+ /optimize- /features:deterministic MethodBoundaries.cs
csc /target:library /debug+ /optimize- /deterministic MethodBoundaries.cs
csc /target:library /debug+ /features:pdb=portable /optimize- /features:deterministic Async.cs
csc /target:library /debug:portable /optimize- /deterministic Async.cs
copy /y Async.pdb Async.pdbx
del Async.pdb
......@@ -177,17 +177,10 @@ private static ImmutableArray<ImmutableArray<MethodLineExtent>> PartitionToNonOv
{
continue;
}
var methodBodyReader = reader.GetBlobReader(methodBody.SequencePoints);
// skip signature:
methodBodyReader.ReadCompressedInteger();
// document:
var currentDocument = MetadataTokens.DocumentHandle(methodBodyReader.ReadCompressedInteger());
// sequence points:
var spReader = reader.GetSequencePointsReader(methodBody.SequencePoints);
var spReader = methodBody.GetSequencePointsReader();
DocumentHandle currentDocument = methodBody.Document;
int minLine = int.MaxValue;
int maxLine = int.MinValue;
......
......@@ -50,7 +50,7 @@ public int FindClosestLine(int line, out int closestLine)
// enumerate method sequence points:
var body = mdReader.GetMethodBody(extent.Method);
var spReader = mdReader.GetSequencePointsReader(body.SequencePoints);
var spReader = body.GetSequencePointsReader();
while (spReader.MoveNext())
{
......
......@@ -35,9 +35,7 @@ internal SymMethod(SymReader symReader, MethodBodyHandle handle)
private SequencePointBlobReader GetSequencePointsReader()
{
var mdReader = SymReader.MetadataReader;
var body = mdReader.GetMethodBody(BodyHandle);
return mdReader.GetSequencePointsReader(body.SequencePoints);
return SymReader.MetadataReader.GetMethodBody(BodyHandle).GetSequencePointsReader();
}
private RootScopeData GetRootScopeData()
......
......@@ -10,6 +10,7 @@
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using Roslyn.Reflection.Metadata.Decoding;
namespace Roslyn.Test.MetadataUtilities
{
......@@ -614,7 +615,10 @@ private string FormatImports(BlobHandle handle)
private string SequencePoint(SequencePoint sequencePoint)
{
string range = sequencePoint.IsHidden ? "<hidden>" : $"({sequencePoint.StartLine}, {sequencePoint.StartColumn}) - ({sequencePoint.EndLine}, {sequencePoint.EndColumn})";
string range = sequencePoint.IsHidden ?
"<hidden>" :
$"({sequencePoint.StartLine}, {sequencePoint.StartColumn}) - ({sequencePoint.EndLine}, {sequencePoint.EndColumn}) {Token(() => sequencePoint.Document)}";
return $"IL_{sequencePoint.Offset:X4}: " + range;
}
......@@ -1511,7 +1515,7 @@ private void WriteMethodBody()
try
{
var spReader = _reader.GetSequencePointsReader(entry.SequencePoints);
var spReader = entry.GetSequencePointsReader();
while (spReader.MoveNext())
{
_writer.Write(" ");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册