Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Kanamori <AtsushiKan@users.noreply.github.com>2017-09-05 18:04:10 +0300
committerGitHub <noreply@github.com>2017-09-05 18:04:10 +0300
commitf7174c8e8cb28944e28b59258f37ae0af1571769 (patch)
tree88046ce34b9697759d6ca277b663e9acdf802bcb /src/System.Private.Reflection.Core
parentcc9d93f207b4d2265a700433b23d08b74655c364 (diff)
Fix late bound invoke on string constructors added in NS2.0 (#4449)
Fixes https://devdiv.visualstudio.com/DevDiv/_workitems/edit/476529 This fix also consolidates four different MethodInvokers into one general purpose one (CustomMethodInvoker.) - IntPtr/UIntPtr invokers - vaporized. The intrinsics all have fallback bodies and late-bound invoke now works fine on them using the normal path. - String/Nullable invokers - the normal path still doesn't work on them (no surprise since we never asked them to support this.) These have been replaced with CustomMethodInvoker and the NS2.0-added String constructors added. - The array constructors and get/set methods. These used the Synthetic invoker - Synthetic invoker was cleaned up and rebranded as CustomMethodInvoker.
Diffstat (limited to 'src/System.Private.Reflection.Core')
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs1
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs17
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs20
-rw-r--r--src/System.Private.Reflection.Core/src/Resources/Strings.resx9
-rw-r--r--src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj7
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs8
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs72
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs8
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs108
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs96
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs71
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/InvokerOptions.cs15
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs4
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs4
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs22
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs22
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs12
17 files changed, 431 insertions, 65 deletions
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs
index 7a4e60e6d..5d8699ce3 100644
--- a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs
@@ -101,7 +101,6 @@ namespace Internal.Reflection.Core.Execution
//==============================================================================================
// Other
//==============================================================================================
- public abstract MethodInvoker GetSyntheticMethodInvoker(RuntimeTypeHandle thisType, RuntimeTypeHandle[] parameterTypes, InvokerOptions options, Func<Object, Object[], Object> invoker);
public abstract bool IsCOMObject(Type type);
public abstract FieldAccessor CreateLiteralFieldAccessor(object value, RuntimeTypeHandle fieldTypeHandle);
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs
deleted file mode 100644
index 831a454f3..000000000
--- a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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;
-
-namespace Internal.Reflection.Core.Execution
-{
- [Flags]
- public enum InvokerOptions
- {
- None = 0x00000000,
- AllowNullThis = 0x00000001, // Don't raise an exception if the "thisObject" parameter to Invoker is null.
- DontWrapException = 0x00000002, // Don't wrap target exceptions in TargetInvocationException.
- }
-}
-
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs
index 1234a12f9..efeb83909 100644
--- a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs
@@ -8,6 +8,8 @@ using System.Diagnostics;
using System.Globalization;
using System.Reflection.Runtime.General;
+using Internal.Runtime.Augments;
+
namespace Internal.Reflection.Core.Execution
{
//
@@ -32,6 +34,24 @@ namespace Internal.Reflection.Core.Execution
// This property is used to retrieve the target method pointer. It is used by the RuntimeMethodHandle.GetFunctionPointer API
public abstract IntPtr LdFtnResult { get; }
+
+ protected static void ValidateThis(object thisObject, RuntimeTypeHandle declaringTypeHandle)
+ {
+ if (thisObject == null)
+ throw new TargetException(SR.RFLCT_Targ_StatMethReqTarg);
+
+ RuntimeTypeHandle srcTypeHandle = thisObject.GetType().TypeHandle;
+ if (RuntimeAugments.IsAssignableFrom(declaringTypeHandle, srcTypeHandle))
+ return;
+
+ if (RuntimeAugments.IsInterface(declaringTypeHandle))
+ {
+ if (RuntimeAugments.IsInstanceOfInterface(thisObject, declaringTypeHandle))
+ return;
+ }
+
+ throw new TargetException(SR.RFLCT_Targ_ITargMismatch);
+ }
}
}
diff --git a/src/System.Private.Reflection.Core/src/Resources/Strings.resx b/src/System.Private.Reflection.Core/src/Resources/Strings.resx
index 0f8ae09b5..4d7615699 100644
--- a/src/System.Private.Reflection.Core/src/Resources/Strings.resx
+++ b/src/System.Private.Reflection.Core/src/Resources/Strings.resx
@@ -376,4 +376,13 @@
<data name="CannotUseByRefLikeTypeInInstantiation" xml:space="preserve">
<value>Cannot instantiate a generic type on a byref-like type.</value>
</data>
+ <data name="RFLCT_Targ_StatMethReqTarg" xml:space="preserve">
+ <value>Non-static method requires a target.</value>
+ </data>
+ <data name="RFLCT_Targ_ITargMismatch" xml:space="preserve">
+ <value>Object does not match target type.</value>
+ </data>
+ <data name="InvalidOperation_NoValue" xml:space="preserve">
+ <value>Nullable object must have a value.</value>
+ </data>
</root>
diff --git a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
index 33f9df314..e8fd88288 100644
--- a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
+++ b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
@@ -127,6 +127,12 @@
<Compile Include="System\Reflection\Runtime\General\QSignatureTypeHandle.cs" />
<Compile Include="System\Reflection\Runtime\General\QSignatureTypeHandle.NativeFormat.cs" />
<Compile Include="System\Reflection\Runtime\MethodInfos\NativeFormat\NativeFormatMethodCommon.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\CustomMethodInvoker.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\CustomMethodInvokerAction.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\CustomMethodMapper.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\CustomMethodMapper.Nullable.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\CustomMethodMapper.String.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\InvokerOptions.cs" />
<Compile Include="System\Reflection\Runtime\MethodInfos\OpenMethodInvoker.cs" />
<Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeClsIdNullaryConstructorInfo.cs" />
<Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeConstructedGenericMethodInfo.cs" />
@@ -195,7 +201,6 @@
<Compile Include="Internal\Reflection\Core\Execution\FieldAccessor.cs" />
<Compile Include="Internal\Reflection\Core\Execution\MethodInvoker.cs" />
<Compile Include="Internal\Reflection\Core\Execution\ReflectionCoreExecution.cs" />
- <Compile Include="Internal\Reflection\Core\Execution\InvokerOptions.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' == 'true'">
<Compile Include="Internal\Reflection\Tracing\ReflectionTrace.Public.cs" />
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
index fd9603606..79eca8868 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
@@ -143,9 +143,9 @@ namespace System.Reflection.Runtime.MethodInfos
//-----------------------------------------------------------------------------------------------------------
internal sealed partial class RuntimeSyntheticConstructorInfo : RuntimeConstructorInfo
{
- internal static RuntimeSyntheticConstructorInfo GetRuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ internal static RuntimeSyntheticConstructorInfo GetRuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, InvokerOptions options, CustomMethodInvokerAction action)
{
- return new RuntimeSyntheticConstructorInfo(syntheticMethodId, declaringType, runtimeParameterTypes, options, invoker);
+ return new RuntimeSyntheticConstructorInfo(syntheticMethodId, declaringType, runtimeParameterTypes, options, action);
}
}
@@ -189,9 +189,9 @@ namespace System.Reflection.Runtime.MethodInfos
//-----------------------------------------------------------------------------------------------------------
internal sealed partial class RuntimeSyntheticMethodInfo : RuntimeMethodInfo
{
- internal static RuntimeMethodInfo GetRuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, RuntimeTypeInfo returnType, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ internal static RuntimeMethodInfo GetRuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, RuntimeTypeInfo returnType, InvokerOptions options, CustomMethodInvokerAction action)
{
- return new RuntimeSyntheticMethodInfo(syntheticMethodId, name, declaringType, runtimeParameterTypes, returnType, options, invoker).WithDebugName();
+ return new RuntimeSyntheticMethodInfo(syntheticMethodId, name, declaringType, runtimeParameterTypes, returnType, options, action).WithDebugName();
}
}
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs
new file mode 100644
index 000000000..ed124f01a
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs
@@ -0,0 +1,72 @@
+// 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.Diagnostics;
+
+using Internal.Runtime.Augments;
+using Internal.Reflection.Core.Execution;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // Custom invoker for edge case scenarios not handled by the toolchain. Examples: Strings and Nullables.
+ //
+ internal sealed class CustomMethodInvoker : MethodInvoker
+ {
+ public CustomMethodInvoker(Type thisType, Type[] parameterTypes, InvokerOptions options, CustomMethodInvokerAction action)
+ {
+ _action = action;
+ _options = options;
+ _thisType = thisType;
+ _parameterTypes = parameterTypes;
+ }
+
+ protected sealed override object Invoke(object thisObject, object[] arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException)
+ {
+ Debug.Assert(arguments != null);
+
+ // This does not handle optional parameters. None of the methods we use custom invocation for have them.
+ if (!(thisObject == null && 0 != (_options & InvokerOptions.AllowNullThis)))
+ ValidateThis(thisObject, _thisType.TypeHandle);
+
+ if (arguments.Length != _parameterTypes.Length)
+ throw new TargetParameterCountException();
+
+ object[] convertedArguments = new object[arguments.Length];
+ for (int i = 0; i < arguments.Length; i++)
+ {
+ convertedArguments[i] = RuntimeAugments.CheckArgument(arguments[i], _parameterTypes[i].TypeHandle, binderBundle);
+ }
+ object result;
+ try
+ {
+ result = _action(thisObject, convertedArguments, _thisType);
+ }
+ catch (Exception e) when (wrapInTargetInvocationException && ((_options & InvokerOptions.DontWrapException) == 0))
+ {
+ throw new TargetInvocationException(e);
+ }
+ return result;
+ }
+
+ public sealed override Delegate CreateDelegate(RuntimeTypeHandle delegateType, object target, bool isStatic, bool isVirtual, bool isOpen)
+ {
+ if (_thisType.IsConstructedGenericType && _thisType.GetGenericTypeDefinition() == CommonRuntimeTypes.Nullable)
+ {
+ // Desktop compat: MethodInfos to Nullable<T> methods cannot be turned into delegates.
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ }
+
+ throw new PlatformNotSupportedException();
+ }
+
+ public sealed override IntPtr LdFtnResult => throw new PlatformNotSupportedException();
+
+ private readonly InvokerOptions _options;
+ private readonly CustomMethodInvokerAction _action;
+ private readonly Type _thisType;
+ private readonly Type[] _parameterTypes;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs
new file mode 100644
index 000000000..cf7ca94e2
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs
@@ -0,0 +1,8 @@
+// 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.
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ internal delegate object CustomMethodInvokerAction(object thisObject, object[] args, Type thisType);
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs
new file mode 100644
index 000000000..fbf7418f3
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs
@@ -0,0 +1,108 @@
+// 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.Runtime.CompilerServices;
+using System.Reflection.Runtime.General;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ internal static partial class CustomMethodMapper
+ {
+ //
+ // Nullables are another edge case.
+ //
+ private static class NullableActions
+ {
+ public static Dictionary<MethodBase, CustomMethodInvokerAction> Map
+ {
+ get
+ {
+ if (s_lazyMap == null)
+ {
+ Dictionary<MethodBase, CustomMethodInvokerAction> map = new Dictionary<MethodBase, CustomMethodInvokerAction>();
+
+ Type type = CommonRuntimeTypes.Nullable;
+ Type theT = type.GetGenericTypeParameters()[0];
+
+ map.AddMethod(type, nameof(Nullable<int>.ToString), Array.Empty<Type>(),
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return thisObject == null ? string.Empty : thisObject.ToString();
+ }
+ );
+
+ map.AddMethod(type, nameof(Nullable<int>.Equals), new Type[] { CommonRuntimeTypes.Object },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ object other = args[0];
+ if (thisObject == null)
+ return other == null;
+ if (other == null)
+ return false;
+ return thisObject.Equals(other);
+ }
+ );
+
+ map.AddMethod(type, nameof(Nullable<int>.GetHashCode), Array.Empty<Type>(),
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return thisObject == null ? 0 : thisObject.GetHashCode();
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { theT },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return args[0];
+ }
+ );
+
+ map.AddMethod(type, "get_" + nameof(Nullable<int>.HasValue), Array.Empty<Type>(),
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return thisObject != null;
+ }
+ );
+
+ map.AddMethod(type, "get_" + nameof(Nullable<int>.Value), Array.Empty<Type>(),
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ if (thisObject == null)
+ throw new InvalidOperationException(SR.InvalidOperation_NoValue);
+ return thisObject;
+ }
+ );
+
+ map.AddMethod(type, nameof(Nullable<int>.GetValueOrDefault), Array.Empty<Type>(),
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ if (thisObject == null)
+ return RuntimeHelpers.GetUninitializedObject(thisType);
+
+ return thisObject;
+ }
+ );
+
+ map.AddMethod(type, nameof(Nullable<int>.GetValueOrDefault), new Type[] { theT },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ if (thisObject == null)
+ return args[0];
+ return thisObject;
+ }
+ );
+
+ s_lazyMap = map;
+ }
+
+ return s_lazyMap;
+ }
+ }
+
+ private static volatile Dictionary<MethodBase, CustomMethodInvokerAction> s_lazyMap;
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs
new file mode 100644
index 000000000..acd1dada3
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs
@@ -0,0 +1,96 @@
+// 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.Text;
+using System.Collections.Generic;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ internal static partial class CustomMethodMapper
+ {
+ //
+ // String constructors require special casing down the stack, being the only variable-sized objects created via a constructor.
+ //
+ private static class StringActions
+ {
+ public static Dictionary<MethodBase, CustomMethodInvokerAction> Map
+ {
+ get
+ {
+ if (s_lazyMap == null)
+ {
+ Dictionary<MethodBase, CustomMethodInvokerAction> map = new Dictionary<MethodBase, CustomMethodInvokerAction>();
+
+ Type type = CommonRuntimeTypes.String;
+
+ unsafe
+ {
+ map.AddConstructor(type, new Type[] { CommonRuntimeTypes.Char, CommonRuntimeTypes.Int32 },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((char)(args[0]), (int)(args[1]));
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { typeof(char[]) },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((char[])(args[0]));
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { typeof(char[]), CommonRuntimeTypes.Int32, CommonRuntimeTypes.Int32 },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((char[])(args[0]), (int)(args[1]), (int)(args[2]));
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { typeof(char*) },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((char*)(IntPtr)(args[0]));
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { typeof(char*), CommonRuntimeTypes.Int32, CommonRuntimeTypes.Int32 },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((char*)(IntPtr)(args[0]), (int)(args[1]), (int)(args[2]));
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { typeof(sbyte*) },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((sbyte*)(IntPtr)(args[0]));
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { typeof(sbyte*), CommonRuntimeTypes.Int32, CommonRuntimeTypes.Int32 },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((sbyte*)(IntPtr)(args[0]), (int)(args[1]), (int)(args[2]));
+ }
+ );
+
+ map.AddConstructor(type, new Type[] { typeof(sbyte*), CommonRuntimeTypes.Int32, CommonRuntimeTypes.Int32, typeof(Encoding) },
+ (object thisObject, object[] args, Type thisType) =>
+ {
+ return new string((sbyte*)(IntPtr)(args[0]), (int)(args[1]), (int)(args[2]), (Encoding)(args[3]));
+ }
+ );
+ }
+
+ s_lazyMap = map;
+ }
+
+ return s_lazyMap;
+ }
+ }
+ private static volatile Dictionary<MethodBase, CustomMethodInvokerAction> s_lazyMap;
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs
new file mode 100644
index 000000000..ce2306914
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs
@@ -0,0 +1,71 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+
+using Internal.Reflection.Core.Execution;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ internal static partial class CustomMethodMapper
+ {
+ //
+ // Certain types and methods are edge-cases that require special handling.
+ //
+ public static MethodInvoker GetCustomMethodInvokerIfNeeded(this MethodBase methodBase)
+ {
+ Type declaringType = methodBase.DeclaringType;
+ bool isNullable = declaringType.IsConstructedGenericType && declaringType.GetGenericTypeDefinition() == CommonRuntimeTypes.Nullable;
+
+ Dictionary<MethodBase, CustomMethodInvokerAction> map;
+ if (isNullable)
+ map = NullableActions.Map;
+ else if (declaringType == CommonRuntimeTypes.String)
+ map = StringActions.Map;
+ else
+ return null;
+
+ if (!(map.TryGetValue(methodBase.MetadataDefinitionMethod, out CustomMethodInvokerAction action)))
+ return null;
+
+ ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy();
+ Type[] parameterTypes = new Type[parameterInfos.Length];
+ for (int i = 0; i < parameterInfos.Length; i++)
+ {
+ parameterTypes[i] = parameterInfos[i].ParameterType;
+ }
+
+ InvokerOptions options = (methodBase.IsStatic || methodBase is ConstructorInfo || isNullable) ? InvokerOptions.AllowNullThis : InvokerOptions.None;
+ return new CustomMethodInvoker(declaringType, parameterTypes, options, action);
+ }
+
+ private static void AddConstructor(this Dictionary<MethodBase, CustomMethodInvokerAction> map, Type declaringType, Type[] parameterTypes, CustomMethodInvokerAction action)
+ {
+ map.AddMethod(declaringType, ConstructorInfo.ConstructorName, parameterTypes, action);
+ }
+
+ private static void AddMethod(this Dictionary<MethodBase, CustomMethodInvokerAction> map, Type declaringType, string name, Type[] parameterTypes, CustomMethodInvokerAction action)
+ {
+ const BindingFlags bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.ExactBinding;
+
+ MethodBase methodBase;
+ if (name == ConstructorInfo.ConstructorName)
+ {
+ methodBase = declaringType.GetConstructor(bf, null, parameterTypes, null);
+ }
+ else
+ {
+ methodBase = declaringType.GetMethod(name, 0, bf, null, parameterTypes, null);
+ }
+
+ if (methodBase == null)
+ return; // If we got here, this specific member was not included in the metadata.
+
+ Debug.Assert(methodBase == methodBase.MetadataDefinitionMethod);
+ map.Add(methodBase, action);
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/InvokerOptions.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/InvokerOptions.cs
new file mode 100644
index 000000000..c5eb41ac6
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/InvokerOptions.cs
@@ -0,0 +1,15 @@
+// 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.
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ [Flags]
+ internal enum InvokerOptions
+ {
+ None = 0x00000000,
+ AllowNullThis = 0x00000001, // Don't raise an exception if the "thisObject" parameter to Invoker is null.
+ DontWrapException = 0x00000002, // Don't wrap target exceptions in TargetInvocationException.
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
index 40df076c1..c158d76f1 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
@@ -307,6 +307,10 @@ namespace System.Reflection.Runtime.MethodInfos
{
get
{
+ MethodInvoker invoker = this.GetCustomMethodInvokerIfNeeded();
+ if (invoker != null)
+ return invoker;
+
return GetUncachedMethodInvoker(Array.Empty<RuntimeTypeInfo>(), this);
}
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs
index 0dbb40e00..fb5c6a122 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs
@@ -195,6 +195,10 @@ namespace System.Reflection.Runtime.MethodInfos
if (this.IsStatic)
throw new MemberAccessException(SR.Acc_NotClassInit);
+ MethodInvoker invoker = this.GetCustomMethodInvokerIfNeeded();
+ if (invoker != null)
+ return invoker;
+
return _common.GetUncachedMethodInvoker(Array.Empty<RuntimeTypeInfo>(), this);
}
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs
index a0aa8a0aa..ef2dc9e27 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs
@@ -20,12 +20,12 @@ namespace System.Reflection.Runtime.MethodInfos
//
internal sealed partial class RuntimeSyntheticConstructorInfo : RuntimeConstructorInfo, IRuntimeMemberInfoWithNoMetadataDefinition
{
- private RuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ private RuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, InvokerOptions options, CustomMethodInvokerAction action)
{
_syntheticMethodId = syntheticMethodId;
_declaringType = declaringType;
_options = options;
- _invoker = invoker;
+ _action = action;
_runtimeParameterTypes = runtimeParameterTypes;
}
@@ -164,21 +164,7 @@ namespace System.Reflection.Runtime.MethodInfos
}
}
- protected sealed override MethodInvoker UncachedMethodInvoker
- {
- get
- {
- RuntimeTypeInfo[] runtimeParameterTypes = _runtimeParameterTypes;
- RuntimeTypeHandle[] runtimeParameterTypeHandles = new RuntimeTypeHandle[runtimeParameterTypes.Length];
- for (int i = 0; i < runtimeParameterTypes.Length; i++)
- runtimeParameterTypeHandles[i] = runtimeParameterTypes[i].TypeHandle;
- return ReflectionCoreExecution.ExecutionEnvironment.GetSyntheticMethodInvoker(
- _declaringType.TypeHandle,
- runtimeParameterTypeHandles,
- _options,
- _invoker);
- }
- }
+ protected sealed override MethodInvoker UncachedMethodInvoker => new CustomMethodInvoker(_declaringType, _runtimeParameterTypes, _options, _action);
private volatile RuntimeParameterInfo[] _lazyParameters;
@@ -186,6 +172,6 @@ namespace System.Reflection.Runtime.MethodInfos
private readonly RuntimeArrayTypeInfo _declaringType;
private readonly RuntimeTypeInfo[] _runtimeParameterTypes;
private readonly InvokerOptions _options;
- private readonly Func<Object, Object[], Object> _invoker;
+ private readonly CustomMethodInvokerAction _action;
}
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
index e439b4501..2a917563e 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
@@ -19,13 +19,13 @@ namespace System.Reflection.Runtime.MethodInfos
//
internal sealed partial class RuntimeSyntheticMethodInfo : RuntimeMethodInfo, IRuntimeMemberInfoWithNoMetadataDefinition
{
- private RuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] parameterTypes, RuntimeTypeInfo returnType, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ private RuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] parameterTypes, RuntimeTypeInfo returnType, InvokerOptions options, CustomMethodInvokerAction action)
{
_syntheticMethodId = syntheticMethodId;
_name = name;
_declaringType = declaringType;
_options = options;
- _invoker = invoker;
+ _action = action;
_runtimeParameterTypes = parameterTypes;
_returnType = returnType;
}
@@ -171,21 +171,7 @@ namespace System.Reflection.Runtime.MethodInfos
}
}
- protected sealed override MethodInvoker UncachedMethodInvoker
- {
- get
- {
- RuntimeTypeInfo[] runtimeParameterTypes = _runtimeParameterTypes;
- RuntimeTypeHandle[] runtimeParameterTypeHandles = new RuntimeTypeHandle[runtimeParameterTypes.Length];
- for (int i = 0; i < runtimeParameterTypes.Length; i++)
- runtimeParameterTypeHandles[i] = runtimeParameterTypes[i].TypeHandle;
- return ReflectionCoreExecution.ExecutionEnvironment.GetSyntheticMethodInvoker(
- _declaringType.TypeHandle,
- runtimeParameterTypeHandles,
- _options,
- _invoker);
- }
- }
+ protected sealed override MethodInvoker UncachedMethodInvoker => new CustomMethodInvoker(_declaringType, _runtimeParameterTypes, _options, _action);
internal sealed override RuntimeTypeInfo[] RuntimeGenericArgumentsOrParameters
{
@@ -238,6 +224,6 @@ namespace System.Reflection.Runtime.MethodInfos
private readonly RuntimeTypeInfo[] _runtimeParameterTypes;
private readonly RuntimeTypeInfo _returnType;
private readonly InvokerOptions _options;
- private readonly Func<Object, Object[], Object> _invoker;
+ private readonly CustomMethodInvokerAction _action;
}
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs
index e058d0cdd..98db26c70 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs
@@ -73,7 +73,7 @@ namespace System.Reflection.Runtime.TypeInfos
arrayType,
ctorParameters,
InvokerOptions.AllowNullThis | InvokerOptions.DontWrapException,
- delegate (Object _this, Object[] args)
+ delegate (Object _this, Object[] args, Type thisType)
{
int[] lengths = new int[rank];
for (int i = 0; i < rank; i++)
@@ -111,7 +111,7 @@ namespace System.Reflection.Runtime.TypeInfos
arrayType,
ctorParameters,
InvokerOptions.AllowNullThis | InvokerOptions.DontWrapException,
- delegate (Object _this, Object[] args)
+ delegate (Object _this, Object[] args, Type thisType)
{
int[] lengths = new int[args.Length];
for (int i = 0; i < args.Length; i++)
@@ -147,7 +147,7 @@ namespace System.Reflection.Runtime.TypeInfos
arrayType,
ctorParameters,
InvokerOptions.AllowNullThis | InvokerOptions.DontWrapException,
- delegate (Object _this, Object[] args)
+ delegate (Object _this, Object[] args, Type thisType)
{
int[] lengths = new int[rank];
int[] lowerBounds = new int[rank];
@@ -185,7 +185,7 @@ namespace System.Reflection.Runtime.TypeInfos
getParameters,
elementType,
InvokerOptions.None,
- delegate (Object _this, Object[] args)
+ delegate (Object _this, Object[] args, Type thisType)
{
Array array = (Array)_this;
int[] indices = new int[rank];
@@ -208,7 +208,7 @@ namespace System.Reflection.Runtime.TypeInfos
setParameters,
voidType,
InvokerOptions.None,
- delegate (Object _this, Object[] args)
+ delegate (Object _this, Object[] args, Type thisType)
{
Array array = (Array)_this;
int[] indices = new int[rank];
@@ -232,7 +232,7 @@ namespace System.Reflection.Runtime.TypeInfos
addressParameters,
elementType.GetByRefType(),
InvokerOptions.None,
- delegate (Object _this, Object[] args)
+ delegate (Object _this, Object[] args, Type thisType)
{
throw new NotSupportedException();
}