提交 769cd5be 编写于 作者: T Tomas Matousek

The value of nil heap handles in EnC deltas should be zero

上级 8ea9ab66
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CodeGen;
...@@ -64,6 +65,40 @@ public void DeltaHeapsStartWithEmptyItem() ...@@ -64,6 +65,40 @@ public void DeltaHeapsStartWithEmptyItem()
} }
} }
[Fact]
public void Delta_AssemblyDefTable()
{
var source0 = @"public class C { public static void F() { System.Console.WriteLine(1); } }";
var source1 = @"public class C { public static void F() { System.Console.WriteLine(2); } }";
var compilation0 = CreateCompilationWithMscorlib45(source0, options: ComSafeDebugDll);
var compilation1 = compilation0.WithSource(source1);
var f0 = compilation0.GetMember<MethodSymbol>("C.F");
var f1 = compilation1.GetMember<MethodSymbol>("C.F");
var v0 = CompileAndVerify(compilation0);
var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo);
var diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f0, f1, preserveLocalVariables: true)));
var reader1 = diff1.GetMetadata().Reader;
var assemblyDef = reader1.GetAssemblyDefinition();
Assert.False(assemblyDef.Name.IsNil);
Assert.Equal(0, assemblyDef.Version.Major);
Assert.Equal(0, assemblyDef.Version.Minor);
Assert.Equal(0, assemblyDef.Version.Revision);
Assert.Equal(0, assemblyDef.Version.Build);
Assert.True(assemblyDef.PublicKey.IsNil);
Assert.True(assemblyDef.Culture.IsNil);
Assert.Equal((AssemblyFlags)0, assemblyDef.Flags);
Assert.Equal(AssemblyHashAlgorithm.Sha1, assemblyDef.HashAlgorithm);
}
[Fact] [Fact]
public void ModifyMethod() public void ModifyMethod()
{ {
......
...@@ -21,9 +21,9 @@ internal struct StringIdx : IEquatable<StringIdx> ...@@ -21,9 +21,9 @@ internal struct StringIdx : IEquatable<StringIdx>
// index in _stringIndexToHeapPositionMap // index in _stringIndexToHeapPositionMap
public readonly int MapIndex; public readonly int MapIndex;
internal StringIdx(int virtIdx) internal StringIdx(int mapIndex)
{ {
MapIndex = virtIdx; MapIndex = mapIndex;
} }
public bool Equals(StringIdx other) public bool Equals(StringIdx other)
...@@ -103,7 +103,7 @@ internal sealed class MetadataHeapsBuilder ...@@ -103,7 +103,7 @@ internal sealed class MetadataHeapsBuilder
// #String heap // #String heap
private Dictionary<string, StringIdx> _strings = new Dictionary<string, StringIdx>(128); private Dictionary<string, StringIdx> _strings = new Dictionary<string, StringIdx>(128);
private int[] _stringIndexToHeapPositionMap; private int[] _stringIndexToResolvedOffsetMap;
private BlobBuilder _stringWriter; private BlobBuilder _stringWriter;
private readonly int _stringHeapStartOffset; private readonly int _stringHeapStartOffset;
...@@ -124,10 +124,11 @@ internal sealed class MetadataHeapsBuilder ...@@ -124,10 +124,11 @@ internal sealed class MetadataHeapsBuilder
int blobHeapStartOffset = 0, int blobHeapStartOffset = 0,
int guidHeapStartOffset = 0) int guidHeapStartOffset = 0)
{ {
// Add zero-th entry to heaps. // Add zero-th entry to all heaps, even in EnC delta.
// Full metadata represent empty blob/string at heap index 0. // We don't want generation-relative handles to ever be IsNil.
// Delta metadata requires these to avoid nil generation-relative handles, // In both full and delta metadata all nil heap handles should have zero value.
// which are technically viable but confusing. // There should be no blob handle that references the 0 byte added at the
// beginning of the delta blob.
_userStringWriter.WriteByte(0); _userStringWriter.WriteByte(0);
_blobs.Add(ImmutableArray<byte>.Empty, new BlobIdx(0)); _blobs.Add(ImmutableArray<byte>.Empty, new BlobIdx(0));
...@@ -254,12 +255,12 @@ public StringIdx GetStringIndex(string str) ...@@ -254,12 +255,12 @@ public StringIdx GetStringIndex(string str)
public int ResolveStringIndex(StringIdx index) public int ResolveStringIndex(StringIdx index)
{ {
return _stringHeapStartOffset + _stringIndexToHeapPositionMap[index.MapIndex]; return _stringIndexToResolvedOffsetMap[index.MapIndex];
} }
public int ResolveBlobIndex(BlobIdx index) public int ResolveBlobIndex(BlobIdx index)
{ {
return _blobHeapStartOffset + index.HeapPosition; return (index.HeapPosition == 0) ? 0 : _blobHeapStartOffset + index.HeapPosition;
} }
public int GetUserStringToken(string str) public int GetUserStringToken(string str)
...@@ -364,26 +365,26 @@ private void SerializeStringHeap() ...@@ -364,26 +365,26 @@ private void SerializeStringHeap()
_stringWriter = new BlobBuilder(1024); _stringWriter = new BlobBuilder(1024);
// Create VirtIdx to Idx map and add entry for empty string // Create VirtIdx to Idx map and add entry for empty string
_stringIndexToHeapPositionMap = new int[sorted.Count + 1]; _stringIndexToResolvedOffsetMap = new int[sorted.Count + 1];
_stringIndexToHeapPositionMap[0] = 0; _stringIndexToResolvedOffsetMap[0] = 0;
_stringWriter.WriteByte(0); _stringWriter.WriteByte(0);
// Find strings that can be folded // Find strings that can be folded
string prev = string.Empty; string prev = string.Empty;
foreach (KeyValuePair<string, StringIdx> entry in sorted) foreach (KeyValuePair<string, StringIdx> entry in sorted)
{ {
int position = _stringWriter.Position; int position = _stringHeapStartOffset + _stringWriter.Position;
// It is important to use ordinal comparison otherwise we'll use the current culture! // It is important to use ordinal comparison otherwise we'll use the current culture!
if (prev.EndsWith(entry.Key, StringComparison.Ordinal)) if (prev.EndsWith(entry.Key, StringComparison.Ordinal))
{ {
// Map over the tail of prev string. Watch for null-terminator of prev string. // Map over the tail of prev string. Watch for null-terminator of prev string.
_stringIndexToHeapPositionMap[entry.Value.MapIndex] = position - (s_utf8Encoding.GetByteCount(entry.Key) + 1); _stringIndexToResolvedOffsetMap[entry.Value.MapIndex] = position - (s_utf8Encoding.GetByteCount(entry.Key) + 1);
} }
else else
{ {
_stringIndexToHeapPositionMap[entry.Value.MapIndex] = position; _stringIndexToResolvedOffsetMap[entry.Value.MapIndex] = position;
_stringWriter.WriteString(entry.Key, s_utf8Encoding); _stringWriter.WriteString(entry.Key, s_utf8Encoding);
_stringWriter.WriteByte(0); _stringWriter.WriteByte(0);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册