Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Move thread safe flag manipulation into a helper #20

Merged
merged 2 commits into from
Oct 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/ILToNative/src/ILToNative.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
<Compile Include="..\..\TypeSystem\src\Common\TargetDetails.cs">
<Link>TypeSystem\TargetDetails.cs</Link>
</Compile>
<Compile Include="..\..\TypeSystem\src\Common\ThreadSafeFlags.cs">
<Link>TypeSystem\ThreadSafeFlags.cs</Link>
</Compile>
<Compile Include="..\..\TypeSystem\src\Common\TypeCast.cs">
<Link>TypeSystem\TypeCast.cs</Link>
</Compile>
Expand Down
56 changes: 25 additions & 31 deletions src/TypeSystem/src/Common/FieldLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Linq;
using Debug = System.Diagnostics.Debug;
using Interlocked = System.Threading.Interlocked;

namespace Internal.TypeSystem
{
Expand Down Expand Up @@ -458,7 +457,7 @@ private class StaticBlockInfo
public StaticsBlock ThreadStatics;
}

volatile int _fieldLayoutFlags;
ThreadSafeFlags _fieldLayoutFlags;

int _instanceFieldSize;
int _instanceByteCount;
Expand All @@ -471,24 +470,19 @@ public bool ContainsPointers
{
get
{
if ((_fieldLayoutFlags & FieldLayoutFlags.HasContainsPointers) == 0)
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.HasContainsPointers))
{
var flagsToAdd = FieldLayoutFlags.HasContainsPointers;

if (ComputeTypeContainsPointers())
flagsToAdd |= FieldLayoutFlags.ContainsPointers;

EnableFieldLayoutFlags(flagsToAdd);
ComputeTypeContainsPointers();
}
return (_fieldLayoutFlags & FieldLayoutFlags.ContainsPointers) != 0;
return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.ContainsPointers);
}
}

public int InstanceFieldSize
{
get
{
if ((_fieldLayoutFlags & FieldLayoutFlags.HasInstanceFieldLayout) == 0)
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.HasInstanceFieldLayout))
{
ComputeInstanceFieldLayout();
}
Expand All @@ -500,7 +494,7 @@ public int InstanceFieldAlignment
{
get
{
if ((_fieldLayoutFlags & FieldLayoutFlags.HasInstanceFieldLayout) == 0)
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.HasInstanceFieldLayout))
{
ComputeInstanceFieldLayout();
}
Expand All @@ -512,7 +506,7 @@ public int InstanceByteCount
{
get
{
if ((_fieldLayoutFlags & FieldLayoutFlags.HasInstanceFieldLayout) == 0)
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.HasInstanceFieldLayout))
{
ComputeInstanceFieldLayout();
}
Expand All @@ -524,7 +518,7 @@ public int NonGCStaticFieldSize
{
get
{
if ((_fieldLayoutFlags & FieldLayoutFlags.HasStaticFieldLayout) == 0)
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.HasStaticFieldLayout))
{
ComputeStaticFieldLayout();
}
Expand All @@ -536,7 +530,7 @@ public int NonGCStaticFieldAlignment
{
get
{
if ((_fieldLayoutFlags & FieldLayoutFlags.HasStaticFieldLayout) == 0)
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.HasStaticFieldLayout))
{
ComputeStaticFieldLayout();
}
Expand All @@ -558,7 +552,7 @@ internal void ComputeInstanceFieldLayout()
fieldAndOffset.Field.InitializeOffset(fieldAndOffset.Offset);
}

EnableFieldLayoutFlags(FieldLayoutFlags.HasInstanceFieldLayout);
_fieldLayoutFlags.AddFlags(FieldLayoutFlags.HasInstanceFieldLayout);
}

internal void ComputeStaticFieldLayout()
Expand All @@ -584,13 +578,18 @@ internal void ComputeStaticFieldLayout()
}
}

EnableFieldLayoutFlags(FieldLayoutFlags.HasStaticFieldLayout);
_fieldLayoutFlags.AddFlags(FieldLayoutFlags.HasStaticFieldLayout);
}

private bool ComputeTypeContainsPointers()
private void ComputeTypeContainsPointers()
{
int flagsToAdd = FieldLayoutFlags.HasContainsPointers;

if (!IsValueType && HasBaseType && BaseType.ContainsPointers)
return true;
{
_fieldLayoutFlags.AddFlags(flagsToAdd | FieldLayoutFlags.ContainsPointers);
return;
}

foreach (var field in GetFields())
{
Expand All @@ -606,24 +605,19 @@ private bool ComputeTypeContainsPointers()
// case TypeFlags.MethodGenericParameter?
case TypeFlags.GenericParameter:
case TypeFlags.ByRef:
return true;
_fieldLayoutFlags.AddFlags(flagsToAdd | FieldLayoutFlags.ContainsPointers);
return;
case TypeFlags.ValueType:
if (((MetadataType)fieldType).ContainsPointers)
return true;
{
_fieldLayoutFlags.AddFlags(flagsToAdd | FieldLayoutFlags.ContainsPointers);
return;
}
break;
}
}

return false;
}

private void EnableFieldLayoutFlags(int flagsToAdd)
{
var originalFlags = _fieldLayoutFlags;
while (Interlocked.CompareExchange(ref _fieldLayoutFlags, originalFlags | flagsToAdd, originalFlags) != originalFlags)
{
originalFlags = _fieldLayoutFlags;
}
_fieldLayoutFlags.AddFlags(flagsToAdd);
}
}

Expand Down
38 changes: 38 additions & 0 deletions src/TypeSystem/src/Common/ThreadSafeFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Runtime.CompilerServices;
using Interlocked = System.Threading.Interlocked;

namespace Internal.TypeSystem
{
struct ThreadSafeFlags
{
private volatile int _value;

public int Value
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return _value;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasFlags(int value)
{
return (_value & value) == value;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddFlags(int flagsToAdd)
{
var originalFlags = _value;
while (Interlocked.CompareExchange(ref _value, originalFlags | flagsToAdd, originalFlags) != originalFlags)
{
originalFlags = _value;
}
}
}
}
15 changes: 3 additions & 12 deletions src/TypeSystem/src/Ecma/EcmaField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

using Internal.TypeSystem;

using Interlocked = System.Threading.Interlocked;

namespace Internal.TypeSystem.Ecma
{
public sealed class EcmaField : FieldDesc
Expand All @@ -31,7 +29,7 @@ static class FieldFlags
FieldDefinitionHandle _handle;

// Cached values
volatile int _fieldFlags;
ThreadSafeFlags _fieldFlags;
TypeDesc _fieldType;
string _name;

Expand Down Expand Up @@ -152,22 +150,15 @@ private int InitializeFieldFlags(int mask)

Debug.Assert((flags & mask) != 0);

// Atomically update flags
var originalFlags = _fieldFlags;
while (Interlocked.CompareExchange(ref _fieldFlags, (int)(originalFlags | flags), originalFlags) != originalFlags)
{
originalFlags = _fieldFlags;
}

_fieldFlags |= flags;
_fieldFlags.AddFlags(flags);

return flags & mask;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetFieldFlags(int mask)
{
int flags = _fieldFlags & mask;
int flags = _fieldFlags.Value & mask;
if (flags != 0)
return flags;
return InitializeFieldFlags(mask);
Expand Down
1 change: 1 addition & 0 deletions src/TypeSystem/src/TypeSystem.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<Compile Include="Common\PointerType.cs" />
<Compile Include="Common\SignatureVariable.cs" />
<Compile Include="Common\TargetDetails.cs" />
<Compile Include="Common\ThreadSafeFlags.cs" />
<Compile Include="Common\TypeCast.cs" />
<Compile Include="Common\TypeFlags.cs" />
<Compile Include="Common\TypeHashingAlgorithms.cs" />
Expand Down