Exemple #1
0
        static public unsafe object IsInstanceOfInterface(object obj, void *pvTargetType)
        {
            if (obj == null)
            {
                return(null);
            }

            EEType *pTargetType = (EEType *)pvTargetType;
            EEType *pObjType    = obj.EEType;

            if (ImplementsInterface(pObjType, pTargetType))
            {
                return(obj);
            }

            // If object type implements ICastable then there's one more way to check whether it implements
            // the interface.
            if (pObjType->IsICastable)
            {
                // 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 = pObjType->ICastableIsInstanceOfInterfaceMethod;
                Exception castError = null;
                if (CalliIntrinsics.Call <bool>(pfnIsInstanceOfInterface, obj, pTargetType, out castError))
                {
                    return(obj);
                }
            }

            return(null);
        }
Exemple #2
0
        // Given an ExceptionID and an address pointing somewhere into a managed module, get
        // an exception object of a type that the module containing the given address will understand.
        // This finds the classlib-defined GetRuntimeException function and asks it for the exception object.
        internal static Exception GetClasslibException(ExceptionIDs id, IntPtr address)
        {
            // Find the classlib function that will give us the exception object we want to throw. This
            // is a RuntimeExport function from the classlib module, and is therefore managed-callable.
            IntPtr pGetRuntimeExceptionFunction =
                (IntPtr)InternalCalls.RhpGetClasslibFunction(address, ClassLibFunctionId.GetRuntimeException);

            // Return the exception object we get from the classlib.
            Exception e = null;

            try
            {
                e = CalliIntrinsics.Call <Exception>(pGetRuntimeExceptionFunction, id);
            }
            catch
            {
                // disallow all exceptions leaking out of callbacks
            }

            // If the helper fails to yield an object, then we fail-fast.
            if (e == null)
            {
                FailFastViaClasslib(
                    RhFailFastReason.ClassLibDidNotTranslateExceptionID,
                    null,
                    address);
            }

            return(e);
        }
        private static IntPtr RhResolveDispatchWorker(object pObject, EEType *pInterfaceType, ushort slot)
        {
            // Type of object we're dispatching on.
            EEType *pInstanceType = pObject.EEType;

            // 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,
                                                                                         pInterfaceType,
                                                                                         slot);

            if (pTargetCode == IntPtr.Zero && pInstanceType->IsICastable)
            {
                // Dispatch not resolved through normal dispatch map, try using the ICastable
                IntPtr pfnGetImplTypeMethod = pInstanceType->ICastableGetImplTypeMethod;
                pResolvingInstanceType = (EEType *)CalliIntrinsics.Call <IntPtr>(pfnGetImplTypeMethod, pObject, new IntPtr(pInterfaceType));

                pTargetCode = DispatchResolve.FindInterfaceMethodImplementationTarget(pResolvingInstanceType,
                                                                                      pInterfaceType,
                                                                                      slot);
            }

            return(pTargetCode);
        }
Exemple #4
0
#pragma warning restore

        public static IntPtr FindInterfaceMethodImplementationTarget(EEType *pTgtType,
                                                                     EEType *pItfType,
                                                                     ushort itfSlotNumber)
        {
            DynamicModule *dynamicModule = pTgtType->DynamicModule;

            // Use the dynamic module resolver if it's present
            if ((dynamicModule != null) && (dynamicModule->DynamicTypeSlotDispatchResolve != IntPtr.Zero))
            {
                return(CalliIntrinsics.Call <IntPtr>(dynamicModule->DynamicTypeSlotDispatchResolve,
                                                     (IntPtr)pTgtType, (IntPtr)pItfType, itfSlotNumber));
            }

            // Start at the current type and work up the inheritance chain
            EEType *pCur = pTgtType;
            UInt32  iCurInheritanceChainDelta = 0;

            if (pItfType->IsCloned)
            {
                pItfType = pItfType->CanonicalEEType;
            }

            while (pCur != null)
            {
                UInt16 implSlotNumber;
                if (FindImplSlotForCurrentType(
                        pCur, pItfType, itfSlotNumber, &implSlotNumber))
                {
                    IntPtr targetMethod;
                    if (implSlotNumber < pCur->NumVtableSlots)
                    {
                        // true virtual - need to get the slot from the target type in case it got overridden
                        targetMethod = pTgtType->GetVTableStartAddress()[implSlotNumber];
                    }
                    else
                    {
                        // sealed virtual - need to get the slot form the implementing type, because
                        // it's not present on the target type
                        targetMethod = pCur->GetSealedVirtualSlot((ushort)(implSlotNumber - pCur->NumVtableSlots));
                    }
                    return(targetMethod);
                }
                if (pCur->IsArray)
                {
                    pCur = pCur->GetArrayEEType();
                }
                else
                {
                    pCur = pCur->NonArrayBaseType;
                }
                iCurInheritanceChainDelta++;
            }
            return(IntPtr.Zero);
        }
        internal static unsafe IntPtr GetCastableObjectDispatchCellThunk(EEType *pInstanceType, IntPtr pDispatchCell)
        {
            IntPtr pTargetCode = CacheLookup(s_ThunkBasedDispatchCellTargets, pDispatchCell);

            if (pTargetCode != default(IntPtr))
            {
                return(pTargetCode);
            }

            InternalCalls.RhpAcquireCastCacheLock();
            {
                // Look in the cache again after taking the lock

                pTargetCode = CacheLookup(s_ThunkBasedDispatchCellTargets, pDispatchCell);
                if (pTargetCode != default(IntPtr))
                {
                    return(pTargetCode);
                }


                // Allocate a new thunk. Failure to allocate one will result in a fail-fast. We don't return nulls from this API.

                // TODO: The allocation of thunks here looks like a layering duck tape. The allocation of the raw
                // thunks should be a core runtime service (ie it should live in MRT).
                // Delete the callback logic once this moves to MRT.

                IntPtr pAllocateThunkFunction = (IntPtr)InternalCalls.RhpGetClasslibFunction(
                    pInstanceType->GetAssociatedModuleAddress(),
                    EH.ClassLibFunctionId.AllocateThunkWithData);

                pTargetCode = CalliIntrinsics.Call <IntPtr>(
                    pAllocateThunkFunction,
                    InternalCalls.RhpGetCastableObjectDispatch_CommonStub(),
                    pDispatchCell,
                    InternalCalls.RhpGetCastableObjectDispatchHelper_TailCalled());

                if (pTargetCode == IntPtr.Zero)
                {
                    EH.FallbackFailFast(RhFailFastReason.InternalError, null);
                }

                AddToThunkCache(pDispatchCell, pTargetCode);
            }
            InternalCalls.RhpReleaseCastCacheLock();

            return(pTargetCode);
        }
Exemple #6
0
        static public /*internal*/ unsafe object CheckCastInterface(Object obj, void *pvTargetEEType)
        {
            // a null value can be cast to anything
            if (obj == null)
            {
                return(null);
            }

            EEType *pTargetType = (EEType *)pvTargetEEType;
            EEType *pObjType    = obj.EEType;

            if (ImplementsInterface(pObjType, pTargetType))
            {
                return(obj);
            }

            Exception castError = null;

            // If object type implements ICastable then there's one more way to check whether it implements
            // the interface.
            if (pObjType->IsICastable)
            {
                // Call the ICastable.IsInstanceOfInterface method directly rather than via an interface
                // dispatch since we know the method address statically.
                IntPtr pfnIsInstanceOfInterface = pObjType->ICastableIsInstanceOfInterfaceMethod;
                if (CalliIntrinsics.Call <bool>(pfnIsInstanceOfInterface, obj, pTargetType, out castError))
                {
                    return(obj);
                }
            }

            // Throw the invalid cast exception defined by the classlib, using the input EEType* to find the
            // correct classlib unless ICastable.IsInstanceOfInterface returned a more specific exception for
            // us to use.

            IntPtr addr = ((EEType *)pvTargetEEType)->GetAssociatedModuleAddress();

            if (castError == null)
            {
                castError = EH.GetClasslibException(ExceptionIDs.InvalidCast, addr);
            }

            BinderIntrinsics.TailCall_RhpThrowEx(castError);
            throw castError;
        }
        // Given an ExceptionID and an address pointing somewhere into a managed module, get
        // an exception object of a type that the module contianing the given address will understand.
        // This finds the classlib-defined GetRuntimeException function and asks it for the exception object.
        internal static Exception GetClasslibException(ExceptionIDs id, IntPtr address)
        {
            unsafe
            {
                // Find the classlib function that will give us the exception object we want to throw. This
                // is a RuntimeExport function from the classlib module, and is therefore managed-callable.
                void *pGetRuntimeExceptionFunction =
                    InternalCalls.RhpGetClasslibFunction(address, ClassLibFunctionId.GetRuntimeException);

                // Return the exception object we get from the classlib.
                Exception e = null;
                try
                {
                    e = CalliIntrinsics.Call <Exception>((IntPtr)pGetRuntimeExceptionFunction, id);
                }
                catch
                {
                    // Unfortunately, this catch turns into "catch (System.Object)", which will not catch
                    // exceptions thrown from the class library because their objects do not derive from our
                    // System.Object.
                    //
                    // @TODO: Use a filtered catch whose filter always returns 'true'.
                }

                // If the helper fails to yield an object, then we fail-fast.
                if (e == null)
                {
                    FailFastViaClasslib(
                        RhFailFastReason.ClassLibDidNotTranslateExceptionID,
                        null,
                        address);
                }

                return(e);
            }
        }
        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
            }
        }