Skip to content

Commit

Permalink
Use BitOperations in more places (#76933)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephentoub authored Oct 14, 2022
1 parent d4f078b commit 004d732
Show file tree
Hide file tree
Showing 13 changed files with 50 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
Expand Down Expand Up @@ -45,7 +46,7 @@ internal ConcurrentQueueSegment(int boundedLength)
{
// Validate the length
Debug.Assert(boundedLength >= 2, $"Must be >= 2, got {boundedLength}");
Debug.Assert((boundedLength & (boundedLength - 1)) == 0, $"Must be a power of 2, got {boundedLength}");
Debug.Assert(BitOperations.IsPow2(boundedLength), $"Must be a power of 2, got {boundedLength}");

// Initialize the slots and the mask. The mask is used as a way of quickly doing "% _slots.Length",
// instead letting us do "& _slotsMask".
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5214,20 +5214,20 @@ public void AddTask(string name, int value)

public void AddKeyword(string name, ulong value)
{
if ((value & (value - 1)) != 0) // Is it a power of 2?
if ((value & (value - 1)) != 0) // Must be zero or a power of 2
{
ManifestError(SR.Format(SR.EventSource_KeywordNeedPowerOfTwo, "0x" + value.ToString("x", CultureInfo.CurrentCulture), name), true);
ManifestError(SR.Format(SR.EventSource_KeywordNeedPowerOfTwo, $"0x{value:x}", name), true);
}
if ((flags & EventManifestOptions.Strict) != 0)
{
if (value >= 0x0000100000000000UL && !name.StartsWith("Session", StringComparison.Ordinal))
{
ManifestError(SR.Format(SR.EventSource_IllegalKeywordsValue, name, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
ManifestError(SR.Format(SR.EventSource_IllegalKeywordsValue, name, $"0x{value:x}"));
}

if (keywordTab != null && keywordTab.TryGetValue(value, out string? prevName) && !name.Equals(prevName, StringComparison.Ordinal))
{
ManifestError(SR.Format(SR.EventSource_KeywordCollision, name, prevName, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
ManifestError(SR.Format(SR.EventSource_KeywordCollision, name, prevName, $"0x{value:x}"));
}
}

Expand Down Expand Up @@ -5590,7 +5590,7 @@ static FieldInfo[] GetEnumFields(Type localEnumType)

// ETW requires all bitmap values to be powers of 2. Skip the ones that are not.
// TODO: Warn people about the dropping of values.
if (isbitmap && ((hexValue & (hexValue - 1)) != 0 || hexValue == 0))
if (isbitmap && !BitOperations.IsPow2(hexValue))
continue;

hexValue.TryFormat(ulongHexScratch, out int charsWritten, "x");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Numerics;
using System.Threading;

namespace System.Runtime.CompilerServices
Expand Down Expand Up @@ -403,8 +403,6 @@ private void CreateEntry(TKey key, TValue value)
c.CreateEntryNoResize(key, value);
}

private static bool IsPowerOfTwo(int value) => (value > 0) && ((value & (value - 1)) == 0);

//--------------------------------------------------------------------------------------------
// Entry can be in one of four states:
//
Expand Down Expand Up @@ -462,7 +460,7 @@ private sealed class Container
internal Container(ConditionalWeakTable<TKey, TValue> parent)
{
Debug.Assert(parent != null);
Debug.Assert(IsPowerOfTwo(InitialCapacity));
Debug.Assert(BitOperations.IsPow2(InitialCapacity));

const int Size = InitialCapacity;
_buckets = new int[Size];
Expand All @@ -485,7 +483,7 @@ private Container(ConditionalWeakTable<TKey, TValue> parent, int[] buckets, Entr
Debug.Assert(buckets != null);
Debug.Assert(entries != null);
Debug.Assert(buckets.Length == entries.Length);
Debug.Assert(IsPowerOfTwo(buckets.Length));
Debug.Assert(BitOperations.IsPow2(buckets.Length));

_parent = parent;
_buckets = buckets;
Expand Down Expand Up @@ -678,7 +676,7 @@ internal Container Resize()
internal Container Resize(int newSize)
{
Debug.Assert(newSize >= _buckets.Length);
Debug.Assert(IsPowerOfTwo(newSize));
Debug.Assert(BitOperations.IsPow2(newSize));

// Reallocate both buckets and entries and rebuild the bucket and entries from scratch.
// This serves both to scrub entries with expired keys and to put the new entries in the proper bucket.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Threading;
using Debug = System.Diagnostics.Debug;
using Interlocked = System.Threading.Interlocked;
Expand Down Expand Up @@ -143,7 +144,7 @@ private sealed class XHashtableState
/// </summary>
public XHashtableState(ExtractKeyDelegate extractKey, int capacity)
{
Debug.Assert((capacity & (capacity - 1)) == 0, "capacity must be a power of 2");
Debug.Assert(BitOperations.IsPow2(capacity), "capacity must be a power of 2");
Debug.Assert(extractKey != null, "extractKey may not be null");

// Initialize hash table data structures, with specified maximum capacity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
<Compile Include="System\Xml\BinHexDecoder.cs" />
<Compile Include="System\Xml\BinHexEncoder.cs" />
<Compile Include="System\Xml\BinHexEncoderAsync.cs" />
<Compile Include="System\Xml\Bits.cs" />
<Compile Include="System\Xml\BitStack.cs" />
<Compile Include="System\Xml\ByteStack.cs" />
<Compile Include="System\Xml\Core\HtmlEncodedRawTextWriter.cs">
Expand Down
62 changes: 0 additions & 62 deletions src/libraries/System.Private.Xml/src/System/Xml/Bits.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Xml;
using System.Diagnostics;
using System.Numerics;
using System.Text;
using System.Xml;

namespace System.Xml.Schema
{
Expand Down Expand Up @@ -176,10 +177,10 @@ internal static bool TryParse(string text, XsdDateTimeFlags kinds, out XsdDateTi
/// </summary>
public XsdDateTime(DateTime dateTime, XsdDateTimeFlags kinds)
{
Debug.Assert(Bits.ExactlyOne((uint)kinds), "Only one DateTime type code can be set.");
Debug.Assert(BitOperations.IsPow2((uint)kinds), "One and only one DateTime type code can be set.");
_dt = dateTime;

DateTimeTypeCode code = (DateTimeTypeCode)(Bits.LeastPosition((uint)kinds) - 1);
DateTimeTypeCode code = (DateTimeTypeCode)BitOperations.TrailingZeroCount((uint)kinds);
int zoneHour = 0;
int zoneMinute = 0;
XsdDateTimeKind kind;
Expand Down Expand Up @@ -220,12 +221,12 @@ public XsdDateTime(DateTimeOffset dateTimeOffset) : this(dateTimeOffset, XsdDate

public XsdDateTime(DateTimeOffset dateTimeOffset, XsdDateTimeFlags kinds)
{
Debug.Assert(Bits.ExactlyOne((uint)kinds), "Only one DateTime type code can be set.");
Debug.Assert(BitOperations.IsPow2((uint)kinds), "Only one DateTime type code can be set.");

_dt = dateTimeOffset.DateTime;

TimeSpan zoneOffset = dateTimeOffset.Offset;
DateTimeTypeCode code = (DateTimeTypeCode)(Bits.LeastPosition((uint)kinds) - 1);
DateTimeTypeCode code = (DateTimeTypeCode)BitOperations.TrailingZeroCount((uint)kinds);
XsdDateTimeKind kind;
if (zoneOffset.TotalMinutes < 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Schema;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Xml.Xsl.Qil;
using System.Xml.Xsl.Runtime;
using System.Diagnostics.CodeAnalysis;
using TypeFactory = System.Xml.Xsl.XmlQueryTypeFactory;

namespace System.Xml.Xsl.IlGen
Expand Down Expand Up @@ -3263,7 +3264,7 @@ private bool MatchesNodeKinds(QilTargetType ndIsType, XmlQueryType typDerived, X
kinds = typDerived.NodeKinds & kinds;

// Attempt to allow or disallow exactly one kind
if (!Bits.ExactlyOne((uint)kinds))
if (!BitOperations.IsPow2((uint)kinds))
{
// Not possible to allow one kind, so try to disallow one kind
kinds = ~kinds & XmlNodeKindFlags.Any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Numerics;
using System.Xml.Schema;
using System.Xml.XPath;
using TF = System.Xml.Xsl.XmlQueryTypeFactory;
Expand Down Expand Up @@ -699,17 +700,20 @@ private sealed class ChoiceType : XmlQueryType
public static XmlQueryType Create(XmlNodeKindFlags nodeKinds)
{
List<XmlQueryType> members;
uint kinds = (uint)nodeKinds;

// If exactly one kind is set, then create singleton ItemType
if (Bits.ExactlyOne((uint)nodeKinds))
return ItemType.Create(s_nodeKindToTypeCode[Bits.LeastPosition((uint)nodeKinds)], false);
if (BitOperations.IsPow2(kinds))
{
return ItemType.Create(s_nodeKindToTypeCode[BitOperations.TrailingZeroCount(kinds) + 1], false);
}

members = new List<XmlQueryType>();
while (nodeKinds != XmlNodeKindFlags.None)
while (kinds != 0)
{
members.Add(ItemType.Create(s_nodeKindToTypeCode[Bits.LeastPosition((uint)nodeKinds)], false));
members.Add(ItemType.Create(s_nodeKindToTypeCode[BitOperations.TrailingZeroCount(kinds) + 1], false));

nodeKinds = (XmlNodeKindFlags)Bits.ClearLeast((uint)nodeKinds);
kinds &= kinds - 1;
}

return Create(members);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using QilName = System.Xml.Xsl.Qil.QilName;

namespace System.Xml.Xsl.Xslt
Expand Down Expand Up @@ -145,7 +146,7 @@ private void AddRecord()

private void AddRecord(ScopeFlags flag, string? ncName, string? uri, [AllowNull] V value)
{
Debug.Assert(flag == (flag & ScopeFlags.ExclusiveFlags) && (flag & (flag - 1)) == 0 && flag != 0, "One exclusive flag");
Debug.Assert(flag == (flag & ScopeFlags.ExclusiveFlags) && BitOperations.IsPow2((uint)flag), "One exclusive flag");
Debug.Assert(uri != null || ncName == null, "null, null means exclude '#all'");

ScopeFlags flags = _records[_lastRecord].flags;
Expand All @@ -164,7 +165,7 @@ private void AddRecord(ScopeFlags flag, string? ncName, string? uri, [AllowNull]

private void SetFlag(ScopeFlags flag, bool value)
{
Debug.Assert(flag == (flag & ScopeFlags.InheritedFlags) && (flag & (flag - 1)) == 0 && flag != 0, "one inherited flag");
Debug.Assert(flag == (flag & ScopeFlags.InheritedFlags) && BitOperations.IsPow2((uint)flag), "one inherited flag");
ScopeFlags flags = _records[_lastRecord].flags;
if (((flags & flag) != 0) != value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Xml.Xsl.Qil;
using System.Xml.Xsl.XPath;
using T = System.Xml.Xsl.XmlQueryTypeFactory;
Expand Down Expand Up @@ -179,7 +180,7 @@ private void NipOffTypeNameCheck()
}

XmlNodeKindFlags nodeKinds = isType.Right.XmlType!.NodeKinds;
if (!Bits.ExactlyOne((uint)nodeKinds))
if (!BitOperations.IsPow2((uint)nodeKinds))
{
return;
}
Expand Down
8 changes: 8 additions & 0 deletions src/libraries/System.Text.RegularExpressions/gen/Stubs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ namespace System.Buffers
internal delegate void SpanAction<T, in TArg>(Span<T> span, TArg arg);
}

namespace System.Numerics
{
internal static class BitOperations
{
public static bool IsPow2(int value) => (value & (value - 1)) == 0 && value > 0;
}
}

namespace System.Threading
{
internal static class InterlockedExtensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading;

Expand Down Expand Up @@ -1196,7 +1196,7 @@ public static bool IsBoundaryWordChar(char ch)
public static bool DifferByOneBit(char a, char b, out int mask)
{
mask = a ^ b;
return mask != 0 && (mask & (mask - 1)) == 0;
return BitOperations.IsPow2(mask);
}

/// <summary>Determines a character's membership in a character class (via the string representation of the class).</summary>
Expand Down

0 comments on commit 004d732

Please sign in to comment.