You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
173
external/referencesource/mscorlib/system/AppContext/AppContext.cs
vendored
Normal file
173
external/referencesource/mscorlib/system/AppContext/AppContext.cs
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System
|
||||
{
|
||||
public static class AppContext
|
||||
{
|
||||
[Flags]
|
||||
private enum SwitchValueState
|
||||
{
|
||||
HasFalseValue = 0x1,
|
||||
HasTrueValue = 0x2,
|
||||
HasLookedForOverride = 0x4,
|
||||
UnknownValue = 0x8 // Has no default and could not find an override
|
||||
}
|
||||
private static Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
|
||||
private static readonly object s_syncLock = new object();
|
||||
|
||||
public static string BaseDirectory
|
||||
{
|
||||
#if FEATURE_CORECLR
|
||||
[System.Security.SecuritySafeCritical]
|
||||
#endif
|
||||
get
|
||||
{
|
||||
// The value of APP_CONTEXT_BASE_DIRECTORY key has to be a string and it is not allowed to be any other type.
|
||||
// Otherwise the caller will get invalid cast exception
|
||||
return (string) AppDomain.CurrentDomain.GetData("APP_CONTEXT_BASE_DIRECTORY") ?? AppDomain.CurrentDomain.BaseDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
#region Switch APIs
|
||||
|
||||
static AppContext()
|
||||
{
|
||||
// populate the AppContext with the default set of values
|
||||
AppContextDefaultValues.PopulateDefaultValues();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get the value of the switch.
|
||||
/// </summary>
|
||||
/// <param name="switchName">The name of the switch</param>
|
||||
/// <param name="isEnabled">A variable where to place the value of the switch</param>
|
||||
/// <returns>A return value of true represents that the switch was set and <paramref name="isEnabled"/> contains the value of the switch</returns>
|
||||
public static bool TryGetSwitch(string switchName, out bool isEnabled)
|
||||
{
|
||||
if (switchName == null)
|
||||
throw new ArgumentNullException("switchName");
|
||||
if (switchName.Length == 0)
|
||||
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName");
|
||||
|
||||
// By default, the switch is not enabled.
|
||||
isEnabled = false;
|
||||
|
||||
SwitchValueState switchValue;
|
||||
lock (s_switchMap)
|
||||
{
|
||||
if (s_switchMap.TryGetValue(switchName, out switchValue))
|
||||
{
|
||||
// The value is in the dictionary.
|
||||
// There are 3 cases here:
|
||||
// 1. The value of the switch is 'unknown'. This means that the switch name is not known to the system (either via defaults or checking overrides).
|
||||
// Example: This is the case when, during a servicing event, a switch is added to System.Xml which ships before mscorlib. The value of the switch
|
||||
// Will be unknown to mscorlib.dll and we want to prevent checking the overrides every time we check this switch
|
||||
// 2. The switch has a valid value AND we have read the overrides for it
|
||||
// Example: TryGetSwitch is called for a switch set via SetSwitch
|
||||
// 3. The switch has the default value and we need to check for overrides
|
||||
// Example: TryGetSwitch is called for the first time for a switch that has a default value
|
||||
|
||||
// 1. The value is unknown
|
||||
if (switchValue == SwitchValueState.UnknownValue)
|
||||
{
|
||||
isEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We get the value of isEnabled from the value that we stored in the dictionary
|
||||
isEnabled = (switchValue & SwitchValueState.HasTrueValue) == SwitchValueState.HasTrueValue;
|
||||
|
||||
// 2. The switch has a valid value AND we have checked for overrides
|
||||
if ((switchValue & SwitchValueState.HasLookedForOverride) == SwitchValueState.HasLookedForOverride)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. The switch has a valid value, but we need to check for overrides.
|
||||
// Regardless of whether or not the switch has an override, we need to update the value to reflect
|
||||
// the fact that we checked for overrides.
|
||||
bool overrideValue;
|
||||
if (AppContextDefaultValues.TryGetSwitchOverride(switchName, out overrideValue))
|
||||
{
|
||||
// we found an override!
|
||||
isEnabled = overrideValue;
|
||||
}
|
||||
|
||||
// Update the switch in the dictionary to mark it as 'checked for override'
|
||||
s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
|
||||
| SwitchValueState.HasLookedForOverride;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The value is NOT in the dictionary
|
||||
// In this case we need to see if we have an override defined for the value.
|
||||
// There are 2 cases:
|
||||
// 1. The value has an override specified. In this case we need to add the value to the dictionary
|
||||
// and mark it as checked for overrides
|
||||
// Example: In a servicing event, System.Xml introduces a switch and an override is specified.
|
||||
// The value is not found in mscorlib (as System.Xml ships independent of mscorlib)
|
||||
// 2. The value does not have an override specified
|
||||
// In this case, we want to capture the fact that we looked for a value and found nothing by adding
|
||||
// an entry in the dictionary with the 'sentinel' value of 'SwitchValueState.UnknownValue'.
|
||||
// Example: This will prevent us from trying to find overrides for values that we don't have in the dictionary
|
||||
|
||||
// 1. The value has an override specified.
|
||||
bool overrideValue;
|
||||
if (AppContextDefaultValues.TryGetSwitchOverride(switchName, out overrideValue))
|
||||
{
|
||||
isEnabled = overrideValue;
|
||||
|
||||
// Update the switch in the dictionary to mark it as 'checked for override'
|
||||
s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
|
||||
| SwitchValueState.HasLookedForOverride;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. The value does not have an override.
|
||||
s_switchMap[switchName] = SwitchValueState.UnknownValue;
|
||||
}
|
||||
}
|
||||
return false; // we did not find a value for the switch
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assign a switch a value
|
||||
/// </summary>
|
||||
/// <param name="switchName">The name of the switch</param>
|
||||
/// <param name="isEnabled">The value to assign</param>
|
||||
public static void SetSwitch(string switchName, bool isEnabled)
|
||||
{
|
||||
if (switchName == null)
|
||||
throw new ArgumentNullException("switchName");
|
||||
if (switchName.Length == 0)
|
||||
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName");
|
||||
|
||||
lock (s_syncLock)
|
||||
{
|
||||
// Store the new value and the fact that we checked in the dictionary
|
||||
s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
|
||||
| SwitchValueState.HasLookedForOverride;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is going to be called from the AppContextDefaultValues class when setting up the
|
||||
/// default values for the switches. !!!! This method is called during the static constructor so it does not
|
||||
/// take a lock !!!! If you are planning to use this outside of that, please ensure proper locking.
|
||||
/// </summary>
|
||||
internal static void DefineSwitchDefault(string switchName, bool isEnabled)
|
||||
{
|
||||
s_switchMap[switchName] = isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
34
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.Central.cs
vendored
Normal file
34
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.Central.cs
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
|
||||
//
|
||||
// This file is used to provide an implementation for defining a default value
|
||||
// This should be compiled only in mscorlib where the AppContext class is available
|
||||
//
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static partial class AppContextDefaultValues
|
||||
{
|
||||
/// <summary>
|
||||
/// This method allows reading the override for a switch.
|
||||
/// The implementation is platform specific
|
||||
/// </summary>
|
||||
public static bool TryGetSwitchOverride(string switchName, out bool overrideValue)
|
||||
{
|
||||
// The default value for a switch is 'false'
|
||||
overrideValue = false;
|
||||
|
||||
// Read the override value
|
||||
bool overrideFound = false;
|
||||
|
||||
// This partial method will be removed if there are no implementations of it.
|
||||
TryGetSwitchOverridePartial(switchName, ref overrideFound, ref overrideValue);
|
||||
|
||||
return overrideFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs
vendored
Normal file
62
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
using System;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static partial class AppContextDefaultValues
|
||||
{
|
||||
|
||||
internal static readonly string SwitchNoAsyncCurrentCulture = "Switch.System.Globalization.NoAsyncCurrentCulture";
|
||||
internal static readonly string SwitchThrowExceptionIfDisposedCancellationTokenSource = "Switch.System.Threading.ThrowExceptionIfDisposedCancellationTokenSource";
|
||||
internal static readonly string SwitchPreserveEventListnerObjectIdentity = "Switch.System.Diagnostics.EventSource.PreserveEventListnerObjectIdentity";
|
||||
|
||||
|
||||
// This is a partial method. Platforms can provide an implementation of it that will set override values
|
||||
// from whatever mechanism is available on that platform. If no implementation is provided, the compiler is going to remove the calls
|
||||
// to it from the code
|
||||
// We are going to have an implementation of this method for the Desktop platform that will read the overrides from app.config, registry and
|
||||
// the shim database. Additional implementation can be provided for other platforms.
|
||||
static partial void PopulateOverrideValuesPartial();
|
||||
|
||||
static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version)
|
||||
{
|
||||
// When defining a new switch you should add it to the last known version.
|
||||
// For instance, if you are adding a switch in .NET 4.6 (the release after 4.5.2) you should defined your switch
|
||||
// like this:
|
||||
// if (version <= 40502) ...
|
||||
// This ensures that all previous versions of that platform (up-to 4.5.2) will get the old behavior by default
|
||||
// NOTE: When adding a default value for a switch please make sure that the default value is added to ALL of the existing platforms!
|
||||
// NOTE: When adding a new if statement for the version please ensure that ALL previous switches are enabled (ie. don't use else if)
|
||||
switch (platformIdentifier)
|
||||
{
|
||||
case ".NETCore":
|
||||
case ".NETFramework":
|
||||
{
|
||||
if (version <= 40502)
|
||||
{
|
||||
AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
|
||||
AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "WindowsPhone":
|
||||
case "WindowsPhoneApp":
|
||||
{
|
||||
if (version <= 80100)
|
||||
{
|
||||
AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
|
||||
AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we should read the overrides if any are defined
|
||||
PopulateOverrideValuesPartial();
|
||||
}
|
||||
}
|
||||
}
|
||||
136
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.DesktopOverrides.cs
vendored
Normal file
136
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.DesktopOverrides.cs
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static partial class AppContextDefaultValues
|
||||
{
|
||||
/// <summary>
|
||||
/// This method is going to parse the <paramref name="overrides"/> parameter and set the values corresponding to them
|
||||
/// in the AppContext object
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
static partial void PopulateOverrideValuesPartial()
|
||||
{
|
||||
// Retrieve the value from EE config.
|
||||
string overrides = System.Runtime.Versioning.CompatibilitySwitch.GetAppContextOverridesInternalCall();
|
||||
|
||||
// If we have no override values, do nothing.
|
||||
if (string.IsNullOrEmpty(overrides))
|
||||
return;
|
||||
|
||||
bool encounteredEquals = false, encounteredCharsInKey = false, encounteredCharsInValue = false;
|
||||
int previousSemicolonPos = -1, firstEqualsPos = -1;
|
||||
|
||||
// Iterate over the string one character at a time until we reach the end of the string.
|
||||
for (int currentPos = 0; currentPos <= overrides.Length; currentPos++)
|
||||
{
|
||||
// If the current position is either ';' or 'end-of-string' then we potentially have a key=value pair
|
||||
if (currentPos == overrides.Length || overrides[currentPos] == ';')
|
||||
{
|
||||
// We only have a key=value pair if we encountered an equals, characters in the key and in the value
|
||||
// portion of the pair.
|
||||
if (encounteredEquals && encounteredCharsInKey && encounteredCharsInValue)
|
||||
{
|
||||
// We compute the indexes in the string for key and value
|
||||
int firstCharOfKey = previousSemicolonPos + 1; //+1 because we don't take the ';' char
|
||||
int lenghtOfKey = firstEqualsPos - previousSemicolonPos - 1; //-1 because we don't take the '=' char
|
||||
string name = overrides.Substring(firstCharOfKey, lenghtOfKey);
|
||||
|
||||
int firstCharOfValue = firstEqualsPos + 1; // +1 because we don't count the '='
|
||||
int lengthOfValue = currentPos - firstEqualsPos - 1; // -1 because we don't count the '='
|
||||
string value = overrides.Substring(firstCharOfValue, lengthOfValue);
|
||||
|
||||
// apply the value only if it parses as a boolean
|
||||
bool switchValue;
|
||||
if (bool.TryParse(value, out switchValue))
|
||||
{
|
||||
// If multiple switches have the same name, the last value that we find will win.
|
||||
AppContext.SetSwitch(name, switchValue);
|
||||
}
|
||||
}
|
||||
previousSemicolonPos = currentPos;
|
||||
|
||||
// We need to reset these flags once we encounter a ';'
|
||||
encounteredCharsInKey = encounteredCharsInValue = encounteredEquals = false;
|
||||
}
|
||||
else if (overrides[currentPos] == '=')
|
||||
{
|
||||
// if the current character is '=' then we should flag it and remember it
|
||||
if (!encounteredEquals)
|
||||
{
|
||||
encounteredEquals = true;
|
||||
firstEqualsPos = currentPos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to know if the key or value contain any characters (other than ';' and '=');
|
||||
if (encounteredEquals)
|
||||
{
|
||||
encounteredCharsInValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
encounteredCharsInKey = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note -- partial methods cannot return a value so we use refs to return information
|
||||
[SecuritySafeCritical]
|
||||
static partial void TryGetSwitchOverridePartial(string switchName, ref bool overrideFound, ref bool overrideValue)
|
||||
{
|
||||
string valueFromConfig = null;
|
||||
bool boolFromConfig;
|
||||
overrideFound = false;
|
||||
|
||||
// Read the value from the registry if we can (ie. the key exists)
|
||||
if (s_switchesRegKey != null)
|
||||
{
|
||||
// try to read it from the registry key and return null if the switch name is not found
|
||||
valueFromConfig = s_switchesRegKey.GetValue(switchName, (string)null) as string;
|
||||
}
|
||||
|
||||
// Note: valueFromConfig will be null only if the key is not found.
|
||||
// Read the value from the Shim database.
|
||||
if (valueFromConfig == null)
|
||||
{
|
||||
// We are only going to check the Shim Database for an override in this case
|
||||
valueFromConfig = System.Runtime.Versioning.CompatibilitySwitch.GetValue(switchName);
|
||||
}
|
||||
|
||||
if (valueFromConfig != null && bool.TryParse(valueFromConfig, out boolFromConfig))
|
||||
{
|
||||
// If we found a valid override value, we need to let the caller know that.
|
||||
overrideValue = boolFromConfig;
|
||||
overrideFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Cached registry key used to read value overrides from the registry
|
||||
private static RegistryKey s_switchesRegKey = OpenRegKeyNoThrow();
|
||||
|
||||
/// <summary>
|
||||
/// Opens the registry key where the switches are stored and returns null if there is an issue opening the key
|
||||
/// </summary>
|
||||
private static RegistryKey OpenRegKeyNoThrow()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\AppContext");
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
}
|
||||
}
|
||||
169
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.cs
vendored
Normal file
169
external/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.cs
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static partial class AppContextDefaultValues
|
||||
{
|
||||
public static void PopulateDefaultValues()
|
||||
{
|
||||
string platformIdentifier, profile;
|
||||
int version;
|
||||
|
||||
ParseTargetFrameworkName(out platformIdentifier, out profile, out version);
|
||||
|
||||
// Call into each library to populate their default switches
|
||||
PopulateDefaultValuesPartial(platformIdentifier, profile, version);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We have this separate method for getting the parsed elements out of the TargetFrameworkName so we can
|
||||
/// more easily support this on other platforms.
|
||||
/// </summary>
|
||||
private static void ParseTargetFrameworkName(out string identifier, out string profile, out int version)
|
||||
{
|
||||
string targetFrameworkMoniker = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
|
||||
|
||||
// If we don't have a TFM then we should default to the 4.0 behavior where all quirks are turned on.
|
||||
if (!TryParseFrameworkName(targetFrameworkMoniker, out identifier, out version, out profile))
|
||||
{
|
||||
#if FEATURE_CORECLR
|
||||
if (CompatibilitySwitches.UseLatestBehaviorWhenTFMNotSpecified)
|
||||
{
|
||||
// If we want to use the latest behavior it is enough to set the value of the switch to string.Empty.
|
||||
// When the get to the caller of this method (PopulateDefaultValuesPartial) we are going to use the
|
||||
// identifier we just set to decide which switches to turn on. By having an empty string as the
|
||||
// identifier we are simply saying -- don't turn on any switches, and we are going to get the latest
|
||||
// behavior for all the switches
|
||||
identifier = string.Empty;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
identifier = ".NETFramework";
|
||||
version = 40000;
|
||||
profile = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This code was a constructor copied from the FrameworkName class, which is located in System.dll.
|
||||
// Parses strings in the following format: "<identifier>, Version=[v|V]<version>, Profile=<profile>"
|
||||
// - The identifier and version is required, profile is optional
|
||||
// - Only three components are allowed.
|
||||
// - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed
|
||||
private static bool TryParseFrameworkName(String frameworkName, out String identifier, out int version, out String profile)
|
||||
{
|
||||
// For parsing a target Framework moniker, from the FrameworkName class
|
||||
const char c_componentSeparator = ',';
|
||||
const char c_keyValueSeparator = '=';
|
||||
const char c_versionValuePrefix = 'v';
|
||||
const String c_versionKey = "Version";
|
||||
const String c_profileKey = "Profile";
|
||||
|
||||
identifier = profile = string.Empty;
|
||||
version = 0;
|
||||
|
||||
if (frameworkName == null || frameworkName.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] components = frameworkName.Split(c_componentSeparator);
|
||||
version = 0;
|
||||
|
||||
// Identifer and Version are required, Profile is optional.
|
||||
if (components.Length < 2 || components.Length > 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// 1) Parse the "Identifier", which must come first. Trim any whitespace
|
||||
//
|
||||
identifier = components[0].Trim();
|
||||
|
||||
if (identifier.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool versionFound = false;
|
||||
profile = null;
|
||||
|
||||
//
|
||||
// The required "Version" and optional "Profile" component can be in any order
|
||||
//
|
||||
for (int i = 1; i < components.Length; i++)
|
||||
{
|
||||
// Get the key/value pair separated by '='
|
||||
string[] keyValuePair = components[i].Split(c_keyValueSeparator);
|
||||
|
||||
if (keyValuePair.Length != 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the key and value, trimming any whitespace
|
||||
string key = keyValuePair[0].Trim();
|
||||
string value = keyValuePair[1].Trim();
|
||||
|
||||
//
|
||||
// 2) Parse the required "Version" key value
|
||||
//
|
||||
if (key.Equals(c_versionKey, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
versionFound = true;
|
||||
|
||||
// Allow the version to include a 'v' or 'V' prefix...
|
||||
if (value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V'))
|
||||
{
|
||||
value = value.Substring(1);
|
||||
}
|
||||
Version realVersion = new Version(value);
|
||||
// The version class will represent some unset values as -1 internally (instead of 0).
|
||||
version = realVersion.Major * 10000;
|
||||
if (realVersion.Minor > 0)
|
||||
version += realVersion.Minor * 100;
|
||||
if (realVersion.Build > 0)
|
||||
version += realVersion.Build;
|
||||
}
|
||||
//
|
||||
// 3) Parse the optional "Profile" key value
|
||||
//
|
||||
else if (key.Equals(c_profileKey, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (!String.IsNullOrEmpty(value))
|
||||
{
|
||||
profile = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!versionFound)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is a partial method. Platforms (such as Desktop) can provide an implementation of it that will read override value
|
||||
// from whatever mechanism is available on that platform. If no implementation is provided, the compiler is going to remove the calls
|
||||
// to it from the code
|
||||
static partial void TryGetSwitchOverridePartial(string switchName, ref bool overrideFound, ref bool overrideValue);
|
||||
|
||||
/// This is a partial method. This method is responsible for populating the default values based on a TFM.
|
||||
/// It is partial because each library should define this method in their code to contain their defaults.
|
||||
static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
|
||||
}
|
||||
}
|
||||
82
external/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs
vendored
Normal file
82
external/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
|
||||
namespace System
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
internal static class AppContextSwitches
|
||||
{
|
||||
private static int _noAsyncCurrentCulture;
|
||||
public static bool NoAsyncCurrentCulture
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return GetCachedSwitchValue(AppContextDefaultValues.SwitchNoAsyncCurrentCulture, ref _noAsyncCurrentCulture);
|
||||
}
|
||||
}
|
||||
|
||||
private static int _throwExceptionIfDisposedCancellationTokenSource;
|
||||
public static bool ThrowExceptionIfDisposedCancellationTokenSource
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return GetCachedSwitchValue(AppContextDefaultValues.SwitchThrowExceptionIfDisposedCancellationTokenSource, ref _throwExceptionIfDisposedCancellationTokenSource);
|
||||
}
|
||||
}
|
||||
|
||||
private static int _preserveEventListnerObjectIdentity;
|
||||
public static bool PreserveEventListnerObjectIdentity
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return GetCachedSwitchValue(AppContextDefaultValues.SwitchPreserveEventListnerObjectIdentity, ref _preserveEventListnerObjectIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Implementation details
|
||||
//
|
||||
|
||||
private static bool DisableCaching { get; set; }
|
||||
|
||||
static AppContextSwitches()
|
||||
{
|
||||
bool isEnabled;
|
||||
if (AppContext.TryGetSwitch(@"TestSwitch.LocalAppContext.DisableCaching", out isEnabled))
|
||||
{
|
||||
DisableCaching = isEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static bool GetCachedSwitchValue(string switchName, ref int switchValue)
|
||||
{
|
||||
if (switchValue < 0) return false;
|
||||
if (switchValue > 0) return true;
|
||||
|
||||
return GetCachedSwitchValueInternal(switchName, ref switchValue);
|
||||
}
|
||||
|
||||
private static bool GetCachedSwitchValueInternal(string switchName, ref int switchValue)
|
||||
{
|
||||
bool isSwitchEnabled;
|
||||
AppContext.TryGetSwitch(switchName, out isSwitchEnabled);
|
||||
|
||||
if (DisableCaching)
|
||||
{
|
||||
return isSwitchEnabled;
|
||||
}
|
||||
|
||||
switchValue = isSwitchEnabled ? 1 /*true*/ : -1 /*false*/;
|
||||
return isSwitchEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
1431
external/referencesource/mscorlib/system/AppDomainSetup.cs
vendored
Normal file
1431
external/referencesource/mscorlib/system/AppDomainSetup.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
82
external/referencesource/mscorlib/system/FormattableString.cs
vendored
Normal file
82
external/referencesource/mscorlib/system/FormattableString.cs
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
/*============================================================
|
||||
**
|
||||
** Class: FormattableString
|
||||
**
|
||||
**
|
||||
** Purpose: implementation of the FormattableString
|
||||
** class.
|
||||
**
|
||||
===========================================================*/
|
||||
namespace System
|
||||
{
|
||||
/// <summary>
|
||||
/// A composite format string along with the arguments to be formatted. An instance of this
|
||||
/// type may result from the use of the C# or VB language primitive "interpolated string".
|
||||
/// </summary>
|
||||
public abstract class FormattableString : IFormattable
|
||||
{
|
||||
/// <summary>
|
||||
/// The composite format string.
|
||||
/// </summary>
|
||||
public abstract string Format { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object array that contains zero or more objects to format. Clients should not
|
||||
/// mutate the contents of the array.
|
||||
/// </summary>
|
||||
public abstract object[] GetArguments();
|
||||
|
||||
/// <summary>
|
||||
/// The number of arguments to be formatted.
|
||||
/// </summary>
|
||||
public abstract int ArgumentCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns one argument to be formatted from argument position <paramref name="index"/>.
|
||||
/// </summary>
|
||||
public abstract object GetArgument(int index);
|
||||
|
||||
/// <summary>
|
||||
/// Format to a string using the given culture.
|
||||
/// </summary>
|
||||
public abstract string ToString(IFormatProvider formatProvider);
|
||||
|
||||
string IFormattable.ToString(string ignored, IFormatProvider formatProvider)
|
||||
{
|
||||
return ToString(formatProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format the given object in the invariant culture. This static method may be
|
||||
/// imported in C# by
|
||||
/// <code>
|
||||
/// using static System.FormattableString;
|
||||
/// </code>.
|
||||
/// Within the scope
|
||||
/// of that import directive an interpolated string may be formatted in the
|
||||
/// invariant culture by writing, for example,
|
||||
/// <code>
|
||||
/// Invariant($"{{ lat = {latitude}; lon = {longitude} }}")
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public static string Invariant(FormattableString formattable)
|
||||
{
|
||||
if (formattable == null)
|
||||
{
|
||||
throw new ArgumentNullException("formattable");
|
||||
}
|
||||
|
||||
return formattable.ToString(Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(Globalization.CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace System
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[ComVisible(false)]
|
||||
#if !FEATURE_CORECLR && !FEATURE_NETCORE
|
||||
#if !FEATURE_CORECLR
|
||||
[HostProtection(Synchronization = true, ExternalThreading = true)]
|
||||
#endif
|
||||
[DebuggerTypeProxy(typeof(System_LazyDebugView<>))]
|
||||
@@ -283,9 +283,6 @@ namespace System
|
||||
/// </remarks>
|
||||
public bool IsValueCreated
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get
|
||||
{
|
||||
return m_boxed != null && m_boxed is Boxed;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
// <OWNER>[....]</OWNER>
|
||||
// <OWNER>jfree</OWNER>
|
||||
//
|
||||
|
||||
namespace System {
|
||||
|
||||
@@ -31,8 +31,7 @@ namespace System {
|
||||
using AssemblyHashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Diagnostics.Tracing;
|
||||
|
||||
|
||||
// Only statics, does not need to be marked with the serializable attribute
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ComDefaultInterface(typeof(_Activator))]
|
||||
@@ -110,12 +109,6 @@ namespace System {
|
||||
|
||||
static public Object CreateInstance(Type type, params Object[] args)
|
||||
{
|
||||
#if !FEATURE_CORECLR && !MONO
|
||||
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage) && type != null)
|
||||
{
|
||||
FrameworkEventSource.Log.ActivatorCreateInstance(type.GetFullNameForEtw());
|
||||
}
|
||||
#endif
|
||||
return CreateInstance(type,
|
||||
Activator.ConstructorDefault,
|
||||
null,
|
||||
@@ -138,12 +131,6 @@ namespace System {
|
||||
|
||||
static public Object CreateInstance(Type type)
|
||||
{
|
||||
#if !FEATURE_CORECLR && !MONO
|
||||
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage) && type != null)
|
||||
{
|
||||
FrameworkEventSource.Log.ActivatorCreateInstance(type.GetFullNameForEtw());
|
||||
}
|
||||
#endif
|
||||
return Activator.CreateInstance(type, false);
|
||||
}
|
||||
|
||||
@@ -218,12 +205,7 @@ namespace System {
|
||||
static public T CreateInstance<T>()
|
||||
{
|
||||
RuntimeType rt = typeof(T) as RuntimeType;
|
||||
#if !FEATURE_CORECLR && !MONO
|
||||
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage) && rt != null)
|
||||
{
|
||||
FrameworkEventSource.Log.ActivatorCreateInstanceT(rt.GetFullNameForEtw());
|
||||
}
|
||||
#endif
|
||||
|
||||
// This is a hack to maintain compatibility with V2. Without this we would throw a NotSupportedException for void[].
|
||||
// Array, Ref, and Pointer types don't have default constructors.
|
||||
if (rt.HasElementType)
|
||||
@@ -629,6 +611,7 @@ namespace System {
|
||||
#if FEATURE_COMINTEROP || MONO_COM || MOBILE_LEGACY
|
||||
|
||||
#if FEATURE_CLICKONCE || MOBILE_LEGACY
|
||||
#if FEATURE_CLICKONCE || MONO_FEATURE_MULTIPLE_APPDOMAINS
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public static ObjectHandle CreateInstance (ActivationContext activationContext) {
|
||||
AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager;
|
||||
@@ -646,6 +629,17 @@ namespace System {
|
||||
|
||||
return domainManager.ApplicationActivator.CreateInstance(activationContext, activationCustomData);
|
||||
}
|
||||
#else
|
||||
[Obsolete ("Activator.CreateInstance (ActivationContext) is not supported on this platform.", true)]
|
||||
public static ObjectHandle CreateInstance (ActivationContext activationContext) {
|
||||
throw new PlatformNotSupportedException ("Activator.CreateInstance (ActivationContext) is not supported on this platform.");
|
||||
}
|
||||
|
||||
[Obsolete ("Activator.CreateInstance (ActivationContext, string[]) is not supported on this platform.", true)]
|
||||
public static ObjectHandle CreateInstance (ActivationContext activationContext, string[] activationCustomData) {
|
||||
throw new PlatformNotSupportedException ("Activator.CreateInstance (ActivationContext) is not supported on this platform.");
|
||||
}
|
||||
#endif
|
||||
#endif // FEATURE_CLICKONCE
|
||||
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
@@ -732,6 +726,7 @@ namespace System {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !FEATURE_CORECLR
|
||||
void _Activator.GetTypeInfoCount(out uint pcTInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -753,6 +748,7 @@ namespace System {
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
de54d4d62c3fac63d7a78c96906f044734620a9e
|
||||
0d7719d224a5cc564d4059a538c91201946c6082
|
||||
@@ -148,7 +148,6 @@ namespace System {
|
||||
}
|
||||
#endif // FEATURE_CAS_POLICY
|
||||
|
||||
#if !FEATURE_CORECLR
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
|
||||
private static extern void GetEntryAssembly(ObjectHandleOnStack retAssembly);
|
||||
@@ -180,7 +179,6 @@ namespace System {
|
||||
return m_entryAssembly;
|
||||
}
|
||||
}
|
||||
#endif // FEATURE_CORECLR
|
||||
|
||||
internal static AppDomainManager CurrentAppDomainManager {
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace System {
|
||||
get {
|
||||
String s = base.Message;
|
||||
if (!String.IsNullOrEmpty(m_paramName)) {
|
||||
String resourceString = Environment.GetRuntimeResourceString("Arg_ParamName_Name", m_paramName);
|
||||
String resourceString = Environment.GetResourceString("Arg_ParamName_Name", m_paramName);
|
||||
return s + Environment.NewLine + resourceString;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -28,20 +28,14 @@ namespace System {
|
||||
[Serializable]
|
||||
public class ArgumentOutOfRangeException : ArgumentException, ISerializable {
|
||||
|
||||
#if !FEATURE_SPLIT_RESOURCES
|
||||
private static volatile String _rangeMessage;
|
||||
#endif
|
||||
private Object m_actualValue;
|
||||
|
||||
private static String RangeMessage {
|
||||
get {
|
||||
#if FEATURE_SPLIT_RESOURCES
|
||||
return Environment.GetResourceString("Arg_ArgumentOutOfRangeException");
|
||||
#else
|
||||
if (_rangeMessage == null)
|
||||
_rangeMessage = Environment.GetResourceString("Arg_ArgumentOutOfRangeException");
|
||||
return _rangeMessage;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +74,7 @@ namespace System {
|
||||
get {
|
||||
String s = base.Message;
|
||||
if (m_actualValue != null) {
|
||||
String valueMessage = Environment.GetRuntimeResourceString("ArgumentOutOfRange_ActualValue", m_actualValue.ToString());
|
||||
String valueMessage = Environment.GetResourceString("ArgumentOutOfRange_ActualValue", m_actualValue.ToString());
|
||||
if (s == null)
|
||||
return valueMessage;
|
||||
return s + Environment.NewLine + valueMessage;
|
||||
|
||||
@@ -1 +1 @@
|
||||
0b0c4ee5d045e63e25237ca16522b3b9d2766b85
|
||||
7c767692fef9860facfa00e85ad8d5930fb954df
|
||||
@@ -28,13 +28,7 @@ namespace System
|
||||
// three fields from an ArraySegment may not see the same ArraySegment from one call to another
|
||||
// (ie, users could assign a new value to the old location).
|
||||
[Serializable]
|
||||
|
||||
// After .NET 4.5 RTMs, we can undo this and expose the full surface area to CoreCLR
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
public struct ArraySegment<T> : IList<T>, IReadOnlyList<T>
|
||||
#else
|
||||
public struct ArraySegment<T>
|
||||
#endif
|
||||
{
|
||||
private T[] _array;
|
||||
private int _offset;
|
||||
@@ -148,8 +142,6 @@ namespace System
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
// After .NET 4.5 RTMs, we can undo this and expose the full surface area to CoreCLR
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
#region IList<T>
|
||||
T IList<T>.this[int index]
|
||||
{
|
||||
@@ -347,6 +339,5 @@ namespace System
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,12 +140,16 @@ namespace System {
|
||||
List<Attribute> attributeList = new List<Attribute>();
|
||||
CopyToArrayList(attributeList, attributes, types);
|
||||
|
||||
PropertyInfo baseProp = GetParentDefinition(element);
|
||||
//if this is an index we need to get the parameter types to help disambiguate
|
||||
Type[] indexParamTypes = GetIndexParameterTypes(element);
|
||||
|
||||
|
||||
PropertyInfo baseProp = GetParentDefinition(element, indexParamTypes);
|
||||
while (baseProp != null)
|
||||
{
|
||||
attributes = GetCustomAttributes(baseProp, type, false);
|
||||
AddAttributesToList(attributeList, attributes, types);
|
||||
baseProp = GetParentDefinition(baseProp);
|
||||
baseProp = GetParentDefinition(baseProp, indexParamTypes);
|
||||
}
|
||||
Array array = CreateAttributeArrayHelper(type, attributeList.Count);
|
||||
Array.Copy(attributeList.ToArray(), 0, array, 0, attributeList.Count);
|
||||
@@ -165,21 +169,24 @@ namespace System {
|
||||
if (!usage.Inherited)
|
||||
return false;
|
||||
|
||||
PropertyInfo baseProp = GetParentDefinition(element);
|
||||
//if this is an index we need to get the parameter types to help disambiguate
|
||||
Type[] indexParamTypes = GetIndexParameterTypes(element);
|
||||
|
||||
PropertyInfo baseProp = GetParentDefinition(element, indexParamTypes);
|
||||
|
||||
while (baseProp != null)
|
||||
{
|
||||
if (baseProp.IsDefined(attributeType, false))
|
||||
return true;
|
||||
|
||||
baseProp = GetParentDefinition(baseProp);
|
||||
baseProp = GetParentDefinition(baseProp, indexParamTypes);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static PropertyInfo GetParentDefinition(PropertyInfo property)
|
||||
private static PropertyInfo GetParentDefinition(PropertyInfo property, Type[] propertyParameters)
|
||||
{
|
||||
Contract.Requires(property != null);
|
||||
|
||||
@@ -209,7 +216,10 @@ namespace System {
|
||||
return rtPropAccessor.DeclaringType.GetProperty(
|
||||
property.Name,
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
|
||||
property.PropertyType);
|
||||
null, //will use default binder
|
||||
property.PropertyType,
|
||||
propertyParameters, //used for index properties
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,6 +474,23 @@ namespace System {
|
||||
}
|
||||
}
|
||||
|
||||
private static Type[] GetIndexParameterTypes(PropertyInfo element)
|
||||
{
|
||||
ParameterInfo[] indexParams = element.GetIndexParameters();
|
||||
|
||||
if (indexParams.Length > 0)
|
||||
{
|
||||
Type[] indexParamTypes = new Type[indexParams.Length];
|
||||
for (int i = 0; i < indexParams.Length; i++)
|
||||
{
|
||||
indexParamTypes[i] = indexParams[i].ParameterType;
|
||||
}
|
||||
return indexParamTypes;
|
||||
}
|
||||
|
||||
return Array.Empty<Type>();
|
||||
}
|
||||
|
||||
private static void AddAttributesToList(List<Attribute> attributeList, Attribute[] attributes, Dictionary<Type, AttributeUsageAttribute> types)
|
||||
{
|
||||
for (int i = 0; i < attributes.Length; i++)
|
||||
@@ -1017,7 +1044,8 @@ namespace System {
|
||||
#region Public Members
|
||||
public virtual bool IsDefaultAttribute() { return false; }
|
||||
#endregion
|
||||
#if !MOBILE
|
||||
|
||||
#if !FEATURE_CORECLR && !MOBILE
|
||||
void _Attribute.GetTypeInfoCount(out uint pcTInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -111,6 +111,7 @@ namespace System {
|
||||
return (m_value==((Boolean)obj).m_value);
|
||||
}
|
||||
|
||||
[System.Runtime.Versioning.NonVersionable]
|
||||
public bool Equals(Boolean obj)
|
||||
{
|
||||
return m_value == obj;
|
||||
|
||||
111
external/referencesource/mscorlib/system/buffer.cs
vendored
111
external/referencesource/mscorlib/system/buffer.cs
vendored
@@ -14,6 +14,7 @@ namespace System {
|
||||
using System.Runtime.Versioning;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Security;
|
||||
using System.Runtime;
|
||||
|
||||
[System.Runtime.InteropServices.ComVisible(true)]
|
||||
public static partial class Buffer
|
||||
@@ -216,9 +217,6 @@ namespace System {
|
||||
*(src + len) = 0;
|
||||
}
|
||||
|
||||
#if !FEATURE_CORECLR
|
||||
[System.Runtime.ForceTokenStabilization]
|
||||
#endif //!FEATURE_CORECLR
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
internal unsafe static void Memcpy(byte[] dest, int destIndex, byte* src, int srcIndex, int len) {
|
||||
@@ -233,9 +231,6 @@ namespace System {
|
||||
}
|
||||
}
|
||||
|
||||
#if !FEATURE_CORECLR
|
||||
[System.Runtime.ForceTokenStabilization]
|
||||
#endif //!FEATURE_CORECLR
|
||||
[SecurityCritical]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
internal unsafe static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len)
|
||||
@@ -253,10 +248,14 @@ namespace System {
|
||||
#if !MONO
|
||||
// This is tricky to get right AND fast, so lets make it useful for the whole Fx.
|
||||
// E.g. System.Runtime.WindowsRuntime!WindowsRuntimeBufferExtensions.MemCopy uses it.
|
||||
|
||||
// This method has a slightly different behavior on arm and other platforms.
|
||||
// On arm this method behaves like memcpy and does not handle overlapping buffers.
|
||||
// While on other platforms it behaves like memmove and handles overlapping buffers.
|
||||
// This behavioral difference is unfortunate but intentional because
|
||||
// 1. This method is given access to other internal dlls and this close to release we do not want to change it.
|
||||
// 2. It is difficult to get this right for arm and again due to release dates we would like to visit it later.
|
||||
[FriendAccessAllowed]
|
||||
#if !FEATURE_CORECLR
|
||||
[System.Runtime.ForceTokenStabilization]
|
||||
#endif //!FEATURE_CORECLR
|
||||
[System.Security.SecurityCritical]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
@@ -264,9 +263,30 @@ namespace System {
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
internal unsafe static extern void Memcpy(byte* dest, byte* src, int len);
|
||||
#else // ARM
|
||||
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
|
||||
internal unsafe static void Memcpy(byte* dest, byte* src, int len) {
|
||||
Contract.Assert(len >= 0, "Negative length in memcopy!");
|
||||
Memmove(dest, src, (uint)len);
|
||||
}
|
||||
#endif // ARM
|
||||
|
||||
// This method has different signature for x64 and other platforms and is done for performance reasons.
|
||||
[System.Security.SecurityCritical]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
#if WIN64
|
||||
internal unsafe static void Memmove(byte* dest, byte* src, ulong len)
|
||||
#else
|
||||
internal unsafe static void Memmove(byte* dest, byte* src, uint len)
|
||||
#endif
|
||||
{
|
||||
// P/Invoke into the native version when the buffers are overlapping and the copy needs to be performed backwards
|
||||
// This check can produce false positives for lengths greater than Int32.MaxInt. It is fine because we want to use PInvoke path for the large lengths anyway.
|
||||
#if WIN64
|
||||
if ((ulong)dest - (ulong)src < len) goto PInvoke;
|
||||
#else
|
||||
if (((uint)dest - (uint)src) < len) goto PInvoke;
|
||||
#endif
|
||||
//
|
||||
// This is portable version of memcpy. It mirrors what the hand optimized assembly versions of memcpy typically do.
|
||||
//
|
||||
@@ -396,11 +416,7 @@ namespace System {
|
||||
}
|
||||
|
||||
// P/Invoke into the native version for large lengths
|
||||
if (len >= 512)
|
||||
{
|
||||
_Memcpy(dest, src, len);
|
||||
return;
|
||||
}
|
||||
if (len >= 512) goto PInvoke;
|
||||
|
||||
if (((int)dest & 3) != 0)
|
||||
{
|
||||
@@ -430,7 +446,11 @@ namespace System {
|
||||
}
|
||||
#endif
|
||||
|
||||
int count = len / 16;
|
||||
#if WIN64
|
||||
ulong count = len / 16;
|
||||
#else
|
||||
uint count = len / 16;
|
||||
#endif
|
||||
while (count > 0)
|
||||
{
|
||||
#if WIN64
|
||||
@@ -471,7 +491,13 @@ namespace System {
|
||||
src += 2;
|
||||
}
|
||||
if ((len & 1) != 0)
|
||||
*dest++ = *src++;
|
||||
*dest = *src;
|
||||
|
||||
return;
|
||||
|
||||
PInvoke:
|
||||
_Memmove(dest, src, len);
|
||||
|
||||
}
|
||||
|
||||
// Non-inlinable wrapper around the QCall that avoids poluting the fast path
|
||||
@@ -480,9 +506,13 @@ namespace System {
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[MethodImplAttribute(MethodImplOptions.NoInlining)]
|
||||
private unsafe static void _Memcpy(byte* dest, byte* src, int len)
|
||||
#if WIN64
|
||||
private unsafe static void _Memmove(byte* dest, byte* src, ulong len)
|
||||
#else
|
||||
private unsafe static void _Memmove(byte* dest, byte* src, uint len)
|
||||
#endif
|
||||
{
|
||||
__Memcpy(dest, src, len);
|
||||
__Memmove(dest, src, len);
|
||||
}
|
||||
|
||||
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
|
||||
@@ -490,8 +520,49 @@ namespace System {
|
||||
[SecurityCritical]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
extern private unsafe static void __Memcpy(byte* dest, byte* src, int len);
|
||||
#endif // ARM
|
||||
#if WIN64
|
||||
extern private unsafe static void __Memmove(byte* dest, byte* src, ulong len);
|
||||
#else
|
||||
extern private unsafe static void __Memmove(byte* dest, byte* src, uint len);
|
||||
#endif
|
||||
|
||||
|
||||
// The attributes on this method are chosen for best JIT performance.
|
||||
// Please do not edit unless intentional.
|
||||
[System.Security.SecurityCritical]
|
||||
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
|
||||
[CLSCompliant(false)]
|
||||
public static unsafe void MemoryCopy(void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy)
|
||||
{
|
||||
if (sourceBytesToCopy > destinationSizeInBytes)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceBytesToCopy);
|
||||
}
|
||||
#if WIN64
|
||||
Memmove((byte*)destination, (byte*)source, checked((ulong) sourceBytesToCopy));
|
||||
#else
|
||||
Memmove((byte*)destination, (byte*)source, checked((uint)sourceBytesToCopy));
|
||||
#endif // WIN64
|
||||
}
|
||||
|
||||
|
||||
// The attributes on this method are chosen for best JIT performance.
|
||||
// Please do not edit unless intentional.
|
||||
[System.Security.SecurityCritical]
|
||||
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
|
||||
[CLSCompliant(false)]
|
||||
public static unsafe void MemoryCopy(void* source, void* destination, ulong destinationSizeInBytes, ulong sourceBytesToCopy)
|
||||
{
|
||||
if (sourceBytesToCopy > destinationSizeInBytes)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceBytesToCopy);
|
||||
}
|
||||
#if WIN64
|
||||
Memmove((byte*)destination, (byte*)source, sourceBytesToCopy);
|
||||
#else
|
||||
Memmove((byte*)destination, (byte*)source, checked((uint)sourceBytesToCopy));
|
||||
#endif // WIN64
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user