コード例 #1
0
        public bool CanInstantiationsShareCode(RuntimeTypeHandle[] genericArgHandles1, RuntimeTypeHandle[] genericArgHandles2, CanonicalFormKind kind)
        {
            if (genericArgHandles1.Length != genericArgHandles2.Length)
                return false;

            bool match = true;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            for (int i = 0; i < genericArgHandles1.Length; i++)
            {
                TypeDesc genericArg1 = context.ResolveRuntimeTypeHandle(genericArgHandles1[i]);
                TypeDesc genericArg2 = context.ResolveRuntimeTypeHandle(genericArgHandles2[i]);

                if (context.ConvertToCanon(genericArg1, kind) != context.ConvertToCanon(genericArg2, kind))
                {
                    match = false;
                    break;
                }
            }

            TypeSystemContextFactory.Recycle(context);

            return match;
        }
コード例 #2
0
            internal override bool MatchParsedEntry(ref NativeParser entryParser, ref ExternalReferencesTable externalReferencesLookup, IntPtr moduleHandle)
            {
                //
                // Entries read from the hashtable are loaded as GenericMethodDescs, and compared to the input.
                // This lookup is slower than the lookups using RuntimeTypeHandles, but can handle cases where we don't have
                // RuntimeTypeHandle values for all of the components of the input GenericMethodDesc, but still need to look it up in case the
                // method dictionary statically really exists
                //
                TypeSystemContext context = _methodToLookup.Context;

                RuntimeTypeHandle parsedDeclaringTypeHandle = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                // Hash table names / sigs are indirected through to the native layout info
                MethodNameAndSignature nameAndSignature;

                if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutOffset(moduleHandle, entryParser.GetUnsigned(), out nameAndSignature))
                {
                    return(false);
                }

                RuntimeTypeHandle[] parsedArgsHandles = GetTypeSequence(ref externalReferencesLookup, ref entryParser);

                DefType            parsedDeclaringType = context.ResolveRuntimeTypeHandle(parsedDeclaringTypeHandle) as DefType;
                Instantiation      parsedArgs          = context.ResolveRuntimeTypeHandles(parsedArgsHandles);
                InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, nameAndSignature, parsedArgs, IntPtr.Zero, false);

                return(parsedGenericMethod == _methodToLookup);
            }
コード例 #3
0
        /// <summary>
        /// This thunk is used to lazily resolve Finalizer calls
        /// </summary>
        /// <param name="obj">Object to be finalized</param>
        private static void FinalizeThunk(object obj)
        {
            RuntimeTypeHandle rthType = RuntimeAugments.GetRuntimeTypeHandleFromObjectReference(obj);
            TypeSystemContext context = TypeSystemContextFactory.Create();
            TypeDesc          type    = context.ResolveRuntimeTypeHandle(rthType);

            MethodDesc finalizer = type.GetFinalizer();
            IntPtr     fnPtrFinalizer;

            if (!TryGetVTableCallableAddress(finalizer, out fnPtrFinalizer))
            {
                Environment.FailFast("Method address lookup failed for: " + finalizer.ToString());
            }

            TypeSystemContextFactory.Recycle(context);

            unsafe
            {
                rthType.ToEETypePtr()->FinalizerCode = fnPtrFinalizer;
            }

            // Call the finalizer directly. No need to play tricks with tail calling, as this is rare enough, it shouldn't happen much

            // Here we take advantage of the detail that the calling convention abi for a static function
            // that returns no values, and takes a single object parameter matches that of a
            // instance function that takes no parameters
            Intrinsics.Call(fnPtrFinalizer, obj);
        }
コード例 #4
0
        /// <summary>
        /// Attempt a virtual dispatch on a given instanceType based on the method found via a metadata token
        /// </summary>
        private static bool TryDispatchMethodOnTarget_Inner(NativeFormatModuleInfo module, int metadataToken, RuntimeTypeHandle targetInstanceType, out IntPtr methodAddress)
        {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            TypeSystemContext context = TypeSystemContextFactory.Create();

            NativeFormatMetadataUnit metadataUnit = context.ResolveMetadataUnit(module);
            MethodDesc targetMethod = metadataUnit.GetMethod(metadataToken.AsHandle(), null);
            TypeDesc   instanceType = context.ResolveRuntimeTypeHandle(targetInstanceType);

            MethodDesc realTargetMethod = targetMethod;

            // For non-interface methods we support the target method not being the exact target. (This allows
            // a canonical method to be passed in and work for any generic type instantiation.)
            if (!targetMethod.OwningType.IsInterface)
            {
                realTargetMethod = instanceType.FindMethodOnTypeWithMatchingTypicalMethod(targetMethod);
            }

            bool success = LazyVTableResolver.TryDispatchMethodOnTarget(instanceType, realTargetMethod, out methodAddress);

            TypeSystemContextFactory.Recycle(context);
            return(success);
#else
            methodAddress = IntPtr.Zero;
            return(false);
#endif
        }
コード例 #5
0
        public bool TryComputeHasInstantiationDeterminedSize(RuntimeTypeHandle typeHandle, TypeSystemContext context, out bool hasInstantiationDeterminedSize)
        {
            Debug.Assert(RuntimeAugments.IsGenericType(typeHandle) || RuntimeAugments.IsGenericTypeDefinition(typeHandle));
            DefType type = (DefType)context.ResolveRuntimeTypeHandle(typeHandle);

            return TryComputeHasInstantiationDeterminedSize(type, out hasInstantiationDeterminedSize);
        }
コード例 #6
0
        internal TypeDesc GetExternalType(uint index)
        {
            InitializeExternalReferencesLookup();
            RuntimeTypeHandle rtth = _externalReferencesLookup.GetRuntimeTypeHandleFromIndex(index);

            return(_typeSystemContext.ResolveRuntimeTypeHandle(rtth));
        }
コード例 #7
0
        /// <summary>
        /// Resolve a dispatch on an interface EEType/slot index pair to a function pointer
        /// </summary>
        private bool TryResolveTypeSlotDispatch_Inner(IntPtr targetTypeAsIntPtr, IntPtr interfaceTypeAsIntPtr, ushort slot, out IntPtr methodAddress)
        {
            methodAddress = IntPtr.Zero;

#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            TypeSystemContext context = TypeSystemContextFactory.Create();

            TypeDesc targetType;
            TypeDesc interfaceType;

            unsafe
            {
                targetType    = context.ResolveRuntimeTypeHandle(((EEType *)targetTypeAsIntPtr.ToPointer())->ToRuntimeTypeHandle());
                interfaceType = context.ResolveRuntimeTypeHandle(((EEType *)interfaceTypeAsIntPtr.ToPointer())->ToRuntimeTypeHandle());
            }

            if (!(interfaceType.GetTypeDefinition() is MetadataType))
            {
                // If the interface open type is not a metadata type, this must be an interface not known in the metadata world.
                // Use the redhawk resolver for this directly.
                TypeDesc pregeneratedType = LazyVTableResolver.GetMostDerivedPregeneratedOrTemplateLoadedType(targetType);
                pregeneratedType.RetrieveRuntimeTypeHandleIfPossible();
                interfaceType.RetrieveRuntimeTypeHandleIfPossible();
                methodAddress = RuntimeAugments.ResolveDispatchOnType(pregeneratedType.RuntimeTypeHandle, interfaceType.RuntimeTypeHandle, slot);
            }
            else
            {
                MethodDesc interfaceMethod;

                if (!LazyVTableResolver.TryGetMethodFromInterfaceSlot(interfaceType, slot, out interfaceMethod))
                {
                    return(false);
                }

                if (!LazyVTableResolver.TryDispatchMethodOnTarget(targetType, interfaceMethod, out methodAddress))
                {
                    return(false);
                }
            }

            TypeSystemContextFactory.Recycle(context);

            return(true);
#else
            return(false);
#endif
        }
コード例 #8
0
        public int GetCanonicalHashCode(RuntimeTypeHandle typeHandle, CanonicalFormKind kind)
        {
            TypeSystemContext context = TypeSystemContextFactory.Create();
            TypeDesc type = context.ResolveRuntimeTypeHandle(typeHandle);
            int hashCode = type.ConvertToCanonForm(kind).GetHashCode();
            TypeSystemContextFactory.Recycle(context);

            return hashCode;
        }
コード例 #9
0
            internal override bool MatchGenericTypeEntry(GenericTypeEntry entry)
            {
                TypeSystemContext context = _typeToLookup.Context;

                DefType       parsedTypeDefinition = (DefType)context.ResolveRuntimeTypeHandle(entry._genericTypeDefinitionHandle);
                Instantiation parsedArgs           = context.ResolveRuntimeTypeHandles(entry._genericTypeArgumentHandles);
                DefType       parsedGenericType    = context.ResolveGenericInstantiation(parsedTypeDefinition, parsedArgs);

                return(parsedGenericType == _typeToLookup);
            }
コード例 #10
0
            internal override bool MatchGenericMethodEntry(GenericMethodEntry entry)
            {
                TypeSystemContext context = _methodToLookup.Context;

                DefType            parsedDeclaringType = context.ResolveRuntimeTypeHandle(entry._declaringTypeHandle) as DefType;
                Instantiation      parsedArgs          = context.ResolveRuntimeTypeHandles(entry._genericMethodArgumentHandles);
                InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, entry._methodNameAndSignature, parsedArgs, IntPtr.Zero, false);

                return(parsedGenericMethod == _methodToLookup);
            }
コード例 #11
0
        public static MethodDesc ToMethodDesc(this RuntimeMethodHandle rmh, TypeSystemContext typeSystemContext)
        {
            RuntimeTypeHandle      declaringTypeHandle;
            MethodNameAndSignature nameAndSignature;

            RuntimeTypeHandle[] genericMethodArgs;

            if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(rmh, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs))
            {
                return(null);
            }

            QMethodDefinition methodHandle;

            if (!TypeLoaderEnvironment.Instance.TryGetMetadataForTypeMethodNameAndSignature(declaringTypeHandle, nameAndSignature, out methodHandle))
            {
                return(null);
            }

            TypeDesc declaringType = typeSystemContext.ResolveRuntimeTypeHandle(declaringTypeHandle);

            TypeDesc   declaringTypeDefinition = declaringType.GetTypeDefinition();
            MethodDesc typicalMethod           = null;

            if (methodHandle.IsNativeFormatMetadataBased)
            {
                var nativeFormatType = (NativeFormatType)declaringTypeDefinition;
                typicalMethod = nativeFormatType.MetadataUnit.GetMethod(methodHandle.NativeFormatHandle, nativeFormatType);
            }
            else if (methodHandle.IsEcmaFormatMetadataBased)
            {
                var ecmaFormatType = (EcmaType)declaringTypeDefinition;
                typicalMethod = ecmaFormatType.EcmaModule.GetMethod(methodHandle.EcmaFormatHandle);
            }
            Debug.Assert(typicalMethod != null);

            MethodDesc methodOnInstantiatedType = typicalMethod;

            if (declaringType != declaringTypeDefinition)
            {
                methodOnInstantiatedType = typeSystemContext.GetMethodForInstantiatedType(typicalMethod, (InstantiatedType)declaringType);
            }

            MethodDesc instantiatedMethod = methodOnInstantiatedType;

            if (genericMethodArgs != null)
            {
                Debug.Assert(genericMethodArgs.Length > 0);
                Instantiation genericMethodInstantiation = typeSystemContext.ResolveRuntimeTypeHandles(genericMethodArgs);
                typeSystemContext.GetInstantiatedMethod(methodOnInstantiatedType, genericMethodInstantiation);
            }

            return(instantiatedMethod);
        }
コード例 #12
0
        private bool ResolveInterfaceGenericVirtualMethodSlot(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature)
        {
            if (IsPregeneratedOrTemplateRuntimeTypeHandle(targetTypeHandle))
            {
                // If the target type isn't dynamic, or at least is template type generated, the static lookup logic is what we want.
                return(ResolveInterfaceGenericVirtualMethodSlot_Static(targetTypeHandle, ref declaringType, ref methodNameAndSignature));
            }
            else
            {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
                TypeSystemContext context    = TypeSystemContextFactory.Create();
                DefType           targetType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle);

                // Method being called...
                MethodDesc targetVirtualMethod = ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(context, declaringType, methodNameAndSignature);

                if (targetVirtualMethod == null)
                {
                    // If we can't find the method in the type system, it must only be present in the static environment. Search there instead.
                    TypeSystemContextFactory.Recycle(context);
                    return(ResolveInterfaceGenericVirtualMethodSlot_Static(targetTypeHandle, ref declaringType, ref methodNameAndSignature));
                }

                TypeDesc   instanceDefTypeToExamine;
                MethodDesc newlyFoundVirtualMethod = LazyVTableResolver.ResolveInterfaceMethodToVirtualMethod(targetType, out instanceDefTypeToExamine, targetVirtualMethod);

                targetVirtualMethod = newlyFoundVirtualMethod;

                // The pregenerated base type must be the one that implements the interface method
                // Call into Redhawk to deal with this.
                if ((newlyFoundVirtualMethod == null) && (instanceDefTypeToExamine != null))
                {
                    TypeSystemContextFactory.Recycle(context);
                    // If we can't find the method in the type system, the overload must be defined in the static environment. Search there instead.
                    return(ResolveInterfaceGenericVirtualMethodSlot_Static(instanceDefTypeToExamine.GetRuntimeTypeHandle(), ref declaringType, ref methodNameAndSignature));
                }

                declaringType          = targetVirtualMethod.OwningType.GetRuntimeTypeHandle();
                methodNameAndSignature = targetVirtualMethod.NameAndSignature;
                TypeSystemContextFactory.Recycle(context);
                return(true);
#else
                Environment.FailFast("GVM Resolution for non template or pregenerated type");
                return(false);
#endif
            }
        }
コード例 #13
0
            internal override bool MatchParsedEntry(RuntimeTypeHandle tentativeType)
            {
                //
                // Entries read from the hashtable are loaded as DefTypes, and compared to the input.
                // This lookup is slower than the lookups using RuntimeTypeHandles, but can handle cases where we don't have
                // RuntimeTypeHandle values for all of the components of the input DefType, but still need to look it up in case the type
                // statically exists and has an existing RuntimeTypeHandle value.
                //
                TypeSystemContext context = _typeToLookup.Context;

                RuntimeTypeHandle[] parsedArgsHandles;
                RuntimeTypeHandle   parsedTypeDefinitionHandle = RuntimeAugments.GetGenericInstantiation(tentativeType, out parsedArgsHandles);

                DefType       parsedTypeDefinition = (DefType)context.ResolveRuntimeTypeHandle(parsedTypeDefinitionHandle);
                Instantiation parsedArgs           = context.ResolveRuntimeTypeHandles(parsedArgsHandles);
                DefType       parsedGenericType    = context.ResolveGenericInstantiation(parsedTypeDefinition, parsedArgs);

                return(parsedGenericType == _typeToLookup);
            }
コード例 #14
0
        public MethodDesc ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(TypeSystemContext context, RuntimeTypeHandle declaringTypeHandle, MethodNameAndSignature methodNameAndSignature)
        {
            TypeDesc   declaringType       = context.ResolveRuntimeTypeHandle(declaringTypeHandle);
            MethodDesc targetVirtualMethod = null;

            foreach (MethodDesc m in declaringType.GetAllMethods())
            {
                if (!m.IsVirtual)
                {
                    continue;
                }

                if (m.NameAndSignature.Equals(methodNameAndSignature))
                {
                    targetVirtualMethod = m;
                }
            }

            return(targetVirtualMethod);
        }
コード例 #15
0
        /// <summary>
        /// Try to figure out field access information based on type metadata for native format types.
        /// </summary>
        /// <param name="metadataReader">Metadata reader for the declaring type</param>
        /// <param name="declaringTypeHandle">Declaring type for the method</param>
        /// <param name="fieldHandle">Field handle</param>
        /// <param name="canonFormKind">Canonical form to use</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static bool TryGetFieldAccessMetadataFromNativeFormatMetadata(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            TypeSystemContext context,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            Field  field     = metadataReader.GetField(fieldHandle);
            string fieldName = metadataReader.GetString(field.Name);

            TypeDesc declaringType = context.ResolveRuntimeTypeHandle(declaringTypeHandle);

#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            if (declaringType is MetadataType)
            {
                return(TryGetFieldAccessMetadataForNativeFormatType(declaringType, fieldName, ref fieldAccessMetadata));
            }
#endif

            return(false);
        }
コード例 #16
0
        /// <summary>
        /// This function is called from the lazy vtable resolver thunks via the UniversalTransitionThunk to compute
        /// the correct resolution of a virtual dispatch.
        /// </summary>
        /// <param name="callerTransitionBlockParam">pointer to the arguments of the called function</param>
        /// <param name="eeTypePointerOffsetAsIntPtr">eeTypePointerOffsetAsIntPtr is the offset from the start of the EEType to the vtable slot</param>
        /// <returns>function pointer of correct override of virtual function</returns>
        unsafe private static IntPtr VTableResolveThunk(IntPtr callerTransitionBlockParam, IntPtr eeTypePointerOffsetAsIntPtr)
        {
            int eeTypePointerOffset = (int)eeTypePointerOffsetAsIntPtr;
            int vtableSlotIndex     = EETypeVTableOffsetToSlotIndex(eeTypePointerOffset);

            Debug.Assert(eeTypePointerOffset == SlotIndexToEETypeVTableOffset(vtableSlotIndex)); // Assert that the round trip through the slot calculations is good

            EEType **thisPointer = *((EEType ***)(((byte *)callerTransitionBlockParam) + ArgIterator.GetThisOffset()));
            EEType * eeType      = *thisPointer;

            RuntimeTypeHandle rth = eeType->ToRuntimeTypeHandle();

            TypeSystemContext context = TypeSystemContextFactory.Create();
            TypeDesc          type    = context.ResolveRuntimeTypeHandle(rth);

            IntPtr functionPointer = ResolveVirtualVTableFunction(type, vtableSlotIndex);

            eeType->GetVTableStartAddress()[vtableSlotIndex] = functionPointer;

            TypeSystemContextFactory.Recycle(context);

            return(functionPointer);
        }
コード例 #17
0
        private bool ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            if (IsPregeneratedOrTemplateRuntimeTypeHandle(targetTypeHandle))
            {
                // If the target type isn't dynamic, or at least is template type generated, the static lookup logic is what we want.
                return(ResolveGenericVirtualMethodTarget_Static(targetTypeHandle, declaringTypeHandle, genericArguments, callingMethodNameAndSignature, out methodPointer, out dictionaryPointer));
            }
            else
            {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
                methodPointer     = IntPtr.Zero;
                dictionaryPointer = IntPtr.Zero;

                TypeSystemContext context    = TypeSystemContextFactory.Create();
                DefType           targetType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle);

                // Method being called...
                MethodDesc targetVirtualMethod = ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(context, declaringTypeHandle, callingMethodNameAndSignature);

                if (targetVirtualMethod == null)
                {
                    // If we can't find the method in the type system, it must only be present in the static environment. Search there instead.
                    TypeSystemContextFactory.Recycle(context);
                    return(ResolveGenericVirtualMethodTarget_Static(targetTypeHandle, declaringTypeHandle, genericArguments, callingMethodNameAndSignature, out methodPointer, out dictionaryPointer));
                }

                MethodDesc dispatchMethod = targetType.FindVirtualFunctionTargetMethodOnObjectType(targetVirtualMethod);

                if (dispatchMethod == null)
                {
                    return(false);
                }

                Instantiation targetMethodInstantiation  = context.ResolveRuntimeTypeHandles(genericArguments);
                MethodDesc    instantiatedDispatchMethod = dispatchMethod.Context.ResolveGenericMethodInstantiation(dispatchMethod.OwningType.IsValueType /* get the unboxing stub */,
                                                                                                                    dispatchMethod.OwningType.GetClosestDefType(),
                                                                                                                    dispatchMethod.NameAndSignature,
                                                                                                                    targetMethodInstantiation, IntPtr.Zero, false);

                GenericDictionaryCell cell = GenericDictionaryCell.CreateMethodCell(instantiatedDispatchMethod, false);
                using (LockHolder.Hold(_typeLoaderLock))
                {
                    // Now that we hold the lock, we may find that existing types can now find
                    // their associated RuntimeTypeHandle. Flush the type builder states as a way
                    // to force the reresolution of RuntimeTypeHandles which couldn't be found before.
                    context.FlushTypeBuilderStates();

                    TypeBuilder.ResolveSingleCell(cell, out methodPointer);
                }

                TypeSystemContextFactory.Recycle(context);

                return(true);
#else
                methodPointer     = IntPtr.Zero;
                dictionaryPointer = IntPtr.Zero;
                Environment.FailFast("GVM Resolution for non template or pregenerated type");
                return(false);
#endif
            }
        }
コード例 #18
0
        // This method computes the method pointer and dictionary pointer for a GVM.
        // Inputs:
        //      - targetTypeHanlde: target type on which the GVM is implemented
        //      - nameAndSignature: name and signature of the GVM method
        //      - genericMethodArgumentHandles: GVM instantiation arguments
        // Outputs:
        //      - methodPointer: pointer to the GVM's implementation
        //      - dictionaryPointer: (if applicable) pointer to the dictionary to be used with the GVM call
        public bool TryGetGenericVirtualMethodPointer(RuntimeTypeHandle targetTypeHandle, MethodNameAndSignature nameAndSignature, RuntimeTypeHandle[] genericMethodArgumentHandles, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            methodPointer = dictionaryPointer = IntPtr.Zero;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            DefType            targetType          = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle);
            Instantiation      methodInstantiation = context.ResolveRuntimeTypeHandles(genericMethodArgumentHandles);
            InstantiatedMethod method = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, targetType, nameAndSignature, methodInstantiation, IntPtr.Zero, false);

            if (!method.CanShareNormalGenericCode())
            {
                // First see if we can find an exact method implementation for the GVM (avoid using USG implementations if we can,
                // because USG code is much slower).
                if (TryLookupExactMethodPointerForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out methodPointer))
                {
                    Debug.Assert(methodPointer != IntPtr.Zero);
                    TypeSystemContextFactory.Recycle(context);
                    return(true);
                }
            }

            // If we cannot find an exact method entry point, look for an equivalent template and compute the generic dictinoary
            TemplateLocator    templateLocator  = new TemplateLocator();
            NativeLayoutInfo   nativeLayoutInfo = new NativeLayoutInfo();
            InstantiatedMethod templateMethod   = templateLocator.TryGetGenericMethodTemplate(method, out nativeLayoutInfo.Module, out nativeLayoutInfo.Token);

            if (templateMethod == null)
            {
                return(false);
            }

            methodPointer = templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal) ?
                            templateMethod.UsgFunctionPointer :
                            templateMethod.FunctionPointer;

            if (!TryLookupGenericMethodDictionaryForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out dictionaryPointer))
            {
                using (LockHolder.Hold(_typeLoaderLock))
                {
                    // Now that we hold the lock, we may find that existing types can now find
                    // their associated RuntimeTypeHandle. Flush the type builder states as a way
                    // to force the reresolution of RuntimeTypeHandles which couldn't be found before.
                    context.FlushTypeBuilderStates();

                    if (!TypeBuilder.TryBuildGenericMethod(method, out dictionaryPointer))
                    {
                        return(false);
                    }
                }
            }

            Debug.Assert(methodPointer != IntPtr.Zero && dictionaryPointer != IntPtr.Zero);

            if (templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal))
            {
                // Check if we need to wrap the method pointer into a calling convention converter thunk
                if (!TypeLoaderEnvironment.Instance.MethodSignatureHasVarsNeedingCallingConventionConverter(context, nameAndSignature.Signature))
                {
                    TypeSystemContextFactory.Recycle(context);
                    return(true);
                }

                RuntimeTypeHandle[] typeArgs = Array.Empty <RuntimeTypeHandle>();

                if (RuntimeAugments.IsGenericType(targetTypeHandle))
                {
                    RuntimeAugments.GetGenericInstantiation(targetTypeHandle, out typeArgs);
                }

                // Create a CallingConventionConverter to call the method correctly
                IntPtr thunkPtr = CallConverterThunk.MakeThunk(
                    CallConverterThunk.ThunkKind.StandardToGenericInstantiating,
                    methodPointer,
                    nameAndSignature.Signature,
                    dictionaryPointer,
                    typeArgs,
                    genericMethodArgumentHandles);

                Debug.Assert(thunkPtr != IntPtr.Zero);

                methodPointer = thunkPtr;
                // Set dictionaryPointer to null so we don't make a fat function pointer around the whole thing.
                dictionaryPointer = IntPtr.Zero;

                // TODO! add a new call converter thunk that will pass the instantiating arg through and use a fat function pointer.
                // should allow us to make fewer thunks.
            }

            TypeSystemContextFactory.Recycle(context);
            return(true);
        }