Пример #1
0
 public OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, int slot, int handle)
 {
     _resolveType = DispatchResolve;
     _declaringType = declaringTypeOfSlot.ToEETypePtr();
     _methodHandleOrSlotOrCodePointer = new IntPtr(slot);
     _handle = handle;
 }
Пример #2
0
 public unsafe OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, RuntimeMethodHandle gvmSlot, int handle)
 {
     _resolveType = GVMResolve;
     _methodHandleOrSlotOrCodePointer = *(IntPtr*)&gvmSlot;
     _declaringType = declaringTypeOfSlot.ToEETypePtr();
     _handle = handle;
 }
Пример #3
0
 public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, int handle)
 {
     _resolveType = OpenNonVirtualResolve;
     _methodHandleOrSlotOrCodePointer = codePointer;
     _declaringType = declaringType.ToEETypePtr();
     _handle = handle;
 }
Пример #4
0
        private static IntPtr RhResolveDispatch(object pObject, EETypePtr interfaceType, ushort slot)
        {
            DispatchCellInfo cellInfo = new DispatchCellInfo();
            cellInfo.CellType = DispatchCellType.InterfaceAndSlot;
            cellInfo.InterfaceType = interfaceType;
            cellInfo.InterfaceSlot = slot;

            return RhResolveDispatchWorker(pObject, null, ref cellInfo);
        }
Пример #5
0
 public static bool TryGetEEType(this Type type, out EETypePtr eeType)
 {
     RuntimeTypeHandle typeHandle = RuntimeAugments.Callbacks.GetTypeHandleIfAvailable(type);
     if (typeHandle.IsNull)
     {
         eeType = default(EETypePtr);
         return false;
     }
     eeType = typeHandle.ToEETypePtr();
     return true;
 }
Пример #6
0
        private static IntPtr RhResolveDispatchOnType(EETypePtr instanceType, EETypePtr interfaceType, ushort slot)
        {
            // Type of object we're dispatching on.
            EEType* pInstanceType = instanceType.ToPointer();

            // Type of interface
            EEType* pInterfaceType = interfaceType.ToPointer();

            return DispatchResolve.FindInterfaceMethodImplementationTarget(pInstanceType,
                                                                          pInterfaceType,
                                                                          slot);
        }
Пример #7
0
        /// <summary>
        /// Helper for array allocations via `newobj` IL instruction. Dimensions are passed in as block of integers.
        /// The content of the dimensions block may be modified by the helper.
        /// </summary>
        private static unsafe Array NewObjArray(IntPtr pEEType, int nDimensions, int* pDimensions)
        {
            EETypePtr eeType = new EETypePtr(pEEType);
            Debug.Assert(eeType.IsArray);
            Debug.Assert(nDimensions > 0);

            if (eeType.IsSzArray)
            {
                Array ret = (Array)RuntimeImports.RhNewArray(eeType, pDimensions[0]);

                if (nDimensions > 1)
                {
                    // Jagged arrays have constructor for each possible depth
                    EETypePtr elementType = eeType.ArrayElementType;
                    Debug.Assert(elementType.IsSzArray);

                    Array[] arrayOfArrays = (Array[])ret;
                    for (int i = 0; i < arrayOfArrays.Length; i++)
                        arrayOfArrays[i] = NewObjArray(elementType.RawValue, nDimensions - 1, pDimensions + 1);
                }

                return ret;
            }
            else
            {
                // Multidimensional arrays have two ctors, one with and one without lower bounds
                int rank = eeType.ArrayRank;
                Debug.Assert(rank == nDimensions || 2 * rank == nDimensions);

                if (rank < nDimensions)
                {
                    for (int i = 0; i < rank; i++)
                    {
                        if (pDimensions[2 * i] != 0)
                            throw new PlatformNotSupportedException(SR.Arg_NotSupportedNonZeroLowerBound);

                        pDimensions[i] = pDimensions[2 * i + 1];
                    }
                }

                return Array.NewMultiDimArray(eeType, pDimensions, rank);
            }
        }
Пример #8
0
 internal static extern EETypePtr RhGetNullableType(EETypePtr pEEType);
Пример #9
0
 internal static extern uint RhGetValueTypeSize(EETypePtr pEEType);
Пример #10
0
        public static T CreateInstance <T>()
        {
            T t = default(T);

            bool missingDefaultConstructor = false;

            EETypePtr eetype = EETypePtr.EETypePtrOf <T>();

            if (!RuntimeHelpers.IsReference <T>())
            {
                // Early out for valuetypes since we don't support default constructors anyway.
                // This lets codegens that expand IsReference<T> optimize away the rest of this code.
            }
            else if (eetype.ComponentSize != 0)
            {
                // ComponentSize > 0 indicates an array-like type (e.g. string, array, etc).
                // Allocating this using the normal allocator would result in silent heap corruption.
                missingDefaultConstructor = true;
            }
            else if (eetype.IsInterface)
            {
                // Do not attempt to allocate interface types either
                missingDefaultConstructor = true;
            }
            else
            {
                bool oldValueOfMissingDefaultCtorMarkerBool = s_createInstanceMissingDefaultConstructor;

                try
                {
#if PROJECTN
                    t = CreateInstanceIntrinsic <T>();
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
#else
                    t = (T)(RuntimeImports.RhNewObject(eetype));

                    // Run the default constructor. If the default constructor was missing, codegen
                    // will expand DefaultConstructorOf to ClassWithMissingConstructor::.ctor
                    // and we detect that later.
                    IntPtr defaultConstructor = DefaultConstructorOf <T>();
                    RawCalliHelper.Call(defaultConstructor, t);
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
#endif
                }
                catch (Exception e)
                {
                    throw new TargetInvocationException(e);
                }

                if (s_createInstanceMissingDefaultConstructor != oldValueOfMissingDefaultCtorMarkerBool)
                {
                    missingDefaultConstructor = true;

                    // We didn't call the real .ctor (because there wasn't one), but we still allocated
                    // an uninitialized object. If it has a finalizer, it would run - prevent that.
                    GC.SuppressFinalize(t);
                }
            }

            if (missingDefaultConstructor)
            {
                throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, typeof(T)));
            }

            return(t);
        }
Пример #11
0
        //
        // Various reflection scenarios (Array.SetValue(), reflection Invoke, delegate DynamicInvoke and FieldInfo.Set()) perform
        // automatic conveniences such as automatically widening primitive types to fit the destination type.
        //
        // This method attempts to collect as much of that logic as possible in place. (This may not be completely possible
        // as the desktop CLR is not particularly consistent across all these scenarios either.)
        //
        // The transforms supported are:
        //
        //    Value-preserving widenings of primitive integrals and floats.
        //    Enums can be converted to the same or wider underlying primitive.
        //    Primitives can be converted to an enum with the same or wider underlying primitive.
        //
        //    null converted to default(T) (this is important when T is a valuetype.)
        //
        // There is also another transform of T -> Nullable<T>. This method acknowleges that rule but does not actually transform the T.
        // Rather, the transformation happens naturally when the caller unboxes the value to its final destination.
        //
        // This method is targeted by the Delegate ILTransformer.
        //
        //
        public static Object CheckArgument(Object srcObject, RuntimeTypeHandle dstType)
        {
            EETypePtr dstEEType = dstType.EEType;

            return(CheckArgument(srcObject, dstEEType, CheckArgumentSemantics.DynamicInvoke));
        }
Пример #12
0
 internal static unsafe extern IntPtr RhNewInterfaceDispatchCell(EETypePtr pEEType, int slotNumber);
Пример #13
0
 internal static extern int RhGetGCDescSize(EETypePtr eeType);
Пример #14
0
        // Special coersion rules for primitives, enums and pointer.
        private static Exception ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(object srcObject, EETypePtr srcEEType, EETypePtr dstEEType, CheckArgumentSemantics semantics, out object dstObject)
        {
            if (semantics == CheckArgumentSemantics.SetFieldDirect && (srcEEType.IsEnum || dstEEType.IsEnum))
            {
                dstObject = null;
                return(CreateChangeTypeException(srcEEType, dstEEType, semantics));
            }

            if (dstEEType.IsPointer)
            {
                Exception exception = ConvertPointerIfPossible(srcObject, srcEEType, dstEEType, semantics, out IntPtr dstIntPtr);
                if (exception != null)
                {
                    dstObject = null;
                    return(exception);
                }
                dstObject = dstIntPtr;
                return(null);
            }

            if (!(srcEEType.IsPrimitive && dstEEType.IsPrimitive))
            {
                dstObject = null;
                return(CreateChangeTypeException(srcEEType, dstEEType, semantics));
            }

            RuntimeImports.RhCorElementType dstCorElementType = dstEEType.CorElementType;
            if (!srcEEType.CorElementTypeInfo.CanWidenTo(dstCorElementType))
            {
                dstObject = null;
                return(CreateChangeTypeArgumentException(srcEEType, dstEEType));
            }

            switch (dstCorElementType)
            {
            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN:
                dstObject = Convert.ToBoolean(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR:
                dstObject = Convert.ToChar(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1:
                dstObject = Convert.ToSByte(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2:
                dstObject = Convert.ToInt16(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4:
                dstObject = Convert.ToInt32(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8:
                dstObject = Convert.ToInt64(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1:
                dstObject = Convert.ToByte(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2:
                dstObject = Convert.ToUInt16(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4:
                dstObject = Convert.ToUInt32(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8:
                dstObject = Convert.ToUInt64(srcObject);
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R4:
                if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR)
                {
                    dstObject = (float)(char)srcObject;
                }
                else
                {
                    dstObject = Convert.ToSingle(srcObject);
                }
                break;

            case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R8:
                if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR)
                {
                    dstObject = (double)(char)srcObject;
                }
                else
                {
                    dstObject = Convert.ToDouble(srcObject);
                }
                break;

            default:
                Debug.Fail("Unexpected CorElementType: " + dstCorElementType + ": Not a valid widening target.");
                dstObject = null;
                return(CreateChangeTypeException(srcEEType, dstEEType, semantics));
            }

            if (dstEEType.IsEnum)
            {
                Type dstType = ReflectionCoreNonPortable.GetRuntimeTypeForEEType(dstEEType);
                dstObject = Enum.ToObject(dstType, dstObject);
            }

            Debug.Assert(dstObject.EETypePtr == dstEEType);
            return(null);
        }
Пример #15
0
        internal static object?CheckArgument(object?srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle?binderBundle, ref ArgSetupState argSetupState)
        {
            // Methods with ByRefLike types in signatures should be filtered out by the compiler
            Debug.Assert(!dstEEType.IsByRefLike);

            if (srcObject == null)
            {
                // null -> default(T)
                if (dstEEType.IsPointer)
                {
                    return(default(IntPtr));
                }
                else if (dstEEType.IsValueType && !dstEEType.IsNullable)
                {
                    if (semantics == CheckArgumentSemantics.SetFieldDirect)
                    {
                        throw CreateChangeTypeException(typeof(object).TypeHandle.ToEETypePtr(), dstEEType, semantics);
                    }
                    return(Runtime.RuntimeImports.RhNewObject(dstEEType));
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                EETypePtr srcEEType = srcObject.GetEETypePtr();

                if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType))
                {
                    return(srcObject);
                }

                if (dstEEType.IsInterface)
                {
                    if (srcObject is Runtime.InteropServices.IDynamicInterfaceCastable castable &&
                        castable.IsInterfaceImplemented(new RuntimeTypeHandle(dstEEType), throwIfNotImplemented: false))
                    {
                        return(srcObject);
                    }
                }

                object    dstObject;
                Exception exception = ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(srcObject, srcEEType, dstEEType, semantics, out dstObject);
                if (exception == null)
                {
                    return(dstObject);
                }

                if (binderBundle == null)
                {
                    throw exception;
                }

                // Our normal coercion rules could not convert the passed in argument but we were supplied a custom binder. See if it can do it.
                Type exactDstType;
                if (Unsafe.IsNullRef(ref argSetupState))
                {
                    // We were called by someone other than DynamicInvokeParamHelperCore(). Those callers pass the correct dstEEType.
                    exactDstType = Type.GetTypeFromHandle(new RuntimeTypeHandle(dstEEType)) !;
                }
                else
                {
                    // We were called by DynamicInvokeParamHelperCore(). He passes a dstEEType that enums folded to int and possibly other adjustments. A custom binder
                    // is app code however and needs the exact type.
                    exactDstType = GetExactTypeForCustomBinder(argSetupState);
                }

                srcObject = binderBundle.ChangeType(srcObject, exactDstType);

                // For compat with desktop, the result of the binder call gets processed through the default rules again.
                dstObject = CheckArgument(srcObject, dstEEType, semantics, binderBundle: null, ref Unsafe.NullRef <ArgSetupState>());
                return(dstObject);
            }
        }
Пример #16
0
 internal static object?CheckArgument(object?srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle?binderBundle)
 {
     return(CheckArgument(srcObject, dstEEType, semantics, binderBundle, ref Unsafe.NullRef <ArgSetupState>()));
 }
Пример #17
0
        //
        // Various reflection scenarios (Array.SetValue(), reflection Invoke, delegate DynamicInvoke and FieldInfo.Set()) perform
        // automatic conveniences such as automatically widening primitive types to fit the destination type.
        //
        // This method attempts to collect as much of that logic as possible in place. (This may not be completely possible
        // as the desktop CLR is not particularly consistent across all these scenarios either.)
        //
        // The transforms supported are:
        //
        //    Value-preserving widenings of primitive integrals and floats.
        //    Enums can be converted to the same or wider underlying primitive.
        //    Primitives can be converted to an enum with the same or wider underlying primitive.
        //
        //    null converted to default(T) (this is important when T is a valuetype.)
        //
        // There is also another transform of T -> Nullable<T>. This method acknowledges that rule but does not actually transform the T.
        // Rather, the transformation happens naturally when the caller unboxes the value to its final destination.
        //
        // This method is targeted by the Delegate ILTransformer.
        //
        //
        public static object?CheckArgument(object?srcObject, RuntimeTypeHandle dstType, BinderBundle?binderBundle)
        {
            EETypePtr dstEEType = dstType.ToEETypePtr();

            return(CheckArgument(srcObject, dstEEType, CheckArgumentSemantics.DynamicInvoke, binderBundle, ref Unsafe.NullRef <ArgSetupState>()));
        }
Пример #18
0
        private static void DynamicInvokeUnboxIntoActualNullable(object actualBoxedNullable, object boxedFillObject, EETypePtr nullableType)
        {
            // pin the actualBoxedNullable
            // local0 is object pinned pinnedActualBoxedNullable
            // ldarg.0
            // stloc.0

            // ldarg.1 // object to unbox
            // ldarg.0
            // ldflda System.Object::m_eetype
            // sizeof EETypePtr
            // add // byref to data data region within actualBoxedNullable
            // ldarg.2
            // get a byref to the data within the actual boxed nullable, and then call RhUnBox with the boxedFillObject as the boxed object, and nullableType as the unbox type, and unbox into the actualBoxedNullable
            // call static void RuntimeImports.RhUnbox(object obj, void* pData, EETypePtr pUnboxToEEType);
            // ret
        }
Пример #19
0
        internal static Object CheckArgument(Object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics)
        {
            if (srcObject == null)
            {
                // null -> default(T)
                if (dstEEType.IsValueType && !RuntimeImports.RhIsNullable(dstEEType))
                {
                    return(Runtime.RuntimeImports.RhNewObject(dstEEType));
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                EETypePtr srcEEType = srcObject.EETypePtr;

                if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType))
                {
                    return(srcObject);
                }


                if (RuntimeImports.RhIsInterface(dstEEType))
                {
                    ICastable castable = srcObject as ICastable;
                    Exception castError;

                    if (castable != null && castable.IsInstanceOfInterface(new RuntimeTypeHandle(dstEEType), out castError))
                    {
                        return(srcObject);
                    }
                }

                if (!((srcEEType.IsEnum || srcEEType.IsPrimitive) && (dstEEType.IsEnum || dstEEType.IsPrimitive)))
                {
                    throw CreateChangeTypeException(srcEEType, dstEEType, semantics);
                }

                RuntimeImports.RhCorElementType dstCorElementType = dstEEType.CorElementType;
                if (!srcEEType.CorElementTypeInfo.CanWidenTo(dstCorElementType))
                {
                    throw CreateChangeTypeArgumentException(srcEEType, dstEEType);
                }

                Object dstObject;
                switch (dstCorElementType)
                {
                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN:
                    dstObject = Convert.ToBoolean(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR:
                    dstObject = Convert.ToChar(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1:
                    dstObject = Convert.ToSByte(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2:
                    dstObject = Convert.ToInt16(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4:
                    dstObject = Convert.ToInt32(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8:
                    dstObject = Convert.ToInt64(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1:
                    dstObject = Convert.ToByte(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2:
                    dstObject = Convert.ToUInt16(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4:
                    dstObject = Convert.ToUInt32(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8:
                    dstObject = Convert.ToUInt64(srcObject);
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R4:
                    if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR)
                    {
                        dstObject = (float)(char)srcObject;
                    }
                    else
                    {
                        dstObject = Convert.ToSingle(srcObject);
                    }
                    break;

                case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R8:
                    if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR)
                    {
                        dstObject = (double)(char)srcObject;
                    }
                    else
                    {
                        dstObject = Convert.ToDouble(srcObject);
                    }
                    break;

                default:
                    Debug.Assert(false, "Unexpected CorElementType: " + dstCorElementType + ": Not a valid widening target.");
                    throw CreateChangeTypeException(srcEEType, dstEEType, semantics);
                }

                if (dstEEType.IsEnum)
                {
                    Type dstType = ReflectionCoreNonPortable.GetRuntimeTypeForEEType(dstEEType);
                    dstObject = Enum.ToObject(dstType, dstObject);
                }

                Debug.Assert(dstObject.EETypePtr == dstEEType);
                return(dstObject);
            }
        }
Пример #20
0
 internal static extern ushort RhGetComponentSize(EETypePtr pEEType);
Пример #21
0
 internal static extern uint RhGetNumInterfaces(EETypePtr pEEType);
Пример #22
0
        // Special coersion rules for primitives, enums and pointer.
        private static Exception ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(object srcObject, EETypePtr srcEEType, EETypePtr dstEEType, CheckArgumentSemantics semantics, out object dstObject)
        {
            if (semantics == CheckArgumentSemantics.SetFieldDirect && (srcEEType.IsEnum || dstEEType.IsEnum))
            {
                dstObject = null;
                return(CreateChangeTypeException(srcEEType, dstEEType, semantics));
            }

            if (dstEEType.IsPointer)
            {
                Exception exception = ConvertPointerIfPossible(srcObject, srcEEType, dstEEType, semantics, out IntPtr dstIntPtr);
                if (exception != null)
                {
                    dstObject = null;
                    return(exception);
                }
                dstObject = dstIntPtr;
                return(null);
            }

            if (!(srcEEType.IsPrimitive && dstEEType.IsPrimitive))
            {
                dstObject = null;
                return(CreateChangeTypeException(srcEEType, dstEEType, semantics));
            }

            CorElementType dstCorElementType = dstEEType.CorElementType;

            if (!srcEEType.CorElementTypeInfo.CanWidenTo(dstCorElementType))
            {
                dstObject = null;
                return(CreateChangeTypeArgumentException(srcEEType, dstEEType));
            }

            switch (dstCorElementType)
            {
            case CorElementType.ELEMENT_TYPE_BOOLEAN:
                bool boolValue = Convert.ToBoolean(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, boolValue ? 1 : 0) : boolValue;
                break;

            case CorElementType.ELEMENT_TYPE_CHAR:
                char charValue = Convert.ToChar(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, charValue) : charValue;
                break;

            case CorElementType.ELEMENT_TYPE_I1:
                sbyte sbyteValue = Convert.ToSByte(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, sbyteValue) : sbyteValue;
                break;

            case CorElementType.ELEMENT_TYPE_I2:
                short shortValue = Convert.ToInt16(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, shortValue) : shortValue;
                break;

            case CorElementType.ELEMENT_TYPE_I4:
                int intValue = Convert.ToInt32(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, intValue) : intValue;
                break;

            case CorElementType.ELEMENT_TYPE_I8:
                long longValue = Convert.ToInt64(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, longValue) : longValue;
                break;

            case CorElementType.ELEMENT_TYPE_U1:
                byte byteValue = Convert.ToByte(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, byteValue) : byteValue;
                break;

            case CorElementType.ELEMENT_TYPE_U2:
                ushort ushortValue = Convert.ToUInt16(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, ushortValue) : ushortValue;
                break;

            case CorElementType.ELEMENT_TYPE_U4:
                uint uintValue = Convert.ToUInt32(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, uintValue) : uintValue;
                break;

            case CorElementType.ELEMENT_TYPE_U8:
                ulong ulongValue = Convert.ToUInt64(srcObject);
                dstObject = dstEEType.IsEnum ? Enum.ToObject(dstEEType, (long)ulongValue) : ulongValue;
                break;

            case CorElementType.ELEMENT_TYPE_R4:
                if (srcEEType.CorElementType == CorElementType.ELEMENT_TYPE_CHAR)
                {
                    dstObject = (float)(char)srcObject;
                }
                else
                {
                    dstObject = Convert.ToSingle(srcObject);
                }
                break;

            case CorElementType.ELEMENT_TYPE_R8:
                if (srcEEType.CorElementType == CorElementType.ELEMENT_TYPE_CHAR)
                {
                    dstObject = (double)(char)srcObject;
                }
                else
                {
                    dstObject = Convert.ToDouble(srcObject);
                }
                break;

            default:
                Debug.Fail("Unexpected CorElementType: " + dstCorElementType + ": Not a valid widening target.");
                dstObject = null;
                return(CreateChangeTypeException(srcEEType, dstEEType, semantics));
            }

            Debug.Assert(dstObject.EETypePtr == dstEEType);
            return(null);
        }
Пример #23
0
 internal static unsafe extern void RhSetInterface(EETypePtr pEEType, int index, EETypePtr pEETypeInterface);
Пример #24
0
        private static Exception ConvertPointerIfPossible(object srcObject, EETypePtr srcEEType, EETypePtr dstEEType, CheckArgumentSemantics semantics, out IntPtr dstIntPtr)
        {
            if (srcObject is IntPtr srcIntPtr)
            {
                dstIntPtr = srcIntPtr;
                return(null);
            }

            if (srcObject is Pointer srcPointer)
            {
                if (dstEEType == typeof(void *).TypeHandle.ToEETypePtr() || RuntimeImports.AreTypesAssignable(pSourceType: srcPointer.GetPointerType().TypeHandle.ToEETypePtr(), pTargetType: dstEEType))
                {
                    dstIntPtr = srcPointer.GetPointerValue();
                    return(null);
                }
            }

            dstIntPtr = IntPtr.Zero;
            return(CreateChangeTypeException(srcEEType, dstEEType, semantics));
        }
Пример #25
0
 internal static unsafe extern IntPtr RhGetGcStaticFieldData(EETypePtr pEEType);
Пример #26
0
 private static ArgumentException CreateChangeTypeArgumentException(EETypePtr srcEEType, EETypePtr dstEEType)
 {
     return(new ArgumentException(SR.Format(SR.Arg_ObjObjEx, Type.GetTypeFromHandle(new RuntimeTypeHandle(srcEEType)), Type.GetTypeFromHandle(new RuntimeTypeHandle(dstEEType)))));
 }
Пример #27
0
 internal RuntimeTypeHandle(EETypePtr pEEType)
 {
     // CORERT-TODO: RuntimeTypeHandle
     throw new NotImplementedException();
 }
Пример #28
0
 private static InvalidCastException CreateChangeTypeInvalidCastException(EETypePtr srcEEType, EETypePtr dstEEType)
 {
     return(new InvalidCastException(SR.InvalidCast_StoreArrayElement));
 }
Пример #29
0
        internal static object CallDynamicInvokeMethod(
            object thisPtr,
            IntPtr methodToCall,
            object thisPtrDynamicInvokeMethod,
            IntPtr dynamicInvokeHelperMethod,
            IntPtr dynamicInvokeHelperGenericDictionary,
            object targetMethodOrDelegate,
            object[] parameters,
            BinderBundle binderBundle,
            bool wrapInTargetInvocationException,
            bool invokeMethodHelperIsThisCall = true,
            bool methodToCallIsThisCall       = true)
        {
            // This assert is needed because we've double-purposed "targetMethodOrDelegate" (which is actually a MethodBase anytime a custom binder is used)
            // as a way of obtaining the true parameter type which we need to pass to Binder.ChangeType(). (The type normally passed to DynamicInvokeParamHelperCore
            // isn't always the exact type (byref stripped off, enums converted to int, etc.)
            Debug.Assert(!(binderBundle != null && !(targetMethodOrDelegate is MethodBase)), "The only callers that can pass a custom binder are those servicing MethodBase.Invoke() apis.");

            bool          parametersNeedCopyBack = false;
            ArgSetupState argSetupState          = default(ArgSetupState);

            // Capture state of thread static invoke helper statics
            object[]     parametersOld = s_parameters;
            object[]     nullableCopyBackObjectsOld = s_nullableCopyBackObjects;
            int          curIndexOld = s_curIndex;
            object       targetMethodOrDelegateOld = s_targetMethodOrDelegate;
            BinderBundle binderBundleOld           = s_binderBundle;

            s_binderBundle = binderBundle;
            object[] customBinderProvidedParametersOld = s_customBinderProvidedParameters;
            s_customBinderProvidedParameters = null;

            try
            {
                // If the passed in array is not an actual object[] instance, we need to copy it over to an actual object[]
                // instance so that the rest of the code can safely create managed object references to individual elements.
                if (parameters != null && EETypePtr.EETypePtrOf <object[]>() != parameters.EETypePtr)
                {
                    s_parameters = new object[parameters.Length];
                    Array.Copy(parameters, s_parameters, parameters.Length);
                    parametersNeedCopyBack = true;
                }
                else
                {
                    s_parameters = parameters;
                }

                s_nullableCopyBackObjects = null;
                s_curIndex = 0;
                s_targetMethodOrDelegate = targetMethodOrDelegate;

                object result;
                try
                {
                    if (invokeMethodHelperIsThisCall)
                    {
                        Debug.Assert(methodToCallIsThisCall == true);
                        result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtrDynamicInvokeMethod, thisPtr, methodToCall, ref argSetupState);
                        System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                    }
                    else
                    {
                        if (dynamicInvokeHelperGenericDictionary != IntPtr.Zero)
                        {
                            result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, dynamicInvokeHelperGenericDictionary, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall);
                            DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                        }
                        else
                        {
                            result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall);
                            DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                        }
                    }
                }
                catch (Exception e) when(wrapInTargetInvocationException && argSetupState.fComplete)
                {
                    throw new TargetInvocationException(e);
                }
                finally
                {
                    if (parametersNeedCopyBack)
                    {
                        Array.Copy(s_parameters, parameters, parameters.Length);
                    }

                    if (argSetupState.fComplete)
                    {
                        // Nullable objects can't take advantage of the ability to update the boxed value on the heap directly, so perform
                        // an update of the parameters array now.
                        if (argSetupState.nullableCopyBackObjects != null)
                        {
                            for (int i = 0; i < argSetupState.nullableCopyBackObjects.Length; i++)
                            {
                                if (argSetupState.nullableCopyBackObjects[i] != null)
                                {
                                    parameters[i] = DynamicInvokeBoxIntoNonNullable(argSetupState.nullableCopyBackObjects[i]);
                                }
                            }
                        }
                    }
                }

                if (result == NullByRefValueSentinel)
                {
                    throw new NullReferenceException(SR.NullReference_InvokeNullRefReturned);
                }

                return(result);
            }
            finally
            {
                // Restore state of thread static helper statics
                s_parameters = parametersOld;
                s_nullableCopyBackObjects = nullableCopyBackObjectsOld;
                s_curIndex = curIndexOld;
                s_targetMethodOrDelegate         = targetMethodOrDelegateOld;
                s_binderBundle                   = binderBundleOld;
                s_customBinderProvidedParameters = customBinderProvidedParametersOld;
            }
        }
Пример #30
0
        //
        // Various reflection scenarios (Array.SetValue(), reflection Invoke, delegate DynamicInvoke and FieldInfo.Set()) perform
        // automatic conveniences such as automatically widening primitive types to fit the destination type.
        //
        // This method attempts to collect as much of that logic as possible in place. (This may not be completely possible
        // as the desktop CLR is not particularly consistent across all these scenarios either.)
        //
        // The transforms supported are:
        //
        //    Value-preserving widenings of primitive integrals and floats.
        //    Enums can be converted to the same or wider underlying primitive.
        //    Primitives can be converted to an enum with the same or wider underlying primitive.
        //
        //    null converted to default(T) (this is important when T is a valuetype.)
        //
        // There is also another transform of T -> Nullable<T>. This method acknowledges that rule but does not actually transform the T.
        // Rather, the transformation happens naturally when the caller unboxes the value to its final destination.
        //
        // This method is targeted by the Delegate ILTransformer.
        //
        //
        public static object CheckArgument(object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle)
        {
            EETypePtr dstEEType = dstType.ToEETypePtr();

            return(CheckArgument(srcObject, dstEEType, CheckArgumentSemantics.DynamicInvoke, binderBundle, getExactTypeForCustomBinder: null));
        }
Пример #31
0
 internal static extern RhCorElementType RhGetCorElementType(EETypePtr pEEType);
Пример #32
0
        internal static object CheckArgument(object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle binderBundle, Func <Type> getExactTypeForCustomBinder = null)
        {
            if (srcObject == null)
            {
                // null -> default(T)
                if (dstEEType.IsPointer)
                {
                    return(default(IntPtr));
                }
                else if (dstEEType.IsValueType && !dstEEType.IsNullable)
                {
                    if (semantics == CheckArgumentSemantics.SetFieldDirect)
                    {
                        throw CreateChangeTypeException(CommonRuntimeTypes.Object.TypeHandle.ToEETypePtr(), dstEEType, semantics);
                    }
                    return(Runtime.RuntimeImports.RhNewObject(dstEEType));
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                EETypePtr srcEEType = srcObject.EETypePtr;

                if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType))
                {
                    return(srcObject);
                }


                if (dstEEType.IsInterface)
                {
                    ICastable castable = srcObject as ICastable;
                    Exception castError;

                    if (castable != null && castable.IsInstanceOfInterface(new RuntimeTypeHandle(dstEEType), out castError))
                    {
                        return(srcObject);
                    }
                }

                object    dstObject;
                Exception exception = ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(srcObject, srcEEType, dstEEType, semantics, out dstObject);
                if (exception == null)
                {
                    return(dstObject);
                }

                if (binderBundle == null)
                {
                    throw exception;
                }

                // Our normal coercion rules could not convert the passed in argument but we were supplied a custom binder. See if it can do it.
                Type exactDstType;
                if (getExactTypeForCustomBinder == null)
                {
                    // We were called by someone other than DynamicInvokeParamHelperCore(). Those callers pass the correct dstEEType.
                    exactDstType = Type.GetTypeFromHandle(new RuntimeTypeHandle(dstEEType));
                }
                else
                {
                    // We were called by DynamicInvokeParamHelperCore(). He passes a dstEEType that enums folded to int and possibly other adjustments. A custom binder
                    // is app code however and needs the exact type.
                    exactDstType = getExactTypeForCustomBinder();
                }

                srcObject = binderBundle.ChangeType(srcObject, exactDstType);

                // For compat with desktop, the result of the binder call gets processed through the default rules again.
                dstObject = CheckArgument(srcObject, dstEEType, semantics, binderBundle: null, getExactTypeForCustomBinder: null);
                return(dstObject);
            }
        }
Пример #33
0
 internal static extern bool RhIsNullable(EETypePtr pEEType);
Пример #34
0
 private static void DynamicInvokeUnboxIntoActualNullable(object actualBoxedNullable, object boxedFillObject, EETypePtr nullableType)
 {
     // get a byref to the data within the actual boxed nullable, and then call RhUnBox with the boxedFillObject as the boxed object, and nullableType as the unbox type, and unbox into the actualBoxedNullable
     RuntimeImports.RhUnbox(boxedFillObject, ref actualBoxedNullable.GetRawData(), nullableType);
 }
Пример #35
0
 internal static extern EETypePtr RhGetRelatedParameterType(EETypePtr pEEType);
Пример #36
0
 internal RuntimeTypeHandle(EETypePtr pEEType)
 {
     _pEEType = pEEType;
 }
Пример #37
0
 internal static extern EETypePtr RhGetNonArrayBaseType(EETypePtr pEEType);
Пример #38
0
        //
        // Caution: There can be and are multiple EEType for the "same" type (e.g. int[]). That means
        // you can't use the raw IntPtr value for comparisons.
        //

        internal RuntimeTypeHandle(EETypePtr pEEType)
        {
            _value = pEEType.RawValue;
        }
Пример #39
0
 internal static extern EETypePtr RhGetInterface(EETypePtr pEEType, uint index);
Пример #40
0
 internal bool Equals(EETypePtr p)
 {
     return(_value == p._value);
 }
Пример #41
0
 internal static unsafe extern bool RhCreateGenericInstanceDescForType2(EETypePtr pEEType, int arity, int nonGcStaticDataSize,
     int nonGCStaticDataOffset, int gcStaticDataSize, int threadStaticsOffset, void* pGcStaticsDesc, void* pThreadStaticsDesc, int* pGenericVarianceFlags);
Пример #42
0
        public static unsafe void BlockCopy(Array src, int srcOffset,
                                            Array dst, int dstOffset,
                                            int count)
        {
            nuint uSrcLen;
            nuint uDstLen;

            if (src == null)
            {
                throw new ArgumentNullException(nameof(src));
            }
            if (dst == null)
            {
                throw new ArgumentNullException(nameof(dst));
            }

            // Use optimized path for byte arrays since this is the main scenario for Buffer::BlockCopy
            // We only need an unreliable comparison since the slow path can handle the byte[] case too.
            if (src.EETypePtr.FastEqualsUnreliable(EETypePtr.EETypePtrOf <byte[]>()))
            {
                uSrcLen = (nuint)src.Length;
            }
            else
            {
                RuntimeImports.RhCorElementTypeInfo srcCorElementTypeInfo = src.ElementEEType.CorElementTypeInfo;
                uSrcLen = ((nuint)src.Length) << srcCorElementTypeInfo.Log2OfSize;
                if (!srcCorElementTypeInfo.IsPrimitive)
                {
                    throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(src));
                }
            }

            if (src != dst)
            {
                // Use optimized path for byte arrays since this is the main scenario for Buffer::BlockCopy
                // We only need an unreliable comparison since the slow path can handle the byte[] case too.
                if (dst.EETypePtr.FastEqualsUnreliable(EETypePtr.EETypePtrOf <byte[]>()))
                {
                    uDstLen = (nuint)dst.Length;
                }
                else
                {
                    RuntimeImports.RhCorElementTypeInfo dstCorElementTypeInfo = dst.ElementEEType.CorElementTypeInfo;
                    if (!dstCorElementTypeInfo.IsPrimitive)
                    {
                        throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(dst));
                    }
                    uDstLen = ((nuint)dst.Length) << dstCorElementTypeInfo.Log2OfSize;
                }
            }
            else
            {
                uDstLen = uSrcLen;
            }

            if (srcOffset < 0)
            {
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(srcOffset));
            }
            if (dstOffset < 0)
            {
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(dstOffset));
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(count));
            }

            nuint uCount     = (nuint)count;
            nuint uSrcOffset = (nuint)srcOffset;
            nuint uDstOffset = (nuint)dstOffset;

            if (uSrcLen < uSrcOffset + uCount)
            {
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            }
            if (uDstLen < uDstOffset + uCount)
            {
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            }

            if (uCount != 0)
            {
                fixed(byte *pSrc = &src.GetRawArrayData(), pDst = &dst.GetRawArrayData())
                {
                    Buffer.Memmove(pDst + uDstOffset, pSrc + uSrcOffset, uCount);
                }
            }
        }
Пример #43
0
 internal static unsafe extern bool RhSetGenericInstantiation(EETypePtr pEEType, EETypePtr pEETypeDef, int arity, EETypePtr* pInstantiation);
Пример #44
0
 internal static unsafe extern bool RhHasCctor(EETypePtr pEEType);
Пример #45
0
 internal static extern IntPtr RhResolveDispatch(object pObject, EETypePtr pInterfaceType, ushort slot);
Пример #46
0
 internal static unsafe extern IntPtr RhGetRuntimeHelperForType(EETypePtr pEEType, RuntimeHelperKind kind);
Пример #47
0
 internal static unsafe extern bool RhIsDynamicType(EETypePtr pEEType);
Пример #48
0
        internal static object CallDynamicInvokeMethod(
            object thisPtr,
            IntPtr methodToCall,
            object thisPtrDynamicInvokeMethod,
            IntPtr dynamicInvokeHelperMethod,
            IntPtr dynamicInvokeHelperGenericDictionary,
            object defaultParametersContext,
            object[] parameters,
            bool invokeMethodHelperIsThisCall = true,
            bool methodToCallIsThisCall       = true)
        {
            bool          fDontWrapInTargetInvocationException = false;
            bool          parametersNeedCopyBack = false;
            ArgSetupState argSetupState          = default(ArgSetupState);

            // Capture state of thread static invoke helper statics
            object[] parametersOld = s_parameters;
            object[] nullableCopyBackObjectsOld = s_nullableCopyBackObjects;
            int      curIndexOld = s_curIndex;
            object   defaultParametersContextOld = s_defaultParametersContext;

            try
            {
                // If the passed in array is not an actual object[] instance, we need to copy it over to an actual object[]
                // instance so that the rest of the code can safely create managed object references to individual elements.
                if (parameters != null && EETypePtr.EETypePtrOf <object[]>() != parameters.EETypePtr)
                {
                    s_parameters = new object[parameters.Length];
                    Array.Copy(parameters, s_parameters, parameters.Length);
                    parametersNeedCopyBack = true;
                }
                else
                {
                    s_parameters = parameters;
                }

                s_nullableCopyBackObjects = null;
                s_curIndex = 0;
                s_defaultParametersContext = defaultParametersContext;

                try
                {
                    object result = null;
                    if (invokeMethodHelperIsThisCall)
                    {
                        Debug.Assert(methodToCallIsThisCall == true);
                        result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtrDynamicInvokeMethod, thisPtr, methodToCall, ref argSetupState);
                        System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                    }
                    else
                    {
                        if (dynamicInvokeHelperGenericDictionary != IntPtr.Zero)
                        {
                            result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, dynamicInvokeHelperGenericDictionary, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall);
                            DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                        }
                        else
                        {
                            result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall);
                            DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                        }
                    }

                    return(result);
                }
                finally
                {
                    if (parametersNeedCopyBack)
                    {
                        Array.Copy(s_parameters, parameters, parameters.Length);
                    }

                    if (!argSetupState.fComplete)
                    {
                        fDontWrapInTargetInvocationException = true;
                    }
                    else
                    {
                        // Nullable objects can't take advantage of the ability to update the boxed value on the heap directly, so perform
                        // an update of the parameters array now.
                        if (argSetupState.nullableCopyBackObjects != null)
                        {
                            for (int i = 0; i < argSetupState.nullableCopyBackObjects.Length; i++)
                            {
                                if (argSetupState.nullableCopyBackObjects[i] != null)
                                {
                                    parameters[i] = DynamicInvokeBoxIntoNonNullable(argSetupState.nullableCopyBackObjects[i]);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                if (fDontWrapInTargetInvocationException)
                {
                    throw;
                }
                else
                {
                    throw new System.Reflection.TargetInvocationException(e);
                }
            }
            finally
            {
                // Restore state of thread static helper statics
                s_parameters = parametersOld;
                s_nullableCopyBackObjects = nullableCopyBackObjectsOld;
                s_curIndex = curIndexOld;
                s_defaultParametersContext = defaultParametersContextOld;
            }
        }
Пример #49
0
 internal static extern IntPtr RhResolveDispatchOnType(EETypePtr instanceType, EETypePtr interfaceType, ushort slot);
Пример #50
0
 internal static extern void RhUnregisterRefCountedHandleCallback(IntPtr pCalloutMethod, EETypePtr pTypeFilter);
Пример #51
0
 internal static unsafe extern IntPtr RhGetDispatchMapForType(EETypePtr pEEType);
Пример #52
0
        internal static ArgumentException CreateChangeTypeArgumentException(EETypePtr srcEEType, EETypePtr dstEEType, bool destinationIsByRef = false)
        {
            object?destinationTypeName = Type.GetTypeFromHandle(new RuntimeTypeHandle(dstEEType));

            if (destinationIsByRef)
            {
                destinationTypeName += "&";
            }
            return(new ArgumentException(SR.Format(SR.Arg_ObjObjEx, Type.GetTypeFromHandle(new RuntimeTypeHandle(srcEEType)), destinationTypeName)));
        }
Пример #53
0
 internal static unsafe extern byte* RhGetThreadStaticFieldAddress(EETypePtr pEEType, IntPtr fieldCookie);
Пример #54
0
        //
        // Caution: There can be and are multiple MethodTable for the "same" type (e.g. int[]). That means
        // you can't use the raw IntPtr value for comparisons.
        //

        internal RuntimeTypeHandle(EETypePtr pEEType)
            : this(pEEType.RawValue)
        {
        }