/// <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
        }
        internal bool GetMethodFromSignatureAndContext(ref NativeParser parser, TypeManagerHandle moduleHandle, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
        {
            createdType = default(RuntimeTypeHandle);
            nameAndSignature = null;
            genericMethodTypeArgumentHandles = null;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            MethodDesc parsedMethod = TryParseNativeSignatureWorker(context, moduleHandle, ref parser, 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.IsMethodDefinition && 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;
        }
Esempio n. 3
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);
        }
Esempio n. 4
0
        public bool TryComputeHasInstantiationDeterminedSize(RuntimeTypeHandle typeHandle, out bool hasInstantiationDeterminedSize)
        {
            TypeSystemContext context = TypeSystemContextFactory.Create();
            bool success = TryComputeHasInstantiationDeterminedSize(typeHandle, context, out hasInstantiationDeterminedSize);
            TypeSystemContextFactory.Recycle(context);

            return success;
        }
Esempio n. 5
0
        /// <summary>
        /// Attempt to convert the dispatch cell to a metadata token to a more efficient vtable dispatch or interface/slot dispatch.
        /// Failure to convert is not a correctness issue. We also support performing a dispatch based on metadata token alone.
        /// </summary>
        private static DispatchCellInfo ConvertDispatchCellInfo_Inner(NativeFormatModuleInfo module, DispatchCellInfo cellInfo)
        {
            Debug.Assert(cellInfo.CellType == DispatchCellType.MetadataToken);

            TypeSystemContext context = TypeSystemContextFactory.Create();

            MethodDesc targetMethod = context.ResolveMetadataUnit(module).GetMethod(cellInfo.MetadataToken.AsHandle(), null);
            Debug.Assert(!targetMethod.HasInstantiation); // At this time we do not support generic virtuals through the dispatch mechanism
            Debug.Assert(targetMethod.IsVirtual);
            if (targetMethod.OwningType.IsInterface)
            {
                if (!LazyVTableResolver.TryGetInterfaceSlotNumberFromMethod(targetMethod, out cellInfo.InterfaceSlot))
                {
                    // Unable to resolve interface method. Fail, by not mutating cellInfo
                    return cellInfo;
                }

                if (!targetMethod.OwningType.RetrieveRuntimeTypeHandleIfPossible())
                {
                    new TypeBuilder().BuildType(targetMethod.OwningType);
                }

                cellInfo.CellType = DispatchCellType.InterfaceAndSlot;
                cellInfo.InterfaceType = targetMethod.OwningType.RuntimeTypeHandle.ToIntPtr();
                cellInfo.MetadataToken = 0;
            }
            else
            {
                // Virtual function case, attempt to resolve to a VTable slot offset.
                // If the offset is less than 4096 update the cellInfo
#if DEBUG
                // The path of resolving a metadata token at dispatch time is relatively rare in practice.
                // Force it to occur in debug builds with much more regularity
                if ((s_ConvertDispatchCellInfoCounter % 16) == 0)
                {
                    s_ConvertDispatchCellInfoCounter++;
                    TypeSystemContextFactory.Recycle(context);
                    return cellInfo;
                }
                s_ConvertDispatchCellInfoCounter++;
#endif

                int slotIndexOfMethod = LazyVTableResolver.VirtualMethodToSlotIndex(targetMethod);
                int vtableOffset = -1;
                if (slotIndexOfMethod >= 0)
                    vtableOffset = LazyVTableResolver.SlotIndexToEETypeVTableOffset(slotIndexOfMethod);
                if ((vtableOffset < 4096) && (vtableOffset != -1))
                {
                    cellInfo.CellType = DispatchCellType.VTableOffset;
                    cellInfo.VTableOffset = checked((uint)vtableOffset);
                    cellInfo.MetadataToken = 0;
                }
                // Otherwise, do nothing, and resolve with a metadata dispatch later
            }

            TypeSystemContextFactory.Recycle(context);
            return cellInfo;
        }
Esempio n. 6
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;
        }
Esempio n. 7
0
        public bool ConversionToCanonFormIsAChange(RuntimeTypeHandle[] genericArgHandles, CanonicalFormKind kind)
        {
            // Todo: support for universal canon type?

            TypeSystemContext context = TypeSystemContextFactory.Create();

            Instantiation genericArgs = context.ResolveRuntimeTypeHandles(genericArgHandles);
            bool result;
            context.ConvertInstantiationToCanonForm(genericArgs, kind, out result);

            TypeSystemContextFactory.Recycle(context);

            return result;
        }
Esempio n. 8
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
            }
        }
        /// <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
        }
Esempio n. 10
0
        internal bool GetTypeFromSignatureAndContext(ref NativeParser parser, TypeManagerHandle moduleHandle, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType)
        {
            createdType = default(RuntimeTypeHandle);
            TypeSystemContext context = TypeSystemContextFactory.Create();

            TypeDesc parsedType = TryParseNativeSignatureWorker(context, moduleHandle, ref parser, typeArgs, methodArgs, false) as TypeDesc;
            if (parsedType == null)
                return false;

            if (!EnsureTypeHandleForType(parsedType))
                return false;

            createdType = parsedType.RuntimeTypeHandle;

            TypeSystemContextFactory.Recycle(context);
            return true;
        }
Esempio n. 11
0
        //
        // 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 type but any data beyond that is user-defined and returned in "remainingSignature"
        //
        public bool GetTypeFromSignatureAndContext(IntPtr signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out IntPtr remainingSignature)
        {
            remainingSignature = signature;
            createdType = default(RuntimeTypeHandle);
            TypeSystemContext context = TypeSystemContextFactory.Create();

            TypeDesc parsedType = TryParseNativeSignature(context, ref remainingSignature, typeArgs, methodArgs, false) as TypeDesc;
            if (parsedType == null)
                return false;

            if (!EnsureTypeHandleForType(parsedType))
                return false;

            createdType = parsedType.RuntimeTypeHandle;

            TypeSystemContextFactory.Recycle(context);
            return true;
        }
Esempio n. 12
0
        /// <summary>
        /// Try to look up field acccess info for given canon in metadata blobs for all available modules.
        /// </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>
        public static bool TryGetFieldAccessMetadata(
            MetadataReader metadataReader,
            RuntimeTypeHandle runtimeTypeHandle,
            FieldHandle fieldHandle,
            out FieldAccessMetadata fieldAccessMetadata)
        {
            fieldAccessMetadata = default(FieldAccessMetadata);

            if (TryGetFieldAccessMetadataFromFieldAccessMap(
                    metadataReader,
                    runtimeTypeHandle,
                    fieldHandle,
                    CanonicalFormKind.Specific,
                    ref fieldAccessMetadata))
            {
                return(true);
            }

            if (TryGetFieldAccessMetadataFromFieldAccessMap(
                    metadataReader,
                    runtimeTypeHandle,
                    fieldHandle,
                    CanonicalFormKind.Universal,
                    ref fieldAccessMetadata))
            {
                return(true);
            }

            TypeSystemContext context = TypeSystemContextFactory.Create();

            bool success = TryGetFieldAccessMetadataFromNativeFormatMetadata(
                metadataReader,
                runtimeTypeHandle,
                fieldHandle,
                context,
                ref fieldAccessMetadata);

            TypeSystemContextFactory.Recycle(context);

            return(success);
        }
Esempio n. 13
0
        private RuntimeTypeHandle GetExternalTypeHandle(NativeFormatModuleInfo moduleHandle, uint typeIndex)
        {
            Debug.Assert(moduleHandle != null);

            RuntimeTypeHandle result;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            {
                NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext();
                nativeLayoutContext._module            = moduleHandle;
                nativeLayoutContext._typeSystemContext = context;

                TypeDesc type = nativeLayoutContext.GetExternalType(typeIndex);
                result = type.RuntimeTypeHandle;
            }
            TypeSystemContextFactory.Recycle(context);

            Debug.Assert(!result.IsNull());
            return(result);
        }
        private RuntimeTypeHandle GetExternalTypeHandle(ref NativeParser parser, uint typeIndex)
        {
            IntPtr moduleHandle = RuntimeAugments.GetModuleFromPointer(parser.Reader.OffsetToAddress(parser.Offset));

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

            RuntimeTypeHandle result;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            {
                NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext();
                nativeLayoutContext._moduleHandle      = moduleHandle;
                nativeLayoutContext._typeSystemContext = context;

                TypeDesc type = nativeLayoutContext.GetExternalType(typeIndex);
                result = type.RuntimeTypeHandle;
            }
            TypeSystemContextFactory.Recycle(context);

            Debug.Assert(!result.IsNull());
            return(result);
        }
Esempio n. 15
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);
        }
        //
        // Lazily parse the method signature, and construct the call converter data
        //
        private void EnsureCallConversionInfoLoaded()
        {
            if (_signatureParsed)
            {
                return;
            }

            lock (this)
            {
                // Check if race was won by another thread and the signature got parsed
                if (_signatureParsed)
                {
                    return;
                }

                TypeSystemContext context = TypeSystemContextFactory.Create();
                {
                    Instantiation typeInstantiation   = Instantiation.Empty;
                    Instantiation methodInstantiation = Instantiation.Empty;

                    if (_typeArgs != null && _typeArgs.Length > 0)
                    {
                        typeInstantiation = context.ResolveRuntimeTypeHandles(_typeArgs);
                    }
                    if (_methodArgs != null && _methodArgs.Length > 0)
                    {
                        methodInstantiation = context.ResolveRuntimeTypeHandles(_methodArgs);
                    }

                    bool       hasThis;
                    TypeDesc[] parameters;
                    bool[]     paramsByRefForced;
                    if (!TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature(context, _methodSignature, typeInstantiation, methodInstantiation, out hasThis, out parameters, out paramsByRefForced))
                    {
                        Debug.Assert(false);
                        Environment.FailFast("Failed to get type handles for parameters in method signature");
                    }
                    Debug.Assert(parameters != null && parameters.Length >= 1);

                    bool[] byRefParameters = new bool[parameters.Length];
                    RuntimeTypeHandle[] parameterHandles = new RuntimeTypeHandle[parameters.Length];

                    for (int j = 0; j < parameters.Length; j++)
                    {
                        ByRefType parameterAsByRefType = parameters[j] as ByRefType;
                        if (parameterAsByRefType != null)
                        {
                            parameterAsByRefType.ParameterType.RetrieveRuntimeTypeHandleIfPossible();
                            parameterHandles[j] = parameterAsByRefType.ParameterType.RuntimeTypeHandle;
                            byRefParameters[j]  = true;
                        }
                        else
                        {
                            parameters[j].RetrieveRuntimeTypeHandleIfPossible();
                            parameterHandles[j] = parameters[j].RuntimeTypeHandle;
                            byRefParameters[j]  = false;
                        }

                        Debug.Assert(!parameterHandles[j].IsNull());
                    }

                    // Build thunk data
                    TypeHandle   thReturnType = new TypeHandle(CallConverterThunk.GetByRefIndicatorAtIndex(0, byRefParameters), parameterHandles[0]);
                    TypeHandle[] thParameters = null;
                    if (parameters.Length > 1)
                    {
                        thParameters = new TypeHandle[parameters.Length - 1];
                        for (int i = 1; i < parameters.Length; i++)
                        {
                            thParameters[i - 1] = new TypeHandle(CallConverterThunk.GetByRefIndicatorAtIndex(i, byRefParameters), parameterHandles[i]);
                        }
                    }

                    _argIteratorData = new ArgIteratorData(hasThis, false, thParameters, thReturnType);

                    // StandardToStandard thunks don't actually need any parameters to change their ABI
                    // so don't force any params to be adjusted
                    if (!StandardToStandardThunk)
                    {
                        _paramsByRefForced = paramsByRefForced;
                    }
                }
                TypeSystemContextFactory.Recycle(context);

                _signatureParsed = true;
            }
        }
Esempio n. 17
0
        private unsafe static void RegularFuncEval(byte *parameterBuffer, uint parameterBufferSize)
        {
            TypesAndValues typesAndValues = new TypesAndValues();

            uint  trash;
            uint  parameterCount;
            uint  parameterValueSize;
            uint  eeTypeCount;
            ulong eeType;
            uint  offset = 0;

            NativeReader reader = new NativeReader(parameterBuffer, parameterBufferSize);

            offset = reader.DecodeUnsigned(offset, out trash); // The VertexSequence always generate a length, I don't really need it.
            offset = reader.DecodeUnsigned(offset, out parameterCount);

            typesAndValues.parameterValues = new byte[parameterCount][];
            for (int i = 0; i < parameterCount; i++)
            {
                offset = reader.DecodeUnsigned(offset, out parameterValueSize);
                byte[] parameterValue = new byte[parameterValueSize];
                for (int j = 0; j < parameterValueSize; j++)
                {
                    uint parameterByte;
                    offset            = reader.DecodeUnsigned(offset, out parameterByte);
                    parameterValue[j] = (byte)parameterByte;
                }
                typesAndValues.parameterValues[i] = parameterValue;
            }
            offset = reader.DecodeUnsigned(offset, out eeTypeCount);
            ulong[] debuggerPreparedExternalReferences = new ulong[eeTypeCount];
            for (int i = 0; i < eeTypeCount; i++)
            {
                offset = reader.DecodeUnsignedLong(offset, out eeType);
                debuggerPreparedExternalReferences[i] = eeType;
            }

            TypeSystemContext typeSystemContext = TypeSystemContextFactory.Create();
            bool hasThis;

            TypeDesc[] parameters;
            bool[]     parametersWithGenericDependentLayout;
            bool       result = TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(typeSystemContext, RuntimeSignature.CreateFromNativeLayoutSignatureForDebugger(offset), Instantiation.Empty, Instantiation.Empty, out hasThis, out parameters, out parametersWithGenericDependentLayout, reader, debuggerPreparedExternalReferences);

            typesAndValues.types = new RuntimeTypeHandle[parameters.Length];

            bool needToDynamicallyLoadTypes = false;

            for (int i = 0; i < typesAndValues.types.Length; i++)
            {
                if (!parameters[i].RetrieveRuntimeTypeHandleIfPossible())
                {
                    needToDynamicallyLoadTypes = true;
                    break;
                }

                typesAndValues.types[i] = parameters[i].GetRuntimeTypeHandle();
            }

            if (needToDynamicallyLoadTypes)
            {
                TypeLoaderEnvironment.Instance.RunUnderTypeLoaderLock(() =>
                {
                    typeSystemContext.FlushTypeBuilderStates();

                    GenericDictionaryCell[] cells = new GenericDictionaryCell[parameters.Length];
                    for (int i = 0; i < cells.Length; i++)
                    {
                        cells[i] = GenericDictionaryCell.CreateTypeHandleCell(parameters[i]);
                    }
                    IntPtr[] eetypePointers;
                    TypeBuilder.ResolveMultipleCells(cells, out eetypePointers);

                    for (int i = 0; i < parameters.Length; i++)
                    {
                        typesAndValues.types[i] = ((EEType *)eetypePointers[i])->ToRuntimeTypeHandle();
                    }
                });
            }

            TypeSystemContextFactory.Recycle(typeSystemContext);

            LocalVariableType[] argumentTypes = new LocalVariableType[parameters.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                // TODO, FuncEval, what these false really means? Need to make sure our format contains those information
                argumentTypes[i] = new LocalVariableType(typesAndValues.types[i], false, false);
            }

            LocalVariableSet.SetupArbitraryLocalVariableSet <TypesAndValues>(HighLevelDebugFuncEvalHelperWithVariables, ref typesAndValues, argumentTypes);
        }
Esempio n. 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);
        }
Esempio n. 19
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
            }
        }
Esempio n. 20
0
        private static void HighLevelDebugFuncEvalHelper()
        {
            uint parameterBufferSize = RuntimeAugments.RhpGetFuncEvalParameterBufferSize();

            IntPtr writeParameterCommandPointer;
            IntPtr debuggerBufferPointer;

            unsafe
            {
                byte *debuggerBufferRawPointer = stackalloc byte[(int)parameterBufferSize];
                debuggerBufferPointer = new IntPtr(debuggerBufferRawPointer);

                WriteParameterCommand writeParameterCommand = new WriteParameterCommand
                {
                    commandCode   = 1,
                    bufferAddress = debuggerBufferPointer.ToInt64()
                };

                writeParameterCommandPointer = new IntPtr(&writeParameterCommand);

                RuntimeAugments.RhpSendCustomEventToDebugger(writeParameterCommandPointer, Unsafe.SizeOf <WriteParameterCommand>());

                // .. debugger magic ... the debuggerBuffer will be filled with parameter data

                TypesAndValues typesAndValues = new TypesAndValues();

                uint  trash;
                uint  parameterCount;
                uint  parameterValue;
                uint  eeTypeCount;
                ulong eeType;
                uint  offset = 0;

                NativeReader reader = new NativeReader(debuggerBufferRawPointer, parameterBufferSize);
                offset = reader.DecodeUnsigned(offset, out trash); // The VertexSequence always generate a length, I don't really need it.
                offset = reader.DecodeUnsigned(offset, out parameterCount);

                typesAndValues.parameterValues = new int[parameterCount];
                for (int i = 0; i < parameterCount; i++)
                {
                    offset = reader.DecodeUnsigned(offset, out parameterValue);
                    typesAndValues.parameterValues[i] = (int)parameterValue;
                }
                offset = reader.DecodeUnsigned(offset, out eeTypeCount);
                for (int i = 0; i < eeTypeCount; i++)
                {
                    // TODO: Stuff these eeType values into the external reference table
                    offset = reader.DecodeUnsignedLong(offset, out eeType);
                }

                TypeSystemContext typeSystemContext = TypeSystemContextFactory.Create();
                bool       hasThis;
                TypeDesc[] parameters;
                bool[]     parametersWithGenericDependentLayout;
                bool       result = TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(typeSystemContext, RuntimeSignature.CreateFromNativeLayoutSignatureForDebugger(offset), Instantiation.Empty, Instantiation.Empty, out hasThis, out parameters, out parametersWithGenericDependentLayout, reader);

                typesAndValues.types = new RuntimeTypeHandle[parameters.Length];

                bool needToDynamicallyLoadTypes = false;
                for (int i = 0; i < typesAndValues.types.Length; i++)
                {
                    if (!parameters[i].RetrieveRuntimeTypeHandleIfPossible())
                    {
                        needToDynamicallyLoadTypes = true;
                        break;
                    }

                    typesAndValues.types[i] = parameters[i].GetRuntimeTypeHandle();
                }

                if (needToDynamicallyLoadTypes)
                {
                    TypeLoaderEnvironment.Instance.RunUnderTypeLoaderLock(() =>
                    {
                        typeSystemContext.FlushTypeBuilderStates();

                        GenericDictionaryCell[] cells = new GenericDictionaryCell[parameters.Length];
                        for (int i = 0; i < cells.Length; i++)
                        {
                            cells[i] = GenericDictionaryCell.CreateTypeHandleCell(parameters[i]);
                        }
                        IntPtr[] eetypePointers;
                        TypeBuilder.ResolveMultipleCells(cells, out eetypePointers);

                        for (int i = 0; i < parameters.Length; i++)
                        {
                            typesAndValues.types[i] = ((EEType *)eetypePointers[i])->ToRuntimeTypeHandle();
                        }
                    });
                }

                TypeSystemContextFactory.Recycle(typeSystemContext);

                LocalVariableType[] argumentTypes = new LocalVariableType[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    // TODO: What these false really means? Need to make sure our format contains those information
                    argumentTypes[i] = new LocalVariableType(typesAndValues.types[i], false, false);
                }

                LocalVariableSet.SetupArbitraryLocalVariableSet <TypesAndValues>(HighLevelDebugFuncEvalHelperWithVariables, ref typesAndValues, argumentTypes);
            }
        }