Skip to content
Closed
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
17 changes: 17 additions & 0 deletions THIRDPARTYNOTICES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,20 @@ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
-------------------------------

License for fastmod (https://github.com/lemire/fastmod), ibm-fpgen (https://github.com/nigeltao/parse-number-fxx-test-data) and fastrange (https://github.com/lemire/fastrange)
--------------------------------------

Copyright 2018 Daniel Lemire

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file line number Diff line number Diff line change
Expand Up @@ -1322,9 +1322,9 @@ private int GetNextBuildRequestId()
/// <param name="config">The configuration to be mapped.</param>
private void IssueConfigurationRequest(BuildRequestConfiguration config)
{
ErrorUtilities.VerifyThrowArgument(config.WasGeneratedByNode, "InvalidConfigurationId");
ErrorUtilities.VerifyThrow(config.WasGeneratedByNode, "InvalidConfigurationId");
ErrorUtilities.VerifyThrowArgumentNull(config, nameof(config));
ErrorUtilities.VerifyThrowInvalidOperation(_unresolvedConfigurations.HasConfiguration(config.ConfigurationId), "NoUnresolvedConfiguration");
ErrorUtilities.VerifyThrow(_unresolvedConfigurations.HasConfiguration(config.ConfigurationId), "NoUnresolvedConfiguration");
TraceEngine("Issuing configuration request for node config {0}", config.ConfigurationId);
RaiseNewConfigurationRequest(config);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Build/BackEnd/Components/Caching/ResultsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void ClearResults()
/// <returns>The build results for the specified request.</returns>
public BuildResult GetResultForRequest(BuildRequest request)
{
ErrorUtilities.VerifyThrowArgument(request.IsConfigurationResolved, "UnresolvedConfigurationInRequest");
ErrorUtilities.VerifyThrow(request.IsConfigurationResolved, "UnresolvedConfigurationInRequest");

lock (_resultsByConfiguration)
{
Expand Down Expand Up @@ -155,7 +155,7 @@ public BuildResult GetResultsForConfiguration(int configurationId)
/// <returns>A response indicating the results, if any, and the targets needing to be built, if any.</returns>
public ResultsCacheResponse SatisfyRequest(BuildRequest request, List<string> configInitialTargets, List<string> configDefaultTargets, bool skippedResultsDoNotCauseCacheMiss)
{
ErrorUtilities.VerifyThrowArgument(request.IsConfigurationResolved, "UnresolvedConfigurationInRequest");
ErrorUtilities.VerifyThrow(request.IsConfigurationResolved, "UnresolvedConfigurationInRequest");
ResultsCacheResponse response = new ResultsCacheResponse(ResultsCacheResponseType.NotSatisfied);

lock (_resultsByConfiguration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ public static T FactoryForDeserializingTypeWithName<T>(this ITranslator translat
translator.Translate(ref typeName);

var type = Type.GetType(typeName);
ErrorUtilities.VerifyThrowInvalidOperation(type != null, "type cannot be null");
ErrorUtilities.VerifyThrowInvalidOperation(
ErrorUtilities.VerifyThrow(type != null, "type cannot be null");
ErrorUtilities.VerifyThrow(
typeof(T).IsAssignableFrom(type),
$"{typeName} must be a {typeof(T).FullName}");
ErrorUtilities.VerifyThrowInvalidOperation(
ErrorUtilities.VerifyThrow(
typeof(ITranslatable).IsAssignableFrom(type),
$"{typeName} must be a {nameof(ITranslatable)}");

Expand All @@ -85,9 +85,9 @@ public static T FactoryForDeserializingTypeWithName<T>(this ITranslator translat
{
ConstructorInfo constructor = null;
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
ErrorUtilities.VerifyThrowInvalidOperation(
ErrorUtilities.VerifyThrow(
constructor != null,
$"{typeName} must have a private parameterless constructor");
"{0} must have a private parameterless constructor", typeName);
return constructor;
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from Hashset, untested here. And hopefully going away soon with your use of BinaryFormatter.

// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
// Used by Hashtable and Dictionary's SerializationInfo .ctor's to store the SerializationInfo
// object until OnDeserialization is called.
using System.Threading;

namespace System.Collections
{
internal static partial class HashHelpers
{
private static ConditionalWeakTable<object, SerializationInfo>? s_serializationInfoTable;

public static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
{
get
{
if (s_serializationInfoTable == null)
{
_ = Interlocked.CompareExchange(ref s_serializationInfoTable, new ConditionalWeakTable<object, SerializationInfo>(), null);
}

return s_serializationInfoTable;
}
}
}
}
110 changes: 63 additions & 47 deletions src/Build/Collections/RetrievableEntryHashSet/HashHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
#if !SILVERLIGHT
#if FEATURE_CONSTRAINED_EXECUTION
using System.Runtime.ConstrainedExecution;
#endif
#endif
using System.Runtime.CompilerServices;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically verbatim from runtime copy


#nullable disable

namespace Microsoft.Build.Collections
namespace System.Collections
{
/// <summary>
/// Duplicated because internal to mscorlib
/// </summary>
internal static class HashHelpers
internal static partial class HashHelpers
{
// Table of prime numbers to use as hash table sizes.
// The entry used for capacity is the smallest prime number in this array
// that is larger than twice the previous capacity.
// This is the maximum prime smaller than Array.MaxLength.
public const int MaxPrimeArrayLength = 0x7FFFFFC3;

public const int HashPrime = 101;

internal static readonly int[] primes = {
// Table of prime numbers to use as hash table sizes.
// A typical resize algorithm would pick the smallest prime number in this array
// that is larger than twice the previous capacity.
// Suppose our Hashtable currently has capacity x and enough elements are added
// such that a resize needs to occur. Resizing first computes 2x then finds the
// first prime in the table greater than 2x, i.e. if primes are ordered
// p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n.
// Doubling is important for preserving the asymptotic complexity of the
// hashtable operations such as add. Having a prime guarantees that double
// hashing does not lead to infinite loops. IE, your hash function will be
// h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
// We prefer the low computation costs of higher prime numbers over the increased
// memory allocation of a fixed prime number i.e. when right sizing a HashSet.
internal static ReadOnlySpan<int> Primes => new int[]
{
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};

#if !SILVERLIGHT
#if FEATURE_CONSTRAINED_EXECUTION
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
#endif
internal static bool IsPrime(int candidate)
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369
};

public static bool IsPrime(int candidate)
{
if ((candidate & 1) != 0)
{
Expand All @@ -46,61 +47,76 @@ internal static bool IsPrime(int candidate)
return false;
}
}

return true;
}

return candidate == 2;
}

#if !SILVERLIGHT
#if FEATURE_CONSTRAINED_EXECUTION
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
#endif
internal static int GetPrime(int min)
public static int GetPrime(int min)
{
Debug.Assert(min >= 0, "min less than zero; handle overflow checking before calling HashHelpers");
if (min < 0)
{
throw new ArgumentException();
}

for (int i = 0; i < primes.Length; i++)
foreach (int prime in Primes)
{
int prime = primes[i];
if (prime >= min)
{
return prime;
}
}

// Outside of our predefined table. Compute the hard way.
for (int i = (min | 1); i < Int32.MaxValue; i += 2)
// Outside of our predefined table. Compute the hard way.
for (int i = min | 1; i < int.MaxValue; i += 2)
{
if (IsPrime(i))
if (IsPrime(i) && ((i - 1) % HashPrime != 0))
{
return i;
}
}
return min;
}

internal static int GetMinPrime()
{
return primes[0];
return min;
}

// Returns size of hashtable to grow to.
internal static int ExpandPrime(int oldSize)
public static int ExpandPrime(int oldSize)
{
int newSize = 2 * oldSize;

// Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
// Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newSize > MaxPrimeArrayLength)
if ((uint)newSize > MaxPrimeArrayLength && oldSize < MaxPrimeArrayLength)
{
Debug.Assert(GetPrime(MaxPrimeArrayLength) == MaxPrimeArrayLength, "Invalid MaxPrimeArrayLength");
return MaxPrimeArrayLength;
}

return GetPrime(newSize);
}

// This is the maximum prime smaller than Array.MaxArrayLength
internal const int MaxPrimeArrayLength = 0x7FEFFFFD;
/// <summary>Returns approximate reciprocal of the divisor: ceil(2**64 / divisor).</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment here is what I was referring to. it works on 32 bit, IIRC this is here because on 32 bit the multiply below is less efficient . @stephentoub there's no correctness issue here, right? they don't have the benefit of #if BIT64 in this project. My assumption is that the vast majority of their use is 64 bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no correctness issue here, right

Correct

public static ulong GetFastModMultiplier(uint divisor) =>
(ulong.MaxValue / divisor) + 1;

/// <summary>Performs a mod operation using the multiplier pre-computed with <see cref="GetFastModMultiplier"/>.</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FastMod(uint value, uint divisor, ulong multiplier)
{
// We use modified Daniel Lemire's fastmod algorithm,
// which allows to avoid the long multiplication if the divisor is less than 2**31.
Debug.Assert(divisor <= int.MaxValue);

// This is equivalent of (uint)Math.BigMul(multiplier * value, divisor, out _). This version
// is faster than BigMul currently because we only need the high bits.
uint highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32);

Debug.Assert(highbits == value % divisor);
return highbits;
}
}
}
Loading