提交 fd352e9d 编写于 作者: V vsadov

Removed support for reused backing fields for locals of the same names.

Debug info cannot express reuse yet. Locals backed by reused fields cannot be seen in EE for now regadless of their names.
上级 a5091001
......@@ -103,7 +103,7 @@ private FieldSymbol GetAwaiterField(TypeSymbol awaiterType)
}
string fieldName = GeneratedNames.AsyncAwaiterFieldName(slotIndex);
result = F.StateMachineField(awaiterType, fieldName, SynthesizedLocalKind.AwaiterField, slotIndex, localNameOpt: null);
result = F.StateMachineField(awaiterType, fieldName, SynthesizedLocalKind.AwaiterField, slotIndex);
_awaiterFields.Add(awaiterType, result);
}
......
......@@ -283,10 +283,10 @@ private BoundStatement PossibleIteratorScope(ImmutableArray<LocalSymbol> locals,
Debug.Assert(local.SynthesizedKind.IsLongLived());
CapturedSymbolReplacement proxy;
bool reused = false;
if (!proxies.TryGetValue(local, out proxy))
{
proxy = new CapturedToStateMachineFieldReplacement(GetOrAllocateReusableHoistedField(TypeMap.SubstituteType(local.Type).Type, local), isReusable: true);
proxy = new CapturedToStateMachineFieldReplacement(GetOrAllocateReusableHoistedField(TypeMap.SubstituteType(local.Type).Type, out reused, local), isReusable: true);
proxies.Add(local, proxy);
}
......@@ -296,14 +296,11 @@ private BoundStatement PossibleIteratorScope(ImmutableArray<LocalSymbol> locals,
if ((local.SynthesizedKind == SynthesizedLocalKind.UserDefined && local.ScopeDesignatorOpt?.Kind() != SyntaxKind.SwitchSection) ||
local.SynthesizedKind == SynthesizedLocalKind.LambdaDisplayClass)
{
var field = ((CapturedToStateMachineFieldReplacement)proxy).HoistedField;
// NB: This is the case when the local backed by recycled field will not be visible in debugger.
// The backing field could be reused in Release and it may so happen that it was originally created for a local with a different name.
// Since the field name encodes the name of the local that it represents, nothing can be done about that here. Do not add such fields to the scope.
if (field.LocalNameOpt == local.Name)
// It may be possible in the future, but for now a backing field can be mapped only to a single local.
if (!reused)
{
hoistedLocalsWithDebugScopes.Add(field);
hoistedLocalsWithDebugScopes.Add(((CapturedToStateMachineFieldReplacement)proxy).HoistedField);
}
}
}
......@@ -422,7 +419,7 @@ private bool MightContainReferences(TypeSymbol type)
return false;
}
private StateMachineFieldSymbol GetOrAllocateReusableHoistedField(TypeSymbol type, LocalSymbol local = null)
private StateMachineFieldSymbol GetOrAllocateReusableHoistedField(TypeSymbol type, out bool reused, LocalSymbol local = null)
{
// In debug builds we don't reuse any hoisted variable.
Debug.Assert(F.Compilation.Options.OptimizationLevel == OptimizationLevel.Release);
......@@ -432,15 +429,17 @@ private StateMachineFieldSymbol GetOrAllocateReusableHoistedField(TypeSymbol typ
{
var field = fields.Last();
fields.RemoveLast();
reused = true;
return field;
}
reused = false;
var slotIndex = _nextHoistedFieldId++;
if (local?.SynthesizedKind == SynthesizedLocalKind.UserDefined)
{
string fieldName = GeneratedNames.MakeHoistedLocalFieldName(SynthesizedLocalKind.UserDefined, slotIndex, local.Name);
return F.StateMachineField(type, fieldName, SynthesizedLocalKind.UserDefined, slotIndex, local.Name);
return F.StateMachineField(type, fieldName, SynthesizedLocalKind.UserDefined, slotIndex);
}
return F.StateMachineField(type, GeneratedNames.ReusableHoistedLocalFieldName(slotIndex));
......@@ -626,11 +625,11 @@ private BoundExpression HoistRefInitialization(SynthesizedLocal local, BoundAssi
}
string fieldName = GeneratedNames.MakeHoistedLocalFieldName(kind, slotIndex);
hoistedField = F.StateMachineField(expr.Type, fieldName, new LocalSlotDebugInfo(kind, id), slotIndex, localNameOpt: null);
hoistedField = F.StateMachineField(expr.Type, fieldName, new LocalSlotDebugInfo(kind, id), slotIndex);
}
else
{
hoistedField = GetOrAllocateReusableHoistedField(fieldType);
hoistedField = GetOrAllocateReusableHoistedField(fieldType, reused: out _);
}
hoistedFields.Add(hoistedField);
......
......@@ -19,30 +19,26 @@ internal sealed class StateMachineFieldSymbol : SynthesizedFieldSymbolBase, ISyn
// -1 if the field doesn't represent a long-lived local or an awaiter.
internal readonly int SlotIndex;
// if the field represents a local variable - name of the variable.
internal readonly string LocalNameOpt;
internal readonly LocalSlotDebugInfo SlotDebugInfo;
// Some fields need to be public since they are initialized directly by the kickoff method.
public StateMachineFieldSymbol(NamedTypeSymbol stateMachineType, TypeSymbol type, string name, bool isPublic, bool isThis)
: this(stateMachineType, type, name, new LocalSlotDebugInfo(SynthesizedLocalKind.LoweringTemp, LocalDebugId.None), slotIndex: -1, localNameOpt: null, isPublic: isPublic)
: this(stateMachineType, type, name, new LocalSlotDebugInfo(SynthesizedLocalKind.LoweringTemp, LocalDebugId.None), slotIndex: -1, isPublic: isPublic)
{
_isThis = isThis;
}
public StateMachineFieldSymbol(NamedTypeSymbol stateMachineType, TypeSymbol type, string name, SynthesizedLocalKind synthesizedKind, int slotIndex, string localNameOpt, bool isPublic)
: this(stateMachineType, type, name, new LocalSlotDebugInfo(synthesizedKind, LocalDebugId.None), slotIndex, localNameOpt, isPublic: isPublic)
public StateMachineFieldSymbol(NamedTypeSymbol stateMachineType, TypeSymbol type, string name, SynthesizedLocalKind synthesizedKind, int slotIndex, bool isPublic)
: this(stateMachineType, type, name, new LocalSlotDebugInfo(synthesizedKind, LocalDebugId.None), slotIndex, isPublic: isPublic)
{
}
public StateMachineFieldSymbol(NamedTypeSymbol stateMachineType, TypeSymbol type, string name, LocalSlotDebugInfo slotDebugInfo, int slotIndex, string localNameOpt, bool isPublic)
public StateMachineFieldSymbol(NamedTypeSymbol stateMachineType, TypeSymbol type, string name, LocalSlotDebugInfo slotDebugInfo, int slotIndex, bool isPublic)
: base(stateMachineType, name, isPublic: isPublic, isReadOnly: false, isStatic: false)
{
Debug.Assert((object)type != null);
Debug.Assert(slotDebugInfo.SynthesizedKind.IsLongLived() == (slotIndex >= 0));
this.LocalNameOpt = localNameOpt;
_type = type;
this.SlotIndex = slotIndex;
this.SlotDebugInfo = slotDebugInfo;
......
......@@ -195,7 +195,7 @@ protected BoundStatement Rewrite()
}
string fieldName = GeneratedNames.MakeHoistedLocalFieldName(synthesizedKind, slotIndex, local.Name);
field = F.StateMachineField(fieldType, fieldName, new LocalSlotDebugInfo(synthesizedKind, id), slotIndex, local.Name);
field = F.StateMachineField(fieldType, fieldName, new LocalSlotDebugInfo(synthesizedKind, id), slotIndex);
}
if (field != null)
......
......@@ -211,16 +211,16 @@ public StateMachineFieldSymbol StateMachineField(TypeSymbol type, string name, b
return result;
}
public StateMachineFieldSymbol StateMachineField(TypeSymbol type, string name, SynthesizedLocalKind synthesizedKind, int slotIndex, string localNameOpt)
public StateMachineFieldSymbol StateMachineField(TypeSymbol type, string name, SynthesizedLocalKind synthesizedKind, int slotIndex)
{
var result = new StateMachineFieldSymbol(CurrentType, type, name, synthesizedKind, slotIndex, localNameOpt, isPublic: false);
var result = new StateMachineFieldSymbol(CurrentType, type, name, synthesizedKind, slotIndex, isPublic: false);
AddField(CurrentType, result);
return result;
}
public StateMachineFieldSymbol StateMachineField(TypeSymbol type, string name, LocalSlotDebugInfo slotDebugInfo, int slotIndex, string localNameOpt)
public StateMachineFieldSymbol StateMachineField(TypeSymbol type, string name, LocalSlotDebugInfo slotDebugInfo, int slotIndex)
{
var result = new StateMachineFieldSymbol(CurrentType, type, name, slotDebugInfo, slotIndex, localNameOpt, isPublic: false);
var result = new StateMachineFieldSymbol(CurrentType, type, name, slotDebugInfo, slotIndex, isPublic: false);
AddField(CurrentType, result);
return result;
}
......@@ -430,7 +430,7 @@ public BoundStatementList StatementList(BoundStatement first, BoundStatement sec
{
return new BoundStatementList(Syntax, ImmutableArray.Create(first, second)) { WasCompilerGenerated = true };
}
public BoundReturnStatement Return(BoundExpression expression = null)
{
if (expression != null)
......@@ -636,7 +636,7 @@ public BoundCall Call(BoundExpression receiver, MethodSymbol method, ImmutableAr
Syntax, receiver, method, args,
default(ImmutableArray<String>), default(ImmutableArray<RefKind>), false, false, false,
default(ImmutableArray<int>), LookupResultKind.Viable, null, method.ReturnType,
hasErrors:method.OriginalDefinition is ErrorMethodSymbol)
hasErrors: method.OriginalDefinition is ErrorMethodSymbol)
{ WasCompilerGenerated = true };
}
......@@ -985,7 +985,7 @@ public BoundExpression Typeof(TypeSymbol type)
WellKnownType(CodeAnalysis.WellKnownType.System_Type))
{ WasCompilerGenerated = true };
}
public ImmutableArray<BoundExpression> TypeOfs(ImmutableArray<TypeSymbol> typeArguments)
{
return typeArguments.SelectAsArray(Typeof);
......@@ -1183,14 +1183,15 @@ public BoundExpression Array(TypeSymbol elementType, ImmutableArray<BoundExpress
new BoundArrayInitialization(Syntax, elements) { WasCompilerGenerated = true },
Compilation.CreateArrayTypeSymbol(elementType));
}
public BoundExpression Array(TypeSymbol elementType, BoundExpression length)
{
return new BoundArrayCreation(
Syntax,
ImmutableArray.Create<BoundExpression>(length),
null,
Compilation.CreateArrayTypeSymbol(elementType)) { WasCompilerGenerated = true };
Compilation.CreateArrayTypeSymbol(elementType))
{ WasCompilerGenerated = true };
}
internal BoundExpression Default(TypeSymbol type)
......@@ -1331,7 +1332,7 @@ internal ImmutableArray<BoundExpression> MakeTempsForDiscardArguments(ImmutableA
if (discardsCount != 0)
{
arguments = arguments.SelectAsArray(
(arg, t) => arg.Kind == BoundKind.DiscardExpression ? t.factory.MakeTempForDiscard((BoundDiscardExpression)arg, t.builder) : arg,
(arg, t) => arg.Kind == BoundKind.DiscardExpression ? t.factory.MakeTempForDiscard((BoundDiscardExpression)arg, t.builder) : arg,
(factory: this, builder: builder));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册