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

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

上级 8ea9ab66
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using Microsoft.CodeAnalysis.CodeGen;
......@@ -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]
public void ModifyMethod()
{
......
......@@ -21,9 +21,9 @@ internal struct StringIdx : IEquatable<StringIdx>
// index in _stringIndexToHeapPositionMap
public readonly int MapIndex;
internal StringIdx(int virtIdx)
internal StringIdx(int mapIndex)
{
MapIndex = virtIdx;
MapIndex = mapIndex;
}
public bool Equals(StringIdx other)
......@@ -103,7 +103,7 @@ internal sealed class MetadataHeapsBuilder
// #String heap
private Dictionary<string, StringIdx> _strings = new Dictionary<string, StringIdx>(128);
private int[] _stringIndexToHeapPositionMap;
private int[] _stringIndexToResolvedOffsetMap;
private BlobBuilder _stringWriter;
private readonly int _stringHeapStartOffset;
......@@ -124,10 +124,11 @@ internal sealed class MetadataHeapsBuilder
int blobHeapStartOffset = 0,
int guidHeapStartOffset = 0)
{
// Add zero-th entry to heaps.
// Full metadata represent empty blob/string at heap index 0.
// Delta metadata requires these to avoid nil generation-relative handles,
// which are technically viable but confusing.
// Add zero-th entry to all heaps, even in EnC delta.
// We don't want generation-relative handles to ever be IsNil.
// In both full and delta metadata all nil heap handles should have zero value.
// There should be no blob handle that references the 0 byte added at the
// beginning of the delta blob.
_userStringWriter.WriteByte(0);
_blobs.Add(ImmutableArray<byte>.Empty, new BlobIdx(0));
......@@ -254,12 +255,12 @@ public StringIdx GetStringIndex(string str)
public int ResolveStringIndex(StringIdx index)
{
return _stringHeapStartOffset + _stringIndexToHeapPositionMap[index.MapIndex];
return _stringIndexToResolvedOffsetMap[index.MapIndex];
}
public int ResolveBlobIndex(BlobIdx index)
{
return _blobHeapStartOffset + index.HeapPosition;
return (index.HeapPosition == 0) ? 0 : _blobHeapStartOffset + index.HeapPosition;
}
public int GetUserStringToken(string str)
......@@ -364,26 +365,26 @@ private void SerializeStringHeap()
_stringWriter = new BlobBuilder(1024);
// 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);
// Find strings that can be folded
string prev = string.Empty;
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!
if (prev.EndsWith(entry.Key, StringComparison.Ordinal))
{
// 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
{
_stringIndexToHeapPositionMap[entry.Value.MapIndex] = position;
_stringIndexToResolvedOffsetMap[entry.Value.MapIndex] = position;
_stringWriter.WriteString(entry.Key, s_utf8Encoding);
_stringWriter.WriteByte(0);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册