diff options
Diffstat (limited to 'src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs')
-rw-r--r-- | src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs | 250 |
1 files changed, 141 insertions, 109 deletions
diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index b583053d4..8313fbe31 100644 --- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -44,10 +44,6 @@ namespace Internal.Reflection.Execution //========================================================================================================== internal sealed partial class ExecutionEnvironmentImplementation : ExecutionEnvironment { - private struct MethodTargetAndDictionary { public IntPtr TargetPointer; public IntPtr DictionaryPointer; } - - private LowLevelDictionary<IntPtr, MethodTargetAndDictionary> _callConverterWrappedMethodEntrypoints = new LowLevelDictionary<IntPtr, MethodTargetAndDictionary>(); - private RuntimeTypeHandle GetOpenTypeDefinition(RuntimeTypeHandle typeHandle, out RuntimeTypeHandle[] typeArgumentsHandles) { if (RuntimeAugments.IsGenericType(typeHandle)) @@ -475,27 +471,17 @@ namespace Internal.Reflection.Execution } } - private IntPtr GetDynamicMethodInvokerThunk(RuntimeTypeHandle[] argHandles, MethodBase methodInfo) + private IntPtr GetDynamicMethodInvokerThunk(MethodBase methodInfo) { - ParameterInfo[] parameters = methodInfo.GetParametersNoCopy(); - // last entry in argHandles is the return type if the type is not typeof(void) - Debug.Assert(parameters.Length == argHandles.Length || parameters.Length == (argHandles.Length - 1)); - - bool[] byRefParameters = new bool[parameters.Length + 1]; - RuntimeTypeHandle[] parameterTypeHandles = new RuntimeTypeHandle[parameters.Length + 1]; - - // This is either a constructor ("returns" void) or an instance method - MethodInfo reflectionMethodInfo = methodInfo as MethodInfo; - parameterTypeHandles[0] = (reflectionMethodInfo != null ? reflectionMethodInfo.ReturnType.TypeHandle : CommonRuntimeTypes.Void.TypeHandle); - byRefParameters[0] = false; - - for (int i = 0; i < parameters.Length; i++) - { - parameterTypeHandles[i + 1] = argHandles[i]; - byRefParameters[i + 1] = parameters[i].ParameterType.IsByRef; - } - - return CallConverterThunk.MakeThunk(ThunkKind.ReflectionDynamicInvokeThunk, IntPtr.Zero, IntPtr.Zero, false, parameterTypeHandles, byRefParameters, null); + MethodParametersInfo methodParamsInfo = new MethodParametersInfo(methodInfo); + return CallConverterThunk.MakeThunk( + ThunkKind.ReflectionDynamicInvokeThunk, + IntPtr.Zero, + IntPtr.Zero, + false, + methodParamsInfo.ReturnTypeAndParameterTypeHandles.ToArray(), + methodParamsInfo.ReturnTypeAndParametersByRefFlags, + null); } private RuntimeTypeHandle[] GetDynamicInvokeInstantiationArguments(MethodBase reflectionMethodBase) @@ -514,6 +500,17 @@ namespace Internal.Reflection.Execution if (!returnType.Equals(CommonRuntimeTypes.Void)) dynamicInvokeMethodGenArguments.Add(returnType.TypeHandle); + for (int i = 0; i < dynamicInvokeMethodGenArguments.Count; i++) + { + // We can't instantiate over pointer types, so the DynamicInvoke method compensates for it already. + RuntimeTypeHandle type = dynamicInvokeMethodGenArguments[i]; + while (RuntimeAugments.IsUnmanagedPointerType(type)) + { + type = RuntimeAugments.GetRelatedParameterTypeHandle(type); + } + dynamicInvokeMethodGenArguments[i] = type; + } + return dynamicInvokeMethodGenArguments.ToArray(); } @@ -603,33 +600,17 @@ namespace Internal.Reflection.Execution methodHandle.NativeFormatHandle); } - if (methodInvokeMetadata.MethodEntryPoint != methodInvokeMetadata.RawMethodEntryPoint && - !FunctionPointerOps.IsGenericMethodPointer(methodInvokeMetadata.MethodEntryPoint)) - { - // Keep track of the raw method entrypoints for the cases where they get wrapped into a calling convention converter thunk. - // This is needed for reverse lookups, like in TryGetMethodForOriginalLdFtnResult - Debug.Assert(canonFormKind == CanonicalFormKind.Universal); - lock (_callConverterWrappedMethodEntrypoints) - { - _callConverterWrappedMethodEntrypoints.LookupOrAdd(methodInvokeMetadata.MethodEntryPoint, new MethodTargetAndDictionary - { - TargetPointer = methodInvokeMetadata.RawMethodEntryPoint, - DictionaryPointer = methodInvokeMetadata.DictionaryComponent - }); - } - } - - RuntimeTypeHandle[] dynInvokeMethodArgs = GetDynamicInvokeInstantiationArguments(methodInfo); - IntPtr dynamicInvokeMethod; IntPtr dynamicInvokeMethodGenericDictionary; if ((methodInvokeMetadata.InvokeTableFlags & InvokeTableFlags.NeedsParameterInterpretation) != 0) { - dynamicInvokeMethod = GetDynamicMethodInvokerThunk(dynInvokeMethodArgs, methodInfo); + dynamicInvokeMethod = GetDynamicMethodInvokerThunk(methodInfo); dynamicInvokeMethodGenericDictionary = IntPtr.Zero; } else { + RuntimeTypeHandle[] dynInvokeMethodArgs = GetDynamicInvokeInstantiationArguments(methodInfo); + GetDynamicMethodInvokeMethodInfo( methodInvokeMetadata.MappingTableModule, methodInvokeMetadata.DynamicInvokeCookie, @@ -913,53 +894,87 @@ namespace Internal.Reflection.Execution } else { - bool isCallConverterWrappedEntrypoint; - MethodTargetAndDictionary callConverterWrappedEntrypoint; - lock (_callConverterWrappedMethodEntrypoints) + // The thunk could have been created by the TypeLoader as a dictionary slot for USG code + if (!CallConverterThunk.TryGetCallConversionTargetPointerAndInstantiatingArg(originalLdFtnResult, out canonOriginalLdFtnResult, out instantiationArgument)) { - isCallConverterWrappedEntrypoint = _callConverterWrappedMethodEntrypoints.TryGetValue(originalLdFtnResult, out callConverterWrappedEntrypoint); + canonOriginalLdFtnResult = RuntimeAugments.GetCodeTarget(originalLdFtnResult); + instantiationArgument = IntPtr.Zero; } + } + } - if (isCallConverterWrappedEntrypoint) + internal bool TryGetMethodForOriginalLdFtnResult(IntPtr originalLdFtnResult, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + { + GetFunctionPointerAndInstantiationArgumentForOriginalLdFtnResult(originalLdFtnResult, out IntPtr canonOriginalLdFtnResult, out IntPtr instantiationArgument); + + if (instantiationArgument != IntPtr.Zero) + { + // Search TemplateMethodMap + if (TryGetMethodForOriginalLdFtnResult_GenericMethodWithInstantiationArgument(instantiationArgument, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + return true; + } + else + { + // Search ExactInstantiationsMap + foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_ExactInstantations()) { - canonOriginalLdFtnResult = callConverterWrappedEntrypoint.TargetPointer; - instantiationArgument = callConverterWrappedEntrypoint.DictionaryPointer; + int startIndex; + int endIndex; + + if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) + { + for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) + { + uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; + if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, forStartAddress: false, canonOriginalLdFtnResult, parserOffset, + ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + return true; + } + } } - else + } + + // Search InvokeMap + foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_InvokeMap()) + { + int startIndex; + int endIndex; + + if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) { - // The thunk could have been created by the TypeLoader as a dictionary slot for USG code - if (!CallConverterThunk.TryGetCallConversionTargetPointerAndInstantiatingArg(originalLdFtnResult, out canonOriginalLdFtnResult, out instantiationArgument)) + for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) { - canonOriginalLdFtnResult = RuntimeAugments.GetCodeTarget(originalLdFtnResult); - instantiationArgument = IntPtr.Zero; + uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; + if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, forStartAddress: false, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + return true; } } } + + methodHandle = default(QMethodDefinition); + genericMethodTypeArgumentHandles = null; + return false; } - internal bool TryGetMethodForOriginalLdFtnResult(IntPtr originalLdFtnResult, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + internal bool TryGetMethodForStartAddress(IntPtr methodStartAddress, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle) { - GetFunctionPointerAndInstantiationArgumentForOriginalLdFtnResult(originalLdFtnResult, out IntPtr canonOriginalLdFtnResult, out IntPtr instantiationArgument); - - // Search TemplateMethodMap - if ((instantiationArgument != IntPtr.Zero) && TryGetMethodForOriginalLdFtnResult_GenericMethodWithInstantiationArgument(instantiationArgument, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) - { - return true; - } - // Search ExactInstantiationsMap foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_ExactInstantations()) { int startIndex; int endIndex; - if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) + if (perModuleLookup.Value.TryGetOffsetsRange(methodStartAddress, out startIndex, out endIndex)) { for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) { uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; - if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, forStartAddress: true, methodStartAddress, parserOffset, ref declaringTypeHandle, out methodHandle, out _)) + { + if (RuntimeAugments.IsGenericType(declaringTypeHandle)) + declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle); return true; + } } } } @@ -970,19 +985,22 @@ namespace Internal.Reflection.Execution int startIndex; int endIndex; - if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) + if (perModuleLookup.Value.TryGetOffsetsRange(methodStartAddress, out startIndex, out endIndex)) { for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) { uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; - if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, forStartAddress: true, methodStartAddress, IntPtr.Zero, parserOffset, ref declaringTypeHandle, out methodHandle, out _)) + { + if (RuntimeAugments.IsGenericType(declaringTypeHandle)) + declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle); return true; + } } } } methodHandle = default(QMethodDefinition); - genericMethodTypeArgumentHandles = null; return false; } @@ -1047,7 +1065,7 @@ namespace Internal.Reflection.Execution return functionPointerToOffsetInInvokeMap; } - private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFormatModuleInfo mappingTableModule, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFormatModuleInfo mappingTableModule, bool forStartAddress, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { methodHandle = default(QMethodDefinition); genericMethodTypeArgumentHandles = null; @@ -1069,7 +1087,7 @@ namespace Internal.Reflection.Execution // If the passed in method was a fat function pointer, but the entry in the mapping table doesn't need // an instantiation argument (or the other way around), trivially reject it. - if ((instantiationArgument == IntPtr.Zero) != ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0)) + if (!forStartAddress && ((instantiationArgument == IntPtr.Zero) != ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0))) return false; Debug.Assert((entryFlags & InvokeTableFlags.HasEntrypoint) != 0); @@ -1080,39 +1098,46 @@ namespace Internal.Reflection.Execution IntPtr entryMethodEntrypoint = externalReferences.GetFunctionPointerFromIndex(entryParser.GetUnsigned()); if ((entryFlags & InvokeTableFlags.NeedsParameterInterpretation) == 0) - entryParser.GetUnsigned(); // skip dynamic invoke cookie + entryParser.SkipInteger(); // skip dynamic invoke cookie + if (forStartAddress) + { + declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); + } + else + { #if DEBUG - IntPtr targetAddress; - Debug.Assert(entryMethodEntrypoint == canonOriginalLdFtnResult || - RuntimeAugments.GetCodeTarget(entryMethodEntrypoint) == canonOriginalLdFtnResult || - TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress) && - targetAddress == canonOriginalLdFtnResult); + IntPtr targetAddress; + Debug.Assert(entryMethodEntrypoint == canonOriginalLdFtnResult || + RuntimeAugments.GetCodeTarget(entryMethodEntrypoint) == canonOriginalLdFtnResult || + TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress) && + targetAddress == canonOriginalLdFtnResult); #endif - if ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0 && declaringTypeHandle.IsNull()) - declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); + if ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0 && declaringTypeHandle.IsNull()) + declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); - if ((entryFlags & InvokeTableFlags.IsGenericMethod) != 0) - { - if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) + if ((entryFlags & InvokeTableFlags.IsGenericMethod) != 0) { - MethodNameAndSignature dummyNameAndSignature; - bool success = TypeLoaderEnvironment.Instance.TryGetGenericMethodComponents(instantiationArgument, out declaringTypeHandle, out dummyNameAndSignature, out genericMethodTypeArgumentHandles); - Debug.Assert(success); + if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) + { + MethodNameAndSignature dummyNameAndSignature; + bool success = TypeLoaderEnvironment.Instance.TryGetGenericMethodComponents(instantiationArgument, out declaringTypeHandle, out dummyNameAndSignature, out genericMethodTypeArgumentHandles); + Debug.Assert(success); + } + else + genericMethodTypeArgumentHandles = GetTypeSequence(ref externalReferences, ref entryParser); } else - genericMethodTypeArgumentHandles = GetTypeSequence(ref externalReferences, ref entryParser); - } - else - { - genericMethodTypeArgumentHandles = null; - if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) - declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle(instantiationArgument); - } + { + genericMethodTypeArgumentHandles = null; + if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) + declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle(instantiationArgument); + } - RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); - declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle); + RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); + declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle); + } if ((entryFlags & InvokeTableFlags.HasMetadataHandle) != 0) { @@ -1173,17 +1198,17 @@ namespace Internal.Reflection.Execution uint parserOffset = entryParser.Offset; // Declaring Handle - entryParser.GetUnsigned(); + entryParser.SkipInteger(); // NameAndSig - entryParser.GetUnsigned(); + entryParser.SkipInteger(); // generic method arity int parsedArity = (int)entryParser.GetSequenceCount(); for (int i = 0; i < parsedArity; i++) { - entryParser.GetUnsigned(); + entryParser.SkipInteger(); } IntPtr functionPointer = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned()); @@ -1196,14 +1221,11 @@ namespace Internal.Reflection.Execution return functionPointerToOffsetInInvokeMap; } - private unsafe bool TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(NativeFormatModuleInfo mappingTableModule, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + private unsafe bool TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(NativeFormatModuleInfo mappingTableModule, bool forStartAddress, IntPtr canonOriginalLdFtnResult, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { methodHandle = default(QMethodDefinition); genericMethodTypeArgumentHandles = null; - if (instantiationArgument != IntPtr.Zero) - return false; - NativeReader invokeMapReader; if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.ExactMethodInstantiationsHashtable, out invokeMapReader)) { @@ -1225,11 +1247,22 @@ namespace Internal.Reflection.Execution return false; int parsedArity = (int)entryParser.GetSequenceCount(); - genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedArity]; - for (int i = 0; i < parsedArity; i++) + if (forStartAddress) + { + for (int i = 0; i < parsedArity; i++) + { + entryParser.SkipInteger(); + } + } + else { - genericMethodTypeArgumentHandles[i] = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); + genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedArity]; + + for (int i = 0; i < parsedArity; i++) + { + genericMethodTypeArgumentHandles[i] = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); + } } IntPtr functionPointer = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned()); @@ -1486,10 +1519,7 @@ namespace Internal.Reflection.Execution { Type parameterType = parameters[i].ParameterType; - // If the parameter is a pointer type, use IntPtr. Else use the actual parameter type. - if (parameterType.IsPointer) - result.Add(CommonRuntimeTypes.IntPtr.TypeHandle); - else if (parameterType.IsByRef) + if (parameterType.IsByRef) result.Add(parameterType.GetElementType().TypeHandle); else if (parameterType.GetTypeInfo().IsEnum && !parameters[i].HasDefaultValue) result.Add(Enum.GetUnderlyingType(parameterType).TypeHandle); @@ -1509,6 +1539,8 @@ namespace Internal.Reflection.Execution MethodInfo reflectionMethodInfo = _methodBase as MethodInfo; Type returnType = reflectionMethodInfo != null ? reflectionMethodInfo.ReturnType : CommonRuntimeTypes.Void; + if (returnType.IsByRef) + returnType = returnType.GetElementType(); result.Insert(0, returnType.TypeHandle); return result; |