private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch)
        {
            uint numTargetImplementations = entryParser.GetUnsigned();

            for (uint j = 0; j < numTargetImplementations; j++)
            {
                uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken);
                RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

#if REFLECTION_EXECUTION_TRACE
                ReflectionExecutionLogger.WriteLine("    Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle));
#endif

                uint numIfaceImpls = entryParser.GetUnsigned();

                for (uint k = 0; k < numIfaceImpls; k++)
                {
                    RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                    uint numIfaceSigs = entryParser.GetUnsigned();

                    if (!openTargetTypeHandle.Equals(implementingTypeHandle))
                    {
                        // Skip over signatures data
                        for (uint l = 0; l < numIfaceSigs; l++)
                            entryParser.GetUnsigned();

                        continue;
                    }

                    for (uint l = 0; l < numIfaceSigs; l++)
                    {
                        RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle);

                        NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetRvaFromIndex(entryParser.GetUnsigned()));
                        IntPtr currentIfaceSigPtr = ifaceSigParser.Reader.OffsetToAddress(ifaceSigParser.Offset);

                        if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(currentIfaceSigPtr, targetTypeInstantiation, null, out currentIfaceTypeHandle, out currentIfaceSigPtr))
                        {
                            Debug.Assert(!currentIfaceTypeHandle.IsNull());

                            if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) ||
                                (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle)))
                            {
#if REFLECTION_EXECUTION_TRACE
                                ReflectionExecutionLogger.WriteLine("    " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!");
#endif
                                // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller
                                declaringType = targetTypeHandle;
                                methodNameAndSignature = targetMethodNameAndSignature;
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }
        public bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, ref string methodName, ref RuntimeMethodSignature methodSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated)
        {
            MethodNameAndSignature methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature);

#if REFLECTION_EXECUTION_TRACE
            ReflectionExecutionLogger.WriteLine("GVM resolution starting for " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name + "(...)  on a target of type " + GetTypeNameDebug(targetHandle) + " ...");
#endif

            if (RuntimeAugments.IsInterface(declaringType))
            {
                methodPointer = IntPtr.Zero;
                dictionaryPointer = IntPtr.Zero;

                slotUpdated = ResolveInterfaceGenericVirtualMethodSlot(targetHandle, ref declaringType, ref methodNameAndSignature);

                methodName = methodNameAndSignature.Name;
                methodSignature = methodNameAndSignature.Signature;
                return slotUpdated;
            }
            else
            {
                slotUpdated = false;
                return ResolveGenericVirtualMethodTarget(targetHandle, declaringType, genericArguments, methodNameAndSignature, out methodPointer, out dictionaryPointer);
            }
        }
Beispiel #3
0
        public override bool Equals(object compare)
        {
            if (compare == null)
            {
                return(false);
            }

            MethodNameAndSignature other = compare as MethodNameAndSignature;

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

            if (Name != other.Name)
            {
                return(false);
            }

            // Optimistically compare signatures by pointer first
            if (Signature == other.Signature)
            {
                return(true);
            }

            // Walk both signatures to check for equality the slow way
            return(RuntimeAugments.TypeLoaderCallbacks.CompareMethodSignatures(Signature, other.Signature));
        }
Beispiel #4
0
        public RuntimeMethodDesc(bool unboxingStub, DefType owningType,
            MethodNameAndSignature nameAndSignature, int hashcode)
        {
            _owningType = owningType;
            _nameAndSignature = nameAndSignature;
            _unboxingStub = unboxingStub;
            SetHashCode(hashcode);

#if DEBUG
            DebugName = this.ToString();
#endif
        }
Beispiel #5
0
        private unsafe static IntPtr GVMLookupForSlotWorker(RuntimeTypeHandle type, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature methodNameAndSignature)
        {
            bool slotChanged = false;

            IntPtr resolution = IntPtr.Zero;

            // Otherwise, walk parent hierarchy attempting to resolve
            EETypePtr eetype = type.ToEETypePtr();

            IntPtr functionPointer   = IntPtr.Zero;
            IntPtr genericDictionary = IntPtr.Zero;

            while (!eetype.IsNull)
            {
                RuntimeTypeHandle handle          = new RuntimeTypeHandle(eetype);
                string            methodName      = methodNameAndSignature.Name;
                IntPtr            methodSignature = methodNameAndSignature.Signature;
                if (RuntimeAugments.Callbacks.TryGetGenericVirtualTargetForTypeAndSlot(handle, ref declaringType, ref genericArguments, ref methodName, ref methodSignature, out functionPointer, out genericDictionary, out slotChanged))
                {
                    methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature);

                    if (!slotChanged)
                    {
                        resolution = FunctionPointerOps.GetGenericMethodFunctionPointer(functionPointer, genericDictionary);
                    }
                    break;
                }

                eetype = eetype.BaseType;
            }

            // If the current slot to examine has changed, restart the lookup.
            // This happens when there is an interface call.
            if (slotChanged)
            {
                return(GVMLookupForSlotWorker(type, declaringType, genericArguments, methodNameAndSignature));
            }

            if (resolution == IntPtr.Zero)
            {
                Environment.FailFast("GVM resolution failure");
            }

            return(resolution);
        }
        private static unsafe IntPtr GVMLookupForSlotWorker(RuntimeTypeHandle type, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature methodNameAndSignature)
        {
            bool slotChanged = false;

            IntPtr resolution = IntPtr.Zero;

            // Otherwise, walk parent hierarchy attempting to resolve
            EETypePtr eetype = type.ToEETypePtr();

            IntPtr functionPointer = IntPtr.Zero;
            IntPtr genericDictionary = IntPtr.Zero;

            while (!eetype.IsNull)
            {
                RuntimeTypeHandle handle = new RuntimeTypeHandle(eetype);
                string methodName = methodNameAndSignature.Name;
                RuntimeMethodSignature methodSignature = methodNameAndSignature.Signature;
                if (RuntimeAugments.TypeLoaderCallbacks.TryGetGenericVirtualTargetForTypeAndSlot(handle, ref declaringType, genericArguments, ref methodName, ref methodSignature, out functionPointer, out genericDictionary, out slotChanged))
                {
                    methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature);

                    if (!slotChanged)
                        resolution = FunctionPointerOps.GetGenericMethodFunctionPointer(functionPointer, genericDictionary);
                    break;
                }

                eetype = eetype.BaseType;
            }

            // If the current slot to examine has changed, restart the lookup.
            // This happens when there is an interface call.
            if (slotChanged)
            {
                return GVMLookupForSlotWorker(type, declaringType, genericArguments, methodNameAndSignature);
            }

            if (resolution == IntPtr.Zero)
            {
                Environment.FailFast("GVM resolution failure");
            }

            return resolution;
        }
        public uint GetGenericArgumentCountFromMethodNameAndSignature(MethodNameAndSignature signature)
        {
            if (signature.Signature.IsNativeLayoutSignature)
            {
                IntPtr sigPtr = signature.Signature.NativeLayoutSignature;
                NativeReader reader = GetNativeLayoutInfoReader(RuntimeAugments.GetModuleFromPointer(sigPtr));
                NativeParser parser = new NativeParser(reader, reader.AddressToOffset(sigPtr));

                return GetGenericArgCountFromSig(parser);
            }
            else
            {
                var metadataReader = ModuleList.Instance.GetMetadataReaderForModule(signature.Signature.ModuleHandle);
                var methodHandle = signature.Signature.Token.AsHandle().ToMethodHandle(metadataReader);

                var method = methodHandle.GetMethod(metadataReader);
                var methodSignature = method.Signature.GetMethodSignature(metadataReader);
                return checked((uint)methodSignature.GenericParameterCount);
            }
        }
Beispiel #8
0
        public override bool Equals(object compare)
        {
            if (compare == null)
            {
                return(false);
            }

            MethodNameAndSignature other = compare as MethodNameAndSignature;

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

            if (Name != other.Name)
            {
                return(false);
            }

            return(Signature.Equals(other.Signature));
        }
        //
        // Parse a native layout signature pointed to by "signature" in the executable image, optionally using
        // "typeArgs" and "methodArgs" for generic type parameter substitution.  The first field in "signature"
        // must be an encoded method but any data beyond that is user-defined and returned in "remainingSignature"
        //
        public bool GetMethodFromSignatureAndContext(IntPtr signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles, out IntPtr remainingSignature)
        {
            remainingSignature = signature;
            createdType = default(RuntimeTypeHandle);
            nameAndSignature = null;
            genericMethodTypeArgumentHandles = null;
            TypeSystemContext context = TypeSystemContextFactory.Create();

            MethodDesc parsedMethod = TryParseNativeSignature(context, ref remainingSignature, typeArgs, methodArgs, true) as MethodDesc;
            if (parsedMethod == null)
                return false;

            if (!EnsureTypeHandleForType(parsedMethod.OwningType))
                return false;

            createdType = parsedMethod.OwningType.RuntimeTypeHandle;
            nameAndSignature = parsedMethod.NameAndSignature;
            if (parsedMethod.Instantiation.Length > 0)
            {
                genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedMethod.Instantiation.Length];
                for (int i = 0; i < parsedMethod.Instantiation.Length; ++i)
                {
                    if (!EnsureTypeHandleForType(parsedMethod.Instantiation[i]))
                        return false;

                    genericMethodTypeArgumentHandles[i] = parsedMethod.Instantiation[i].RuntimeTypeHandle;
                }
            }

            TypeSystemContextFactory.Recycle(context);

            return true;
        }
        private unsafe bool TryGetStaticRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs)
        {
            declaringTypeHandle = default(RuntimeTypeHandle);
            nameAndSignature = null;
            genericMethodArgs = null;

            // Make sure it's not a dynamically allocated RuntimeMethodHandle before we attempt to use it to parse native layout data
            Debug.Assert(((*(IntPtr*)&runtimeMethodHandle).ToInt64() & 0x1) == 0);

            RuntimeMethodHandleInfo* methodData = *(RuntimeMethodHandleInfo**)&runtimeMethodHandle;

            IntPtr remainingSignature;
            return GetMethodFromSignatureAndContext(methodData->NativeLayoutInfoSignature, null, null, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs, out remainingSignature);
        }
        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
            }
        }
        private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            methodPointer = dictionaryPointer = IntPtr.Zero;

            // Get the open type definition of the containing type of the generic virtual method being resolved
            RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType);

            // Get the open type definition of the current type of the object instance on which the GVM is being resolved
            RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle);

            int hashCode = openCallingTypeHandle.GetHashCode();
            hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode();

#if REFLECTION_EXECUTION_TRACE
            ReflectionExecutionLogger.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name);
#endif

            foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle)))
            {
                NativeReader gvmTableReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader))
                    continue;

                NativeReader nativeLayoutReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader))
                    continue;

                NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0);
                NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser);
                ExternalReferencesTable extRefs = default(ExternalReferencesTable);
                extRefs.InitializeCommonFixupsTable(moduleHandle);

                var lookup = gvmHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle))
                        continue;

                    RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle))
                        continue;

                    uint parsedCallingNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedCallingNameAndSigToken);

                    if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature))
                        continue;

                    uint parsedTargetMethodNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedTargetMethodNameAndSigToken);

                    Debug.Assert(targetMethodNameAndSignature != null);

                    return TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer);
                }
            }

            return false;
        }
Beispiel #13
0
 public abstract bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs);
 public bool TryGetGenericMethodDictionaryForComponents(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle[] genericMethodArgHandles, MethodNameAndSignature nameAndSignature, out IntPtr methodDictionary)
 {
     throw new NotImplementedException();
 }
        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
            }
        }
 public bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs)
 {
     return runtimeMethodHandle.IsDynamic() ?
         TryGetDynamicRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs) :
         TryGetStaticRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs);
 }
 public bool TryGetGenericVirtualMethodPointer(RuntimeTypeHandle targetTypeHandle, MethodNameAndSignature nameAndSignature, RuntimeTypeHandle[] genericMethodArgumentHandles, out IntPtr methodPointer, out IntPtr dictionaryPointer)
 {
     throw new NotImplementedException();
 }
 public override bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs)
 {
     return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs);
 }
 public bool TryGetGenericMethodComponents(IntPtr methodDictionary, out RuntimeTypeHandle declaringType, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgumentHandles)
 {
     throw new NotImplementedException();
 }
 public bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs)
 {
     throw new NotImplementedException();
 }
 public bool TryGetMethodNameAndSignatureFromNativeLayoutOffset(IntPtr moduleHandle, uint nativeLayoutOffset, out MethodNameAndSignature nameAndSignature)
 {
     throw new NotImplementedException();
 }
        private unsafe bool TryGetDynamicRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs)
        {
            IntPtr runtimeMethodHandleValue = *(IntPtr*)&runtimeMethodHandle;
            Debug.Assert((runtimeMethodHandleValue.ToInt64() & 0x1) == 0x1);

            // Special flag in the handle value to indicate it was dynamically allocated, and doesn't point into the InvokeMap blob
            runtimeMethodHandleValue = runtimeMethodHandleValue - 1;

            DynamicMethodHandleInfo* methodData = (DynamicMethodHandleInfo*)runtimeMethodHandleValue.ToPointer();
            declaringTypeHandle = *(RuntimeTypeHandle*)&(methodData->DeclaringType);
            genericMethodArgs = Empty<RuntimeTypeHandle>.Array;

            if (methodData->NumGenericArgs > 0)
            {
                IntPtr* genericArgPtr = &(methodData->GenericArgsArray);
                genericMethodArgs = new RuntimeTypeHandle[methodData->NumGenericArgs];
                for (int i = 0; i < methodData->NumGenericArgs; i++)
                {
                    genericMethodArgs[i] = *(RuntimeTypeHandle*)&(genericArgPtr[i]);
                }
            }

            if (methodData->MethodSignature.IsNativeLayoutSignature)
            {
                // MethodName points to the method name in NativeLayout format, so we parse it using a NativeParser
                IntPtr methodNamePtr = methodData->MethodName;
                string name = GetStringFromMemoryInNativeFormat(methodNamePtr);

                nameAndSignature = new MethodNameAndSignature(name, methodData->MethodSignature);
            }
            else
            {
                // method signature is NativeFormat
                var metadataReader = ModuleList.Instance.GetMetadataReaderForModule(methodData->MethodSignature.ModuleHandle);
                var methodHandle = methodData->MethodSignature.Token.AsHandle().ToMethodHandle(metadataReader);

                var method = methodHandle.GetMethod(metadataReader);
                nameAndSignature = new MethodNameAndSignature(metadataReader.GetConstantStringValue(method.Name).Value, methodData->MethodSignature);
            }

            return true;
        }
        private bool ResolveInterfaceGenericVirtualMethodSlot_Static(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature)
        {
            // Get the open type definition of the containing type of the generic virtual method being resolved
            RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType);

            // Get the open type definition of the current type of the object instance on which the GVM is being resolved
            RuntimeTypeHandle openTargetTypeHandle;
            RuntimeTypeHandle[] targetTypeInstantiation;
            openTargetTypeHandle = GetOpenTypeDefinition(targetTypeHandle, out targetTypeInstantiation);

#if REFLECTION_EXECUTION_TRACE
            ReflectionExecutionLogger.WriteLine("INTERFACE GVM call = " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name);
#endif

            foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle)))
            {
                NativeReader gvmTableReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.InterfaceGenericVirtualMethodTable, out gvmTableReader))
                    continue;

                NativeReader nativeLayoutReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader))
                    continue;

                NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0);
                NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser);

                ExternalReferencesTable extRefs = default(ExternalReferencesTable);
                extRefs.InitializeCommonFixupsTable(moduleHandle);

                var lookup = gvmHashtable.Lookup(openCallingTypeHandle.GetHashCode());

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    RuntimeTypeHandle interfaceTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!openCallingTypeHandle.Equals(interfaceTypeHandle))
                        continue;

                    uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken);

                    if (!interfaceMethodNameAndSignature.Equals(methodNameAndSignature))
                        continue;

                    // For each of the possible GVM slot targets for the current interface call, we will do the following:
                    //
                    //  Step 1: Scan the types that currently provide implementations for the current GVM slot target, and look
                    //          for ones that match the target object's type.
                    //
                    //  Step 2: For each type that we find in step #1, get a list of all the interfaces that the current GVM target
                    //          provides an implementation for
                    //
                    //  Step 3: For each interface in the list in step #2, parse the signature of that interface, do the generic argument
                    //          substitution (in case of a generic interface), and check if this interface signature is assignable from the
                    //          calling interface signature (from the name and sig input). if there is an exact match based on 
                    //          interface type, then we've found the right slot. Otherwise, re-scan the entry again and see if some interface 
                    //          type is compatible with the initial slots interface by means of variance. 
                    //          This is done by calling the TypeLoaderEnvironment helper function.
                    //
                    // Example:
                    //      public interface IFoo<out T, out U>
                    //      {
                    //          string M1<V>();
                    //      }
                    //      public class Foo1<T, U> : IFoo<T, U>, IFoo<Kvp<T, string>, U>
                    //      {
                    //          string IFoo<T, U>.M1<V>() { ... }
                    //          public virtual string M1<V>() { ... }
                    //      }
                    //      public class Foo2<T, U> : Foo1<object, U>, IFoo<U, T>
                    //      {
                    //          string IFoo<U, T>.M1<V>() { ... }
                    //      }        
                    //
                    //  GVM Table layout for IFoo<T, U>.M1<V>:
                    //  {
                    //      InterfaceTypeHandle = IFoo<T, U>
                    //      InterfaceMethodNameAndSignature = { "M1", SigOf(string M1) }
                    //      GVMTargetSlots[] = 
                    //      {
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo1<T, U>
                    //              ImplementingTypes[] = {
                    //                  ImplementingTypeHandle = Foo1<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<!0, !1>) }
                    //              }
                    //          },
                    //
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo1<T, U>
                    //              ImplementingTypes[] = {
                    //                  ImplementingTypeHandle = Foo1<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<Kvp<!0, string>, !1>) }
                    //              }
                    //          },
                    //
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo2<T, U>
                    //              ImplementingTypes = {
                    //                  ImplementingTypeHandle = Foo2<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<!1, !0>) }
                    //              }
                    //          }, 
                    //      }
                    //  }
                    //

                    uint currentOffset = entryParser.Offset;

                    // Non-variant dispatch of a variant generic interface generic virtual method.
                    if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, false))
                    {
                        return true;
                    }

                    entryParser.Offset = currentOffset;

                    // Variant dispatch of a variant generic interface generic virtual method.
                    if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, true))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        public bool TryGetMethodNameAndSignatureFromNativeLayoutOffset(IntPtr moduleHandle, uint nativeLayoutOffset, out MethodNameAndSignature nameAndSignature)
        {
            nameAndSignature = null;

            NativeReader reader = GetNativeLayoutInfoReader(moduleHandle);
            NativeParser parser = new NativeParser(reader, nativeLayoutOffset);
            if (parser.IsNull)
                return false;

            IntPtr methodSigPtr;
            IntPtr methodNameSigPtr;
            nameAndSignature = GetMethodNameAndSignature(ref parser, out methodNameSigPtr, out methodSigPtr);
            return true;
        }
        public bool TryGetGenericMethodDictionaryForComponents(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle[] genericMethodArgHandles, MethodNameAndSignature nameAndSignature, out IntPtr methodDictionary)
        {
            if (TryLookupGenericMethodDictionaryForComponents(declaringTypeHandle, nameAndSignature, genericMethodArgHandles, out methodDictionary))
                return true;

            using (LockHolder.Hold(_typeLoaderLock))
            {
                return TypeBuilder.TryBuildGenericMethod(declaringTypeHandle, genericMethodArgHandles, nameAndSignature, out methodDictionary);
            }
        }
        public bool TryGetMethodNameAndSignatureFromNativeLayoutSignature(ref IntPtr signature, out MethodNameAndSignature nameAndSignature)
        {
            nameAndSignature = null;

            NativeReader reader = GetNativeLayoutInfoReader(RuntimeAugments.GetModuleFromPointer(signature));
            uint offset = reader.AddressToOffset(signature);
            NativeParser parser = new NativeParser(reader, offset);
            if (parser.IsNull)
                return false;

            IntPtr methodSigPtr;
            IntPtr methodNameSigPtr;
            nameAndSignature = GetMethodNameAndSignature(ref parser, out methodNameSigPtr, out methodSigPtr);
            signature = (IntPtr)((long)signature + (parser.Offset - offset));
            return true;
        }
        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;
        }
Beispiel #28
0
        private static unsafe IntPtr GVMLookupForSlotWorker(RuntimeTypeHandle type, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature methodNameAndSignature)
        {
            bool slotChanged = false;

            IntPtr resolution        = IntPtr.Zero;
            IntPtr functionPointer   = IntPtr.Zero;
            IntPtr genericDictionary = IntPtr.Zero;

            bool lookForDefaultImplementations = false;

again:
            // Walk parent hierarchy attempting to resolve
            EETypePtr eeType = type.ToEETypePtr();

            while (!eeType.IsNull)
            {
                RuntimeTypeHandle handle          = new RuntimeTypeHandle(eeType);
                string            methodName      = methodNameAndSignature.Name;
                RuntimeSignature  methodSignature = methodNameAndSignature.Signature;
                if (RuntimeAugments.TypeLoaderCallbacks.TryGetGenericVirtualTargetForTypeAndSlot(handle, ref declaringType, genericArguments, ref methodName, ref methodSignature, lookForDefaultImplementations, out functionPointer, out genericDictionary, out slotChanged))
                {
                    methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature);

                    if (!slotChanged)
                    {
                        resolution = FunctionPointerOps.GetGenericMethodFunctionPointer(functionPointer, genericDictionary);
                    }
                    break;
                }

                eeType = eeType.BaseType;
            }

            // If the current slot to examine has changed, restart the lookup.
            // This happens when there is an interface call.
            if (slotChanged)
            {
                return(GVMLookupForSlotWorker(type, declaringType, genericArguments, methodNameAndSignature));
            }

            if (resolution == IntPtr.Zero &&
                !lookForDefaultImplementations &&
                declaringType.ToEETypePtr().IsInterface)
            {
                lookForDefaultImplementations = true;
                goto again;
            }

            if (resolution == IntPtr.Zero)
            {
                var sb = new System.Text.StringBuilder();
                sb.AppendLine("Generic virtual method pointer lookup failure.");
                sb.AppendLine();
                sb.AppendLine("Declaring type: " + declaringType.LastResortToString);
                sb.AppendLine("Target type: " + type.LastResortToString);
                sb.AppendLine("Method name: " + methodNameAndSignature.Name);
                sb.AppendLine("Instantiation:");
                for (int i = 0; i < genericArguments.Length; i++)
                {
                    sb.AppendLine("  Argument " + i.LowLevelToString() + ": " + genericArguments[i].LastResortToString);
                }

                Environment.FailFast(sb.ToString());
            }

            return(resolution);
        }
 public bool TryGetMethodNameAndSignatureFromNativeLayoutSignature(ref IntPtr signature, out MethodNameAndSignature nameAndSignature)
 {
     throw new NotImplementedException();
 }