Browse Source

Fixed thread safety issues as per code review comments.

pull/1236/head
Andrey Shchekin 7 years ago
parent
commit
d677f0dcf1
  1. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  2. 14
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  3. 21
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  4. 33
      ICSharpCode.Decompiler/TypeSystem/Implementation/ThreeState.cs

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -362,6 +362,7 @@ @@ -362,6 +362,7 @@
<Compile Include="TypeSystem\Implementation\MetadataTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedParameter.cs" />
<Compile Include="TypeSystem\Implementation\ThreeState.cs" />
<Compile Include="TypeSystem\MetadataModule.cs" />
<Compile Include="TypeSystem\ModifiedType.cs" />
<Compile Include="TypeSystem\Implementation\PinnedType.cs" />

14
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs

@ -42,7 +42,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -42,7 +42,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
object constantValue;
IType type;
bool isVolatile; // initialized together with this.type
bool? isDecimalConstant;
// this can't be bool? as bool? is not thread-safe from torn reads
byte decimalConstantState;
internal MetadataField(MetadataModule module, FieldDefinitionHandle handle)
{
@ -53,9 +54,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -53,9 +54,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var def = module.metadata.GetFieldDefinition(handle);
this.attributes = def.Attributes;
if ((attributes & (FieldAttributes.Static | FieldAttributes.InitOnly)) != (FieldAttributes.Static | FieldAttributes.InitOnly)) {
isDecimalConstant = false;
}
if ((attributes & (FieldAttributes.Static | FieldAttributes.InitOnly)) != (FieldAttributes.Static | FieldAttributes.InitOnly))
decimalConstantState = ThreeState.False;
}
public EntityHandle MetadataToken => handle;
@ -193,11 +193,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -193,11 +193,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool IsDecimalConstant {
get {
if (isDecimalConstant == null) {
if (decimalConstantState == ThreeState.Unknown) {
var fieldDef = module.metadata.GetFieldDefinition(handle);
isDecimalConstant = DecimalConstantHelper.IsDecimalConstant(module, fieldDef.GetCustomAttributes());
decimalConstantState = ThreeState.From(DecimalConstantHelper.IsDecimalConstant(module, fieldDef.GetCustomAttributes()));
}
return (bool)isDecimalConstant;
return decimalConstantState == ThreeState.True;
}
}

21
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs

@ -37,8 +37,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -37,8 +37,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// lazy-loaded:
string name;
bool? hasConstantValueInSignature;
bool? isDecimalConstant;
// these can't be bool? as bool? is not thread-safe from torn reads
byte constantValueInSignatureState;
byte decimalConstantState;
internal MetadataParameter(MetadataModule module, IParameterizedMember owner, IType type, ParameterHandle handle)
{
@ -50,7 +51,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -50,7 +51,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var param = module.metadata.GetParameter(handle);
this.attributes = param.Attributes;
if (!IsOptional)
isDecimalConstant = false; // only optional parameters can be constants
decimalConstantState = ThreeState.False; // only optional parameters can be constants
}
public EntityHandle MetadataToken => handle;
@ -125,25 +126,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -125,25 +126,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool HasConstantValueInSignature {
get {
if (hasConstantValueInSignature == null) {
if (constantValueInSignatureState == ThreeState.Unknown) {
if (IsDecimalConstant) {
hasConstantValueInSignature = DecimalConstantHelper.AllowsDecimalConstants(module);
constantValueInSignatureState = ThreeState.From(DecimalConstantHelper.AllowsDecimalConstants(module));
}
else {
hasConstantValueInSignature = !module.metadata.GetParameter(handle).GetDefaultValue().IsNil;
constantValueInSignatureState = ThreeState.From(!module.metadata.GetParameter(handle).GetDefaultValue().IsNil);
}
}
return (bool)hasConstantValueInSignature;
return constantValueInSignatureState == ThreeState.True;
}
}
bool IsDecimalConstant {
get {
if (isDecimalConstant == null) {
if (decimalConstantState == ThreeState.Unknown) {
var parameterDef = module.metadata.GetParameter(handle);
isDecimalConstant = DecimalConstantHelper.IsDecimalConstant(module, parameterDef.GetCustomAttributes());
decimalConstantState = ThreeState.From(DecimalConstantHelper.IsDecimalConstant(module, parameterDef.GetCustomAttributes()));
}
return (bool)isDecimalConstant;
return decimalConstantState == ThreeState.True;
}
}

33
ICSharpCode.Decompiler/TypeSystem/Implementation/ThreeState.cs

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
// Copyright (c) 2018 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
/// <summary>
/// Constants used instead of <see cref="bool?"/>
/// in multithreaded code, as <c>bool?</c> might produce torn reads.
/// </summary>
static class ThreeState
{
public const byte Unknown = 0;
public const byte False = 1;
public const byte True = 2;
public static byte From(bool value) => value ? True : False;
}
}
Loading…
Cancel
Save