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:
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.cs250
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;