private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void *cell, ref DispatchCellInfo cellInfo)
        {
            // Type of object we're dispatching on.
            MethodTable *pInstanceType = pObject.GetMethodTable();

            if (cellInfo.CellType == DispatchCellType.InterfaceAndSlot)
            {
                // Type whose DispatchMap is used. Usually the same as the above but for types which implement IDynamicInterfaceCastable
                // we may repeat this process with an alternate type.
                MethodTable *pResolvingInstanceType = pInstanceType;

                IntPtr pTargetCode = DispatchResolve.FindInterfaceMethodImplementationTarget(pResolvingInstanceType,
                                                                                             cellInfo.InterfaceType.ToPointer(),
                                                                                             cellInfo.InterfaceSlot,
                                                                                             ppGenericContext: null);
                if (pTargetCode == IntPtr.Zero && pInstanceType->IsIDynamicInterfaceCastable)
                {
                    // Dispatch not resolved through normal dispatch map, try using the IDynamicInterfaceCastable
                    // This will either give us the appropriate result, or throw.
                    var pfnGetInterfaceImplementation = (delegate * < object, MethodTable *, ushort, IntPtr >)
                                                        pInstanceType->GetClasslibFunction(ClassLibFunctionId.IDynamicCastableGetInterfaceImplementation);
                    pTargetCode = pfnGetInterfaceImplementation(pObject, cellInfo.InterfaceType.ToPointer(), cellInfo.InterfaceSlot);
                    Diagnostics.Debug.Assert(pTargetCode != IntPtr.Zero);
                }
                return(pTargetCode);
            }
            else if (cellInfo.CellType == DispatchCellType.VTableOffset)
            {
                // Dereference VTable
                return(*(IntPtr *)(((byte *)pInstanceType) + cellInfo.VTableOffset));
            }
            else
            {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING_AND_SUPPORTS_TOKEN_BASED_DISPATCH_CELLS
                // Attempt to convert dispatch cell to non-metadata form if we haven't acquired a cache for this cell yet
                if (cellInfo.HasCache == 0)
                {
                    cellInfo = InternalTypeLoaderCalls.ConvertMetadataTokenDispatch(InternalCalls.RhGetModuleFromPointer(cell), cellInfo);
                    if (cellInfo.CellType != DispatchCellType.MetadataToken)
                    {
                        return(RhResolveDispatchWorker(pObject, cell, ref cellInfo));
                    }
                }

                // If that failed, go down the metadata resolution path
                return(InternalTypeLoaderCalls.ResolveMetadataTokenDispatch(InternalCalls.RhGetModuleFromPointer(cell), (int)cellInfo.MetadataToken, new IntPtr(pInstanceType)));
#else
                EH.FallbackFailFast(RhFailFastReason.InternalError, null);
                return(IntPtr.Zero);
#endif
            }
        }
        private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void *cell, ref DispatchCellInfo cellInfo)
        {
            // Type of object we're dispatching on.
            EEType *pInstanceType = pObject.EEType;

            if (cellInfo.CellType == DispatchCellType.InterfaceAndSlot)
            {
                // Type whose DispatchMap is used.
                EEType *pResolvingInstanceType = pInstanceType;

                IntPtr pTargetCode = DispatchResolve.FindInterfaceMethodImplementationTarget(pResolvingInstanceType,
                                                                                             cellInfo.InterfaceType.ToPointer(),
                                                                                             cellInfo.InterfaceSlot);
                return(pTargetCode);
            }
            else if (cellInfo.CellType == DispatchCellType.VTableOffset)
            {
                // Dereference VTable
                return(*(IntPtr *)(((byte *)pInstanceType) + cellInfo.VTableOffset));
            }
            else
            {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING_AND_SUPPORTS_TOKEN_BASED_DISPATCH_CELLS
                // Attempt to convert dispatch cell to non-metadata form if we haven't acquired a cache for this cell yet
                if (cellInfo.HasCache == 0)
                {
                    cellInfo = InternalTypeLoaderCalls.ConvertMetadataTokenDispatch(InternalCalls.RhGetModuleFromPointer(cell), cellInfo);
                    if (cellInfo.CellType != DispatchCellType.MetadataToken)
                    {
                        return(RhResolveDispatchWorker(pObject, cell, ref cellInfo));
                    }
                }

                // If that failed, go down the metadata resolution path
                return(InternalTypeLoaderCalls.ResolveMetadataTokenDispatch(InternalCalls.RhGetModuleFromPointer(cell), (int)cellInfo.MetadataToken, new IntPtr(pInstanceType)));
#else
                EH.FallbackFailFast(RhFailFastReason.InternalError, null);
                return(IntPtr.Zero);
#endif
            }
        }
Example #3
0
        private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void *cell, ref DispatchCellInfo cellInfo)
        {
            // Type of object we're dispatching on.
            EEType *pInstanceType = pObject.EEType;

            if (cellInfo.CellType == DispatchCellType.InterfaceAndSlot)
            {
                // Type whose DispatchMap is used. Usually the same as the above but for types which implement ICastable
                // we may repeat this process with an alternate type.
                EEType *pResolvingInstanceType = pInstanceType;

                IntPtr pTargetCode = DispatchResolve.FindInterfaceMethodImplementationTarget(pResolvingInstanceType,
                                                                                             cellInfo.InterfaceType.ToPointer(),
                                                                                             cellInfo.InterfaceSlot);

                if (pTargetCode == IntPtr.Zero && pInstanceType->IsICastable)
                {
                    // TODO!! BEGIN REMOVE THIS CODE WHEN WE REMOVE ICASTABLE
                    // Dispatch not resolved through normal dispatch map, try using the ICastable
                    // Call the ICastable.IsInstanceOfInterface method directly rather than via an interface
                    // dispatch since we know the method address statically. We ignore any cast error exception
                    // object passed back on failure (result == false) since IsInstanceOfInterface never throws.
                    IntPtr    pfnIsInstanceOfInterface = pInstanceType->ICastableIsInstanceOfInterfaceMethod;
                    Exception castError = null;
                    if (CalliIntrinsics.Call <bool>(pfnIsInstanceOfInterface, pObject, cellInfo.InterfaceType.ToPointer(), out castError))
                    {
                        IntPtr pfnGetImplTypeMethod = pInstanceType->ICastableGetImplTypeMethod;
                        pResolvingInstanceType = (EEType *)CalliIntrinsics.Call <IntPtr>(pfnGetImplTypeMethod, pObject, new IntPtr(cellInfo.InterfaceType.ToPointer()));
                        pTargetCode            = DispatchResolve.FindInterfaceMethodImplementationTarget(pResolvingInstanceType,
                                                                                                         cellInfo.InterfaceType.ToPointer(),
                                                                                                         cellInfo.InterfaceSlot);
                    }
                    else
                    // TODO!! END REMOVE THIS CODE WHEN WE REMOVE ICASTABLE
                    {
                        // Dispatch not resolved through normal dispatch map, using the CastableObject path
                        pTargetCode = InternalCalls.RhpGetCastableObjectDispatchHelper();
                    }
                }

                return(pTargetCode);
            }
            else if (cellInfo.CellType == DispatchCellType.VTableOffset)
            {
                // Dereference VTable
                return(*(IntPtr *)(((byte *)pInstanceType) + cellInfo.VTableOffset));
            }
            else
            {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
                // Attempt to convert dispatch cell to non-metadata form if we haven't acquired a cache for this cell yet
                if (cellInfo.HasCache == 0)
                {
                    cellInfo = InternalTypeLoaderCalls.ConvertMetadataTokenDispatch(InternalCalls.RhGetModuleFromPointer(cell), cellInfo);
                    if (cellInfo.CellType != DispatchCellType.MetadataToken)
                    {
                        return(RhResolveDispatchWorker(pObject, cell, ref cellInfo));
                    }
                }

                // If that failed, go down the metadata resolution path
                return(InternalTypeLoaderCalls.ResolveMetadataTokenDispatch(InternalCalls.RhGetModuleFromPointer(cell), (int)cellInfo.MetadataToken, new IntPtr(pInstanceType)));
#else
                EH.FallbackFailFast(RhFailFastReason.InternalError, null);
                return(IntPtr.Zero);
#endif
            }
        }