Ejemplo n.º 1
0
 public override IntPtr ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(IntPtr unboxingFunctionPointer, RuntimeTypeHandle declaringType)
 {
     return TypeLoaderEnvironment.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(unboxingFunctionPointer, declaringType);
 }
Ejemplo n.º 2
0
            private static unsafe IntPtr ResolveCallOnValueType(IntPtr unused, IntPtr callDescIntPtr)
#endif
            {
                NonGenericConstrainedCallDesc *callDesc = (NonGenericConstrainedCallDesc *)callDescIntPtr;
                IntPtr exactTarget        = IntPtr.Zero;
                IntPtr targetOnTypeVtable = RuntimeAugments.ResolveDispatchOnType(callDesc->_constraintType, callDesc->_constrainedMethodType, callDesc->_constrainedMethodSlot);
                bool   decodeUnboxing     = true;

                if (!RuntimeAugments.IsInterface(callDesc->_constrainedMethodType))
                {
                    // Non-interface constrained call on a valuetype to a method that isn't GetHashCode/Equals/ToString?!?!
                    if (callDesc->_constrainedMethodSlot > s_MaxObjectVTableSlot)
                    {
                        throw new NotSupportedException();
                    }

                    RuntimeTypeHandle baseTypeHandle;
                    bool gotBaseType = RuntimeAugments.TryGetBaseType(callDesc->_constraintType, out baseTypeHandle);
                    Debug.Assert(gotBaseType);
                    if (targetOnTypeVtable == RuntimeAugments.ResolveDispatchOnType(baseTypeHandle, callDesc->_constrainedMethodType, callDesc->_constrainedMethodSlot))
                    {
                        // In this case, the valuetype does not override the base types implementation of ToString(), GetHashCode(), or Equals(object)
                        decodeUnboxing = false;
                    }
                }

                if (decodeUnboxing)
                {
                    exactTarget = TypeLoaderEnvironment.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(targetOnTypeVtable, callDesc->_constraintType);
                }
                else
                {
                    // Create a fat function pointer, where the instantiation argument is ConstraintType, and the target is BoxAndToString, BoxAndGetHashCode, or BoxAndEquals
                    IntPtr realTarget;

                    switch (callDesc->_constrainedMethodSlot)
                    {
                    case s_ToStringSlot:
                        realTarget = s_boxAndToStringFuncPtr;
                        break;

                    case s_GetHashCodeSlot:
                        realTarget = s_boxAndGetHashCodeFuncPtr;
                        break;

                    case s_EqualsSlot:
                        realTarget = s_boxAndEqualsFuncPtr;
                        break;

                    default:
                        throw new NotSupportedException();
                    }

                    exactTarget = FunctionPointerOps.GetGenericMethodFunctionPointer(realTarget, callDesc->_constraintType.ToIntPtr());
                }

                // Ensure that all threads will have their function pointers completely published before updating callDesc.
                // as the ExactTarget is read from callDesc by binder generated code without a barrier, we need a barrier here
                // to ensure that the new function pointer data is valid on all threads
                Interlocked.MemoryBarrier();

                // Its possible for multiple threads to race to set exact target. Check to see we always set the same value
                if (callDesc->_exactTarget != IntPtr.Zero)
                {
                    Debug.Assert(callDesc->_exactTarget == exactTarget);
                }

                callDesc->_exactTarget = exactTarget;
                return(exactTarget);
            }