Imported Upstream version 5.16.0.100

Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-08-07 15:19:03 +00:00
parent 0a9828183b
commit 7d7f676260
4419 changed files with 170950 additions and 90273 deletions

View File

@@ -13,10 +13,10 @@
<DefineConstants Condition=" '$(IsInterpreting)' != 'true' ">$(DefineConstants);FEATURE_COMPILE</DefineConstants>
<DefineConstants Condition=" '$(FeatureInterpret)' == 'true' ">$(DefineConstants);FEATURE_INTERPRET</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uapaot-Windows_NT-Debug|AnyCPU'" />
@@ -41,12 +41,6 @@
<Compile Include="$(CommonPath)\System\Collections\Generic\ArrayBuilder.cs">
<Link>Common\System\Collections\Generic\ArrayBuilder.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Collections\Generic\EnumerableHelpers.cs">
<Link>Common\System\Collections\Generic\EnumerableHelpers.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Collections\Generic\LargeArrayBuilder.cs">
<Link>Common\System\Collections\Generic\LargeArrayBuilder.cs</Link>
</Compile>
<Compile Include="System\Dynamic\Utils\CacheDict.cs" />
<Compile Include="System\Dynamic\Utils\ContractUtils.cs" />
<Compile Include="System\Dynamic\Utils\ExpressionUtils.cs" />

View File

@@ -43,10 +43,13 @@ namespace System.Dynamic
public DynamicMetaObject(Expression expression, BindingRestrictions restrictions, object value)
: this(expression, restrictions)
{
Value = value;
HasValue = true;
_value = value;
}
// having sentinel value means having no value. (this way we do not need a separate hasValue field)
private static readonly object s_noValueSentinel = new object();
private readonly object _value = s_noValueSentinel;
/// <summary>
/// The expression representing the <see cref="DynamicMetaObject"/> during the dynamic binding process.
/// </summary>
@@ -60,12 +63,12 @@ namespace System.Dynamic
/// <summary>
/// The runtime value represented by this <see cref="DynamicMetaObject"/>.
/// </summary>
public object Value { get; }
public object Value => HasValue ? _value : null;
/// <summary>
/// Gets a value indicating whether the <see cref="DynamicMetaObject"/> has the runtime value.
/// </summary>
public bool HasValue { get; }
public bool HasValue => _value != s_noValueSentinel;
/// <summary>
/// Gets the <see cref="Type"/> of the runtime value or null if the <see cref="DynamicMetaObject"/> has no value associated with it.

View File

@@ -38,7 +38,7 @@ for (int i = 1; i <= 10; i++)
//
// Create matchmaker and its site. We'll need them regardless.
//
site = CallSiteOps.CreateMatchmaker(@this);
site = @this.GetMatchmaker();
//
// Level 1 cache lookup
@@ -62,6 +62,7 @@ for (int i = 1; i <= 10; i++)
if (CallSiteOps.GetMatch(site))
{
CallSiteOps.UpdateRules(@this, i);
@this.ReleaseMatchmaker(site);
return result;
}
@@ -96,6 +97,7 @@ for (int i = 1; i <= 10; i++)
result = rule(<#=ruleInvocationArguments#>);
if (CallSiteOps.GetMatch(site))
{
@this.ReleaseMatchmaker(site);
return result;
}
}
@@ -137,6 +139,7 @@ for (int i = 1; i <= 10; i++)
result = rule(<#=ruleInvocationArguments#>);
if (CallSiteOps.GetMatch(site))
{
@this.ReleaseMatchmaker(site);
return result;
}
}
@@ -191,7 +194,7 @@ for (int i = 1; i <= 10; i++)
//
// Create matchmaker and its site. We'll need them regardless.
//
site = CallSiteOps.CreateMatchmaker(@this);
site = @this.GetMatchmaker();
//
// Level 1 cache lookup
@@ -215,6 +218,7 @@ for (int i = 1; i <= 10; i++)
if (CallSiteOps.GetMatch(site))
{
CallSiteOps.UpdateRules(@this, i);
@this.ReleaseMatchmaker(site);
return;
}
@@ -249,6 +253,7 @@ for (int i = 1; i <= 10; i++)
rule(<#=ruleInvocationArguments#>);
if (CallSiteOps.GetMatch(site))
{
@this.ReleaseMatchmaker(site);
return;
}
}
@@ -290,6 +295,7 @@ for (int i = 1; i <= 10; i++)
rule(<#=ruleInvocationArguments#>);
if (CallSiteOps.GetMatch(site))
{
@this.ReleaseMatchmaker(site);
return;
}
}

View File

@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.CompilerServices;
namespace System.Dynamic.Utils
@@ -74,7 +75,7 @@ namespace System.Dynamic.Utils
return builder.ToReadOnlyCollection();
}
T[] array = EnumerableHelpers.ToArray(enumerable);
T[] array = enumerable.ToArray();
return array.Length == 0 ?
EmptyReadOnlyCollection<T>.Instance :
new TrueReadOnlyCollection<T>(array);

View File

@@ -1 +1 @@
60d45b933bc489e12a2bb109d4ae0f88f5a0cec6
87a7ed9e4bcbdd043686b5217fa7074509f94168

View File

@@ -8,6 +8,7 @@ using System.Dynamic;
using System.Dynamic.Utils;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using static System.Linq.Expressions.CachedReflectionInfo;
namespace System.Runtime.CompilerServices
@@ -149,6 +150,11 @@ namespace System.Runtime.CompilerServices
/// </summary>
internal T[] Rules;
/// <summary>
/// an instance of matchmaker site to opportunistically reuse when site is polymorphic
/// </summary>
internal CallSite _cachedMatchmaker;
// Cached update delegate for all sites with a given T
private static T s_cachedUpdate;
@@ -172,6 +178,30 @@ namespace System.Runtime.CompilerServices
return new CallSite<T>();
}
internal CallSite GetMatchmaker()
{
// check if we have a cached matchmaker and attempt to atomically grab it.
var matchmaker = _cachedMatchmaker;
if (matchmaker != null)
{
matchmaker = Interlocked.Exchange(ref _cachedMatchmaker, null);
Debug.Assert(matchmaker?._match != false, "cached site should be set up for matchmaking");
}
return matchmaker ?? new CallSite<T>() { _match = true };
}
internal void ReleaseMatchmaker(CallSite matchMaker)
{
// If "Rules" has not been created, this is the first (and likely the only) Update of the site.
// 90% sites stay monomorphic and will never need a matchmaker again.
// Otherwise store the matchmaker for the future use.
if (Rules != null)
{
_cachedMatchmaker = matchMaker;
}
}
/// <summary>
/// Creates an instance of the dynamic call site, initialized with the binder responsible for the
/// runtime binding of the dynamic operations at this call site.

View File

@@ -113,9 +113,9 @@ namespace System.Runtime.CompilerServices
else
{
newRules = new T[newLength];
Array.Copy(rules, 0, newRules, 0, InsertPosition);
}
Array.Copy(rules, 0, newRules, 0, InsertPosition);
newRules[InsertPosition] = item;
Array.Copy(rules, InsertPosition, newRules, InsertPosition + 1, newLength - InsertPosition - 1);
return newRules;

View File

@@ -576,5 +576,87 @@ namespace System.Linq.Expressions.Tests
BinaryExpression e2 = Expression.MultiplyChecked(Expression.Parameter(typeof(int), "a"), Expression.Parameter(typeof(int), "b"));
Assert.Equal("(a * b)", e2.ToString());
}
// Simulate VB-style overloading of exponentiation operation
public struct VBStyleExponentiation
{
public VBStyleExponentiation(double value) => Value = value;
public double Value { get; }
public static implicit operator VBStyleExponentiation(double value) => new VBStyleExponentiation(value);
public static VBStyleExponentiation op_Exponent(VBStyleExponentiation x, VBStyleExponentiation y) => Math.Pow(x.Value, y.Value);
}
[Theory, ClassData(typeof(CompilationTypes))]
public static void VBStyleOperatorOverloading(bool useInterpreter)
{
var b = Expression.Parameter(typeof(VBStyleExponentiation));
var e = Expression.Parameter(typeof(VBStyleExponentiation));
var func = Expression.Lambda<Func<VBStyleExponentiation, VBStyleExponentiation, VBStyleExponentiation>>(
Expression.Power(b, e), b, e).Compile(useInterpreter);
Assert.Equal(8.0, func(2.0, 3.0).Value);
Assert.Equal(10000.0, func(10.0, 4.0).Value);
}
[Theory, ClassData(typeof(CompilationTypes))]
public static void VBStyleOperatorOverloadingLifted(bool useInterpreter)
{
var b = Expression.Parameter(typeof(VBStyleExponentiation?));
var e = Expression.Parameter(typeof(VBStyleExponentiation?));
var func = Expression.Lambda<Func<VBStyleExponentiation?, VBStyleExponentiation?, VBStyleExponentiation?>>(
Expression.Power(b, e), b, e).Compile(useInterpreter);
Assert.Equal(8.0, func(2.0, 3.0).Value.Value);
Assert.Equal(10000.0, func(10.0, 4.0).Value.Value);
Assert.Null(func(2.0, null));
Assert.Null(func(null, 2.0));
Assert.Null(func(null, null));
}
// Simulate F#-style overloading of exponentiation operation
public struct FSStyleExponentiation
{
public FSStyleExponentiation(double value) => Value = value;
public static implicit operator FSStyleExponentiation(double value) => new FSStyleExponentiation(value);
public double Value { get; }
public static FSStyleExponentiation op_Exponentiation(FSStyleExponentiation x, FSStyleExponentiation y)
=> new FSStyleExponentiation(Math.Pow(x.Value, y.Value));
}
[Theory, ClassData(typeof(CompilationTypes))]
public static void FSStyleOperatorOverloading(bool useInterpreter)
{
var b = Expression.Parameter(typeof(FSStyleExponentiation));
var e = Expression.Parameter(typeof(FSStyleExponentiation));
var func = Expression.Lambda<Func<FSStyleExponentiation, FSStyleExponentiation, FSStyleExponentiation>>(
Expression.Power(b, e), b, e).Compile(useInterpreter);
Assert.Equal(8.0, func(2.0, 3.0).Value);
Assert.Equal(10000.0, func(10.0, 4.0).Value);
}
[Theory, ClassData(typeof(CompilationTypes))]
public static void FSStyleOperatorOverloadingLifted(bool useInterpreter)
{
var b = Expression.Parameter(typeof(FSStyleExponentiation?));
var e = Expression.Parameter(typeof(FSStyleExponentiation?));
var func = Expression.Lambda<Func<FSStyleExponentiation?, FSStyleExponentiation?, FSStyleExponentiation?>>(
Expression.Power(b, e), b, e).Compile(useInterpreter);
Assert.Equal(8.0, func(2.0, 3.0).Value.Value);
Assert.Equal(10000.0, func(10.0, 4.0).Value.Value);
Assert.Null(func(2.0, null));
Assert.Null(func(null, 2.0));
Assert.Null(func(null, null));
}
[Fact]
public static void ExponentiationNotSupported()
{
ConstantExpression arg = Expression.Constant("");
Assert.Throws<InvalidOperationException>(() => Expression.Power(arg, arg));
}
}
}

View File

@@ -0,0 +1,126 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Dynamic;
using System.Linq.Expressions;
using Microsoft.CSharp.RuntimeBinder;
using Xunit;
namespace System.Runtime.CompilerServices.Tests
{
public class CallSiteCachingTests
{
[Fact]
public void InlineCache()
{
var callSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, "A", typeof(CallSiteCachingTests), new CSharpArgumentInfo[1]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
var initialTarget = callSite.Target;
Assert.Equal((object)initialTarget, callSite.Update);
object newExpando = CallSiteCachingTests.GetNewExpando(123);
callSite.Target(callSite, newExpando);
var newTarget = callSite.Target;
for (int i = 0; i < 10; i++)
{
callSite.Target(callSite, newExpando);
// rule should not be changing
Assert.Equal((object)newTarget, callSite.Target);
}
}
[Fact]
public void L1Cache()
{
var callSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, "A", typeof(CallSiteCachingTests), new CSharpArgumentInfo[1]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
ObjAndRule[] t = new ObjAndRule[200];
for (int i = 0; i < 10; i++)
{
object newExpando = CallSiteCachingTests.GetNewExpando(i);
callSite.Target(callSite, newExpando);
t[i].obj = newExpando;
t[i].rule = callSite.Target;
if (i > 0)
{
// must not reuse rules for new expandos
Assert.NotEqual((object)t[i].rule, t[i - 1].rule);
}
}
for (int i = 0; i < 10; i++)
{
var L1 = CallSiteOps.GetRules((dynamic)callSite);
// L1 must contain rules
Assert.Equal((object)t[9 - i].rule, L1[i]);
}
}
[Fact]
public void L2Cache()
{
var callSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, "A", typeof(CallSiteCachingTests), new CSharpArgumentInfo[1]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
ObjAndRule[] t = new ObjAndRule[200];
for (int i = 0; i < 100; i++)
{
object newExpando = CallSiteCachingTests.GetNewExpando(i);
callSite.Target(callSite, newExpando);
t[i].obj = newExpando;
t[i].rule = callSite.Target;
if (i > 0)
{
// must not reuse rules for new expandos
Assert.NotEqual((object)t[i].rule, t[i - 1].rule);
}
}
for (int i = 0; i < 100; i++)
{
object newExpando = CallSiteCachingTests.GetNewExpando(i);
callSite.Target(callSite, newExpando);
// must reuse rules from L2 cache
Assert.Equal((object)t[i].rule, callSite.Target);
}
}
private static dynamic GetNewExpando(int i)
{
dynamic e = new ExpandoObject();
e.A = i;
var d = e as IDictionary<string, Object>;
d.Add(i.ToString(), i);
return e;
}
private struct ObjAndRule
{
public object obj;
public object rule;
}
}
}

View File

@@ -64,7 +64,7 @@ namespace System.Dynamic.Tests
Assert.Equal(Enumerable.Repeat(new KeyValuePair<string, object>("key", 2), 1), eo);
}
[Fact, ActiveIssue(13541)]
[Fact]
public void DictionaryMatchesProperties()
{
dynamic eo = new ExpandoObject();

View File

@@ -12,10 +12,10 @@
<DefineConstants Condition=" '$(FeatureInterpret)' == 'true' ">$(DefineConstants);FEATURE_INTERPRET</DefineConstants>
<IncludeDefaultReferences>false</IncludeDefaultReferences>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uapaot-Windows_NT-Debug|AnyCPU'" />
@@ -130,6 +130,7 @@
<Compile Include="Dynamic\BindingRestrictionsTests.cs" />
<Compile Include="Dynamic\CallInfoTests.cs" />
<Compile Include="Dynamic\CallSiteBinderDefaultBehaviourTests.cs" />
<Compile Include="Dynamic\CallSiteCachingTests.cs" />
<Compile Include="Dynamic\CallSiteTests.cs" />
<Compile Include="Dynamic\ConvertBinderTests.cs" />
<Compile Include="Dynamic\DynamicAttributeTests.cs" />

View File

@@ -310,7 +310,6 @@ namespace System.Linq.Expressions.Tests
}
[Theory]
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "This test causes a fail fast on uapaot: https://github.com/dotnet/corefx/issues/19129")]
[MemberData(nameof(ReadAndWriteRefCases))]
public void ReadAndWriteRefParameters(bool useInterpreter, object value, object increment, object result)
{