Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@ -1 +1 @@
1bf3586fe471a184fd2979557e4ed976454224d7
caaa20be1c251a00b9b793ebc242502485008f70

View File

@ -1 +1 @@
35fac908aaa66aff3ad8e3911047f71186a4fad7
d60a17c3bbe7b659960f9a5955fb142c298973e7

View File

@ -136,7 +136,7 @@ namespace System
if (Win32Native.RegOpenKeyEx(hklm, REG_KEY_APPCONTEXT, 0, Win32Native.KEY_READ, out hkey) == 0)
{
int size = 6; // "false".Length+1
int size = 6 * sizeof(char); // "false".Length+1 * sizeof (char) as the API expects byte count and not char count.
int type = 0;
System.Text.StringBuilder keyBuffer = new System.Text.StringBuilder((int)size);
if (Win32Native.RegQueryValueEx(hkey, switchName, null, ref type, keyBuffer, ref size) == 0)

View File

@ -1 +0,0 @@
b1b7786df7e252f1c86a96303144059702326bfa

View File

@ -323,25 +323,26 @@ namespace System.Diagnostics {
private void BuildStackFrame(int skipFrames, bool fNeedFileInfo)
{
StackFrameHelper StackF = new StackFrameHelper(fNeedFileInfo, null);
StackTrace.GetStackFramesInternal (StackF, 0, null);
int iNumOfFrames = StackF.GetNumberOfFrames();
skipFrames += StackTrace.CalculateFramesToSkip (StackF, iNumOfFrames);
if ((iNumOfFrames - skipFrames) > 0)
using (StackFrameHelper StackF = new StackFrameHelper(null))
{
method = StackF.GetMethodBase (skipFrames);
offset = StackF.GetOffset (skipFrames);
ILOffset = StackF.GetILOffset (skipFrames);
if (fNeedFileInfo)
StackF.InitializeSourceInfo(0, fNeedFileInfo, null);
int iNumOfFrames = StackF.GetNumberOfFrames();
skipFrames += StackTrace.CalculateFramesToSkip(StackF, iNumOfFrames);
if ((iNumOfFrames - skipFrames) > 0)
{
strFileName = StackF.GetFilename (skipFrames);
iLineNumber = StackF.GetLineNumber (skipFrames);
iColumnNumber = StackF.GetColumnNumber (skipFrames);
}
method = StackF.GetMethodBase(skipFrames);
offset = StackF.GetOffset(skipFrames);
ILOffset = StackF.GetILOffset(skipFrames);
if (fNeedFileInfo)
{
strFileName = StackF.GetFilename(skipFrames);
iLineNumber = StackF.GetLineNumber(skipFrames);
iColumnNumber = StackF.GetColumnNumber(skipFrames);
}
}
}
}
}

View File

@ -23,7 +23,7 @@ namespace System.Diagnostics {
// to the unmanaged definition of the StackFrameHelper class, in
// VM\DebugDebugger.h. The binder will catch some of these layout problems.
[Serializable]
internal class StackFrameHelper
internal class StackFrameHelper : IDisposable
{
[NonSerialized]
private Thread targetThread;
@ -32,14 +32,20 @@ namespace System.Diagnostics {
// this field is here only for backwards compatibility of serialization format
private MethodBase[] rgMethodBase;
#pragma warning disable 414 // Field is not used from managed.
#pragma warning disable 414
// dynamicMethods is an array of System.Resolver objects, used to keep
// DynamicMethodDescs alive for the lifetime of StackFrameHelper.
private Object dynamicMethods;
#pragma warning restore 414
private Object dynamicMethods; // Field is not used from managed.
[NonSerialized]
private IntPtr[] rgMethodHandle;
private String[] rgAssemblyPath;
private IntPtr[] rgLoadedPeAddress;
private int[] rgiLoadedPeSize;
private IntPtr[] rgInMemoryPdbAddress;
private int[] rgiInMemoryPdbSize;
// if rgiMethodToken[i] == 0, then don't attempt to get the portable PDB source/info
private int[] rgiMethodToken;
private String[] rgFilename;
private int[] rgiLineNumber;
private int[] rgiColumnNumber;
@ -47,21 +53,38 @@ namespace System.Diagnostics {
[OptionalField]
private bool[] rgiLastFrameFromForeignExceptionStackTrace;
#endif // FEATURE_EXCEPTIONDISPATCHINFO
private GetSourceLineInfoDelegate getSourceLineInfo;
private int iFrameCount;
private bool fNeedFileInfo;
#pragma warning restore 414
private delegate void GetSourceLineInfoDelegate(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize,
IntPtr inMemoryPdbAddress, int inMemoryPdbSize, int methodToken, int ilOffset,
out string sourceFile, out int sourceLine, out int sourceColumn);
private static Type s_symbolsType = null;
private static MethodInfo s_symbolsMethodInfo = null;
[ThreadStatic]
private static int t_reentrancy = 0;
public StackFrameHelper(bool fNeedFileLineColInfo, Thread target)
public StackFrameHelper(Thread target)
{
targetThread = target;
rgMethodBase = null;
rgMethodHandle = null;
rgiMethodToken = null;
rgiOffset = null;
rgiILOffset = null;
rgAssemblyPath = null;
rgLoadedPeAddress = null;
rgiLoadedPeSize = null;
rgInMemoryPdbAddress = null;
rgiInMemoryPdbSize = null;
dynamicMethods = null;
rgFilename = null;
rgiLineNumber = null;
rgiColumnNumber = null;
dynamicMethods = null;
getSourceLineInfo = null;
#if FEATURE_EXCEPTIONDISPATCHINFO
rgiLastFrameFromForeignExceptionStackTrace = null;
@ -75,10 +98,99 @@ namespace System.Diagnostics {
// limit in the future, then we should expose it in the managed API so applications can
// override it.
iFrameCount = 0;
fNeedFileInfo = fNeedFileLineColInfo;
}
//
// Initializes the stack trace helper. If fNeedFileInfo is true, initializes rgFilename,
// rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already
// done by GetStackFramesInternal (on Windows for old PDB format).
//
[SecuritySafeCritical]
internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exception)
{
StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception);
if (!fNeedFileInfo)
return;
// Check if this function is being reentered because of an exception in the code below
if (t_reentrancy > 0)
return;
t_reentrancy++;
try
{
// need private reflection below
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
if (s_symbolsMethodInfo == null)
{
s_symbolsType = Type.GetType(
"System.Diagnostics.StackTraceSymbols, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
throwOnError: false);
if (s_symbolsType == null)
{
return;
}
s_symbolsMethodInfo = s_symbolsType.GetMethod("GetSourceLineInfo",
new Type[] { typeof(string),
typeof(IntPtr),
typeof(int),
typeof(IntPtr),
typeof(int),
typeof(int),
typeof(int),
typeof(string).MakeByRefType(),
typeof(int).MakeByRefType(),
typeof(int).MakeByRefType() });
if (s_symbolsMethodInfo == null)
return;
}
if (getSourceLineInfo == null)
{
// Create an instance of System.Diagnostics.Stacktrace.Symbols
object target = Activator.CreateInstance(s_symbolsType);
// Create an instance delegate for the GetSourceLineInfo method
getSourceLineInfo = (GetSourceLineInfoDelegate)s_symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target);
}
for (int index = 0; index < iFrameCount; index++)
{
// If there was some reason not to try get get the symbols from the portable PDB reader like the module was
// ENC or the source/line info was already retrieved, the method token is 0.
if (rgiMethodToken[index] != 0)
{
getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index],
rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index],
rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]);
}
}
}
catch
{
}
finally
{
t_reentrancy--;
}
}
void IDisposable.Dispose()
{
if (getSourceLineInfo != null)
{
IDisposable disposable = getSourceLineInfo.Target as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
[System.Security.SecuritySafeCritical]
public virtual MethodBase GetMethodBase(int i)
{
@ -99,9 +211,9 @@ namespace System.Diagnostics {
public virtual int GetOffset(int i) { return rgiOffset[i];}
public virtual int GetILOffset(int i) { return rgiILOffset[i];}
public virtual String GetFilename(int i) { return rgFilename[i];}
public virtual int GetLineNumber(int i) { return rgiLineNumber[i];}
public virtual int GetColumnNumber(int i) { return rgiColumnNumber[i];}
public virtual String GetFilename(int i) { return rgFilename == null ? null : rgFilename[i];}
public virtual int GetLineNumber(int i) { return rgiLineNumber == null ? 0 : rgiLineNumber[i];}
public virtual int GetColumnNumber(int i) { return rgiColumnNumber == null ? 0 : rgiColumnNumber[i];}
#if FEATURE_EXCEPTIONDISPATCHINFO
public virtual bool IsLastFrameFromForeignExceptionStackTrace(int i)
@ -344,11 +456,10 @@ namespace System.Diagnostics {
[System.Security.SecuritySafeCritical]
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, Exception e);
internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception e);
internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrames)
{
int iRetVal = 0;
String PackageName = "System.Diagnostics";
@ -378,63 +489,63 @@ namespace System.Diagnostics {
// Retrieves an object with stack trace information encoded.
// It leaves out the first "iSkip" lines of the stacktrace.
//
private void CaptureStackTrace(int iSkip, bool fNeedFileInfo, Thread targetThread,
Exception e)
private void CaptureStackTrace(int iSkip, bool fNeedFileInfo, Thread targetThread, Exception e)
{
m_iMethodsToSkip += iSkip;
StackFrameHelper StackF = new StackFrameHelper(fNeedFileInfo, targetThread);
GetStackFramesInternal(StackF, 0, e);
m_iNumOfFrames = StackF.GetNumberOfFrames();
if (m_iMethodsToSkip > m_iNumOfFrames)
m_iMethodsToSkip = m_iNumOfFrames;
if (m_iNumOfFrames != 0)
using (StackFrameHelper StackF = new StackFrameHelper(targetThread))
{
frames = new StackFrame[m_iNumOfFrames];
StackF.InitializeSourceInfo(0, fNeedFileInfo, e);
for (int i = 0; i < m_iNumOfFrames; i++)
m_iNumOfFrames = StackF.GetNumberOfFrames();
if (m_iMethodsToSkip > m_iNumOfFrames)
m_iMethodsToSkip = m_iNumOfFrames;
if (m_iNumOfFrames != 0)
{
bool fDummy1 = true;
bool fDummy2 = true;
StackFrame sfTemp = new StackFrame(fDummy1, fDummy2);
frames = new StackFrame[m_iNumOfFrames];
sfTemp.SetMethodBase(StackF.GetMethodBase(i));
sfTemp.SetOffset(StackF.GetOffset(i));
sfTemp.SetILOffset(StackF.GetILOffset(i));
for (int i = 0; i < m_iNumOfFrames; i++)
{
bool fDummy1 = true;
bool fDummy2 = true;
StackFrame sfTemp = new StackFrame(fDummy1, fDummy2);
sfTemp.SetMethodBase(StackF.GetMethodBase(i));
sfTemp.SetOffset(StackF.GetOffset(i));
sfTemp.SetILOffset(StackF.GetILOffset(i));
#if FEATURE_EXCEPTIONDISPATCHINFO
sfTemp.SetIsLastFrameFromForeignExceptionStackTrace(StackF.IsLastFrameFromForeignExceptionStackTrace(i));
#endif // FEATURE_EXCEPTIONDISPATCHINFO
if (fNeedFileInfo)
{
sfTemp.SetFileName(StackF.GetFilename (i));
sfTemp.SetLineNumber(StackF.GetLineNumber(i));
sfTemp.SetColumnNumber(StackF.GetColumnNumber(i));
}
if (fNeedFileInfo)
{
sfTemp.SetFileName(StackF.GetFilename(i));
sfTemp.SetLineNumber(StackF.GetLineNumber(i));
sfTemp.SetColumnNumber(StackF.GetColumnNumber(i));
}
frames[i] = sfTemp;
frames[i] = sfTemp;
}
// CalculateFramesToSkip skips all frames in the System.Diagnostics namespace,
// but this is not desired if building a stack trace from an exception.
if (e == null)
m_iMethodsToSkip += CalculateFramesToSkip(StackF, m_iNumOfFrames);
m_iNumOfFrames -= m_iMethodsToSkip;
if (m_iNumOfFrames < 0)
{
m_iNumOfFrames = 0;
}
}
// CalculateFramesToSkip skips all frames in the System.Diagnostics namespace,
// but this is not desired if building a stack trace from an exception.
if (e == null)
m_iMethodsToSkip += CalculateFramesToSkip(StackF, m_iNumOfFrames);
m_iNumOfFrames -= m_iMethodsToSkip;
if (m_iNumOfFrames < 0)
{
m_iNumOfFrames = 0;
}
// In case this is the same object being re-used, set frames to null
else
frames = null;
}
// In case this is the same object being re-used, set frames to null
else
frames = null;
}
// Property to get the number of frames in the stack trace

View File

@ -103,6 +103,16 @@ namespace System {
return (*(UInt64*)(&d) & 0x7FFFFFFFFFFFFFFFL) > 0x7FF0000000000000L;
}
#if MONO
[Pure]
[System.Runtime.Versioning.NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static bool IsFinite(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
return (bits & 0x7FFFFFFFFFFFFFFF) < 0x7FF0000000000000;
}
#endif
// Compares this object to another object, returning an instance of System.Relation.
// Null is considered less than any instance.

View File

@ -358,6 +358,25 @@ namespace System.Globalization {
this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
}
private CultureInfo(CultureData cultureData)
{
Contract.Assert(cultureData != null);
m_cultureData = cultureData;
m_name = cultureData.CultureName;
m_isInherited = false;
}
private static CultureInfo CreateCultureInfoNoThrow(string name, bool useUserOverride)
{
Contract.Assert(name != null);
CultureData cultureData = CultureData.GetCultureData(name, useUserOverride);
if (cultureData == null)
{
return null;
}
return new CultureInfo(cultureData);
}
#if FEATURE_USE_LCID
public CultureInfo(int culture) : this(culture, true) {
@ -958,29 +977,29 @@ namespace System.Globalization {
get
{
Contract.Ensures(Contract.Result<CultureInfo>() != null);
CultureInfo culture = null;
if (null == m_parent)
{
try
{
string parentName = this.m_cultureData.SPARENT;
string parentName = this.m_cultureData.SPARENT;
if (String.IsNullOrEmpty(parentName))
{
m_parent = InvariantCulture;
}
else
{
m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride);
}
}
catch (ArgumentException)
if (String.IsNullOrEmpty(parentName))
{
// For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
// We can't allow ourselves to fail. In case of custom cultures the parent of the
// current custom culture isn't installed.
m_parent = InvariantCulture;
culture = InvariantCulture;
}
else
{
culture = CreateCultureInfoNoThrow(parentName, m_cultureData.UseUserOverride);
if (culture == null)
{
// For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
// We can't allow ourselves to fail. In case of custom cultures the parent of the
// current custom culture isn't installed.
culture = InvariantCulture;
}
}
Interlocked.CompareExchange<CultureInfo>(ref m_parent, culture, null);
}
return m_parent;
}

View File

@ -22,7 +22,6 @@ namespace System.Globalization {
** Taiwan 01/01/01 8088/12/31
============================================================================*/
[System.Runtime.InteropServices.ComVisible(true)]
[Serializable] public class TaiwanCalendar: Calendar {
//

View File

@ -40,7 +40,7 @@ namespace System.IO {
[ContractClass(typeof(StreamContract))]
#endif
#if FEATURE_REMOTING || MONO
public abstract class Stream : MarshalByRefObject, IDisposable {
public abstract partial class Stream : MarshalByRefObject, IDisposable {
#else // FEATURE_REMOTING
public abstract class Stream : IDisposable {
#endif // FEATURE_REMOTING
@ -195,6 +195,9 @@ namespace System.IO {
InternalCopyTo(destination, _DefaultCopyBufferSize);
}
#if MONO
virtual
#endif
public void CopyTo(Stream destination, int bufferSize)
{
if (destination == null)

View File

@ -48,10 +48,19 @@ namespace System {
if (ClassName == null) {
return base.Message;
} else {
#if MONO
string res = ClassName + "." + MemberName;
if (!string.IsNullOrEmpty(signature))
res = string.Format (CultureInfo.InvariantCulture, signature, res);
if (!string.IsNullOrEmpty(_message))
res += " Due to: " + _message;
return res;
#else
// do any desired fixups to classname here.
return Environment.GetResourceString("MissingMethod_Name",
ClassName + "." + MemberName +
(Signature != null ? " " + FormatSignature(Signature) : ""));
#endif
}
}
}
@ -73,5 +82,17 @@ namespace System {
// If ClassName != null, Message will construct on the fly using it
// and the other variables. This allows customization of the
// format depending on the language environment.
#if MONO
// Called from the EE
private MissingMethodException(String className, String methodName, String signature, String message) : base (message)
{
ClassName = className;
MemberName = methodName;
this.signature = signature;
}
[NonSerialized]
string signature;
#endif
}
}

View File

@ -1,60 +0,0 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// <OWNER>[....]</OWNER>
// <OWNER>[....]</OWNER>
// <OWNER>[....]</OWNER>
using System;
namespace System.Runtime.InteropServices.WindowsRuntime
{
[ComImport]
[Guid("629bdbc8-d932-4ff4-96b9-8d96c5c1e858")]
[WindowsRuntimeImport]
internal interface IPropertyValueFactory
{
IPropertyValue CreateEmpty();
IPropertyValue CreateUInt8(byte value);
IPropertyValue CreateInt16(short value);
IPropertyValue CreateUInt16(ushort value);
IPropertyValue CreateInt32(int value);
IPropertyValue CreateUInt32(uint value);
IPropertyValue CreateInt64(long value);
IPropertyValue CreateUInt64(ulong value);
IPropertyValue CreateSingle(float value);
IPropertyValue CreateDouble(double value);
IPropertyValue CreateChar16(char value);
IPropertyValue CreateBoolean(bool value);
IPropertyValue CreateString(string value);
IPropertyValue CreateInspectable(object value);
IPropertyValue CreateGuid(Guid value);
IPropertyValue CreateDateTime(DateTimeOffset value);
IPropertyValue CreateTimeSpan(TimeSpan value);
IPropertyValue CreatePoint(Point value);
IPropertyValue CreateSize(Size value);
IPropertyValue CreateRect(Rect value);
IPropertyValue CreateUInt8Array(byte[] value);
IPropertyValue CreateInt16Array(short[] value);
IPropertyValue CreateUInt16Array(ushort[] value);
IPropertyValue CreateInt32Array(Int32[] value);
IPropertyValue CreateUInt32Array(UInt32[] value);
IPropertyValue CreateInt64Array(Int64[] value);
IPropertyValue CreateUInt64Array(UInt64[] value);
IPropertyValue CreateSingleArray(Single[] value);
IPropertyValue CreateDoubleArray(Double[] value);
IPropertyValue CreateChar16Array(Char[] value);
IPropertyValue CreateBooleanArray(Boolean[] value);
IPropertyValue CreateStringArray(String[] value);
IPropertyValue CreateInspectableArray(Object[] value);
IPropertyValue CreateGuidArray(Guid[] value);
IPropertyValue CreateDateTimeArray(DateTimeOffset[] value);
IPropertyValue CreateTimeSpanArray(TimeSpan[] value);
IPropertyValue CreatePointArray(Point[] value);
IPropertyValue CreateSizeArray(Size[] value);
IPropertyValue CreateRectArray(Rect[] value);
}
}

View File

@ -76,6 +76,15 @@ namespace System {
return (*(int*)(&f) & 0x7FFFFFFF) > 0x7F800000;
}
#if MONO
[Pure]
[System.Runtime.Versioning.NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static bool IsFinite(float f) {
return (*(int*)(&f) & 0x7FFFFFFF) < 0x7F800000;
}
#endif
// Compares this object to another object, returning an integer that
// indicates the relationship.
// Returns a value less than zero if this object

View File

@ -133,31 +133,46 @@ namespace System {
, IWellKnownStringEqualityComparer
#endif
{
private CompareInfo _compareInfo;
private bool _ignoreCase;
[OptionalField]
private CompareOptions _options;
internal CultureAwareComparer(CultureInfo culture, bool ignoreCase) {
_compareInfo = culture.CompareInfo;
_ignoreCase = ignoreCase;
_options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
}
internal CultureAwareComparer(CompareInfo compareInfo, bool ignoreCase) {
_compareInfo = compareInfo;
_ignoreCase = ignoreCase;
_options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
}
internal CultureAwareComparer(CompareInfo compareInfo, CompareOptions options) {
_compareInfo = compareInfo;
_options = options;
// set the _ignoreCase flag to preserve compat in case this type is serialized on a
// newer version of the framework and deserialized on an older version of the framework
_ignoreCase = ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase ||
(options & CompareOptions.OrdinalIgnoreCase ) == CompareOptions.OrdinalIgnoreCase);
}
public override int Compare(string x, string y) {
if (Object.ReferenceEquals(x, y)) return 0;
if (x == null) return -1;
if (y == null) return 1;
return _compareInfo.Compare(x, y, _ignoreCase? CompareOptions.IgnoreCase : CompareOptions.None);
return _compareInfo.Compare(x, y, _options);
}
public override bool Equals(string x, string y) {
if (Object.ReferenceEquals(x ,y)) return true;
if (x == null || y == null) return false;
return (_compareInfo.Compare(x, y, _ignoreCase? CompareOptions.IgnoreCase : CompareOptions.None) == 0);
return (_compareInfo.Compare(x, y, _options) == 0);
}
public override int GetHashCode(string obj) {
@ -166,13 +181,7 @@ namespace System {
}
Contract.EndContractBlock();
CompareOptions options = CompareOptions.None;
if( _ignoreCase) {
options |= CompareOptions.IgnoreCase;
}
return _compareInfo.GetHashCodeOfString(obj, options);
return _compareInfo.GetHashCodeOfString(obj, _options);
}
// Equals method for the comparer itself.
@ -181,7 +190,8 @@ namespace System {
if( comparer == null) {
return false;
}
return (this._ignoreCase == comparer._ignoreCase) && (this._compareInfo.Equals(comparer._compareInfo));
return (this._ignoreCase == comparer._ignoreCase) && (this._compareInfo.Equals(comparer._compareInfo)
&& this._options == comparer._options);
}
public override int GetHashCode() {

View File

@ -124,7 +124,7 @@ namespace System.Text
0xD800, 0xDBFF));
if (!Char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException("CharUnknownLow",
throw new ArgumentOutOfRangeException("charUnknownLow",
Environment.GetResourceString("ArgumentOutOfRange_Range",
0xDC00, 0xDFFF));
Contract.EndContractBlock();

View File

@ -70,7 +70,7 @@ namespace System.Text
}
if (!Char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException("CharUnknownLow",
throw new ArgumentOutOfRangeException("charUnknownLow",
Environment.GetResourceString("ArgumentOutOfRange_Range",
0xDC00, 0xDFFF));
}
@ -153,7 +153,7 @@ namespace System.Text
}
if (!Char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException("CharUnknownLow",
throw new ArgumentOutOfRangeException("charUnknownLow",
Environment.GetResourceString("ArgumentOutOfRange_Range",
0xDC00, 0xDFFF));
}

View File

@ -155,7 +155,7 @@ namespace System.Text
0xD800, 0xDBFF));
if (!Char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException("CharUnknownLow",
throw new ArgumentOutOfRangeException("charUnknownLow",
Environment.GetResourceString("ArgumentOutOfRange_Range",
0xDC00, 0xDFFF));
Contract.EndContractBlock();

View File

@ -16,6 +16,7 @@
using System;
using System.Threading;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
#pragma warning disable 0420
@ -24,6 +25,7 @@ namespace System.Threading.Tasks
/// <summary>
/// Represents an index range
/// </summary>
[StructLayout(LayoutKind.Auto)]
internal struct IndexRange
{
// the From and To values for this range. These do not change.
@ -32,7 +34,11 @@ namespace System.Threading.Tasks
// The shared index, stored as the offset from nFromInclusive. Using an offset rather than the actual
// value saves us from overflows that can happen due to multiple workers racing to increment this.
// All updates to this field need to be interlocked.
// All updates to this field need to be interlocked. To avoid split interlockeds across cache-lines
// in 32-bit processes, in 32-bit processes when the range fits in a 32-bit value, we prefer to use
// a 32-bit field, and just use the first 32-bits of the long. And to minimize false sharing, each
// value is stored in its own heap-allocated object, which is lazily allocated by the thread using
// that range, minimizing the chances it'll be near the objects from other threads.
internal volatile Shared<long> m_nSharedCurrentIndexOffset;
// to be set to 1 by the worker that finishes this range. It's OK to do a non-interlocked write here.
@ -43,6 +49,7 @@ namespace System.Threading.Tasks
/// <summary>
/// The RangeWorker struct wraps the state needed by a task that services the parallel loop
/// </summary>
[StructLayout(LayoutKind.Auto)]
internal struct RangeWorker
{
// reference to the IndexRange array allocated by the range manager
@ -61,13 +68,17 @@ namespace System.Threading.Tasks
// the increment value is doubled each time this worker finds work, and is capped at this value
internal readonly long m_nMaxIncrementValue;
// whether to use 32-bits or 64-bits of current index in each range
internal readonly bool _use32BitCurrentIndex;
/// <summary>
/// Initializes a RangeWorker struct
/// </summary>
internal RangeWorker(IndexRange[] ranges, int nInitialRange, long nStep)
internal RangeWorker(IndexRange[] ranges, int nInitialRange, long nStep, bool use32BitCurrentIndex)
{
m_indexRanges = ranges;
m_nCurrentIndexRange = nInitialRange;
_use32BitCurrentIndex = use32BitCurrentIndex;
m_nStep = nStep;
m_nIncrementValue = nStep;
@ -104,8 +115,24 @@ namespace System.Threading.Tasks
}
// this access needs to be on the array slot
long nMyOffset = Interlocked.Add(ref m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset.Value,
m_nIncrementValue) - m_nIncrementValue;
long nMyOffset;
if (IntPtr.Size == 4 && _use32BitCurrentIndex)
{
// In 32-bit processes, we prefer to use 32-bit interlocked operations, to avoid the possibility of doing
// a 64-bit interlocked when the target value crosses a cache line, as that can be super expensive.
// We use the first 32 bits of the Int64 index in such cases.
unsafe
{
fixed (long* indexPtr = &m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset.Value)
{
nMyOffset = Interlocked.Add(ref *(int*)indexPtr, (int)m_nIncrementValue) - m_nIncrementValue;
}
}
}
else
{
nMyOffset = Interlocked.Add(ref m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset.Value, m_nIncrementValue) - m_nIncrementValue;
}
if (currentRange.m_nToExclusive - currentRange.m_nFromInclusive > nMyOffset)
{
@ -187,6 +214,7 @@ namespace System.Threading.Tasks
internal class RangeManager
{
internal readonly IndexRange[] m_indexRanges;
internal readonly bool _use32BitCurrentIndex;
internal int m_nCurrentIndexRangeToAssign;
internal long m_nStep;
@ -234,6 +262,7 @@ namespace System.Threading.Tasks
// Convert to signed so the rest of the logic works.
// Should be fine so long as uRangeSize < Int64.MaxValue, which we guaranteed by setting #workers >= 2.
long nRangeSize = (long)uRangeSize;
_use32BitCurrentIndex = IntPtr.Size == 4 && nRangeSize <= int.MaxValue;
// allocate the array of index ranges
m_indexRanges = new IndexRange[nNumRanges];
@ -274,7 +303,7 @@ namespace System.Threading.Tasks
int nInitialRange = (Interlocked.Increment(ref m_nCurrentIndexRangeToAssign) - 1) % m_indexRanges.Length;
return new RangeWorker(m_indexRanges, nInitialRange, m_nStep);
return new RangeWorker(m_indexRanges, nInitialRange, m_nStep, _use32BitCurrentIndex);
}
}
}

View File

@ -1 +1 @@
0ca6568e9fbbe9f32c8048eca0973d09bcb98996
8638327150a075ac05d1173af19b1c7d862a30e3

View File

@ -1 +1 @@
b15df277ab4b1bde5025f55ca2d78d2e066722e2
de78cb0b18239aafe6c7a8caab4112989cc0690c

Some files were not shown because too many files have changed in this diff Show More