Example #1
0
        /// <summary>
        /// For a shared (canonical) instance method on a generic valuetype, gets a method that can be used to call the
        /// method given a boxed version of the generic valuetype as 'this' pointer.
        /// </summary>
        public MethodDesc GetSpecialUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk)
        {
            Debug.Assert(targetMethod.IsSharedByGenericInstantiations);
            Debug.Assert(!targetMethod.Signature.IsStatic);
            Debug.Assert(!targetMethod.HasInstantiation);

            TypeDesc owningType = targetMethod.OwningType;

            Debug.Assert(owningType.IsValueType);

            var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition();

            // Get a reference type that has the same layout as the boxed valuetype.
            var            typeKey             = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk);
            BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey);

            // Get a method on the reference type with the same signature as the target method (but different
            // calling convention, since 'this' will be a reference type).
            var targetMethodDefinition = targetMethod.GetTypicalMethodDefinition();
            var methodKey = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition);
            GenericUnboxingThunk thunkDefinition = _unboxingThunkHashtable.GetOrCreateValue(methodKey);

            // Find the thunk on the instantiated version of the reference type.
            Debug.Assert(owningType != owningTypeDefinition);
            InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation);

            MethodDesc thunk = GetMethodForInstantiatedType(thunkDefinition, boxedType);

            Debug.Assert(!thunk.HasInstantiation);

            return(thunk);
        }
        public MethodDesc GetUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk)
        {
            TypeDesc owningType = targetMethod.OwningType;

            Debug.Assert(owningType.IsValueType);

            var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition();

            // Get a reference type that has the same layout as the boxed valuetype.
            var            typeKey             = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk);
            BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey);

            // Get a method on the reference type with the same signature as the target method (but different
            // calling convention, since 'this' will be a reference type).
            var           targetMethodDefinition = targetMethod.GetTypicalMethodDefinition();
            var           methodKey       = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition);
            UnboxingThunk thunkDefinition = _nonGenericUnboxingThunkHashtable.GetOrCreateValue(methodKey);

            // Find the thunk on the instantiated version of the reference type.
            if (owningType != owningTypeDefinition)
            {
                InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation);
                MethodDesc       thunk     = GetMethodForInstantiatedType(thunkDefinition, boxedType);
                //TODO: this might be triggered by a struct that implements an interface with a generic method
                Debug.Assert(!thunk.HasInstantiation);
                return(thunk);
            }
            else
            {
                //TODO: this might be triggered by a struct that implements an interface with a generic method
                Debug.Assert(!thunkDefinition.HasInstantiation);
                return(thunkDefinition);
            }
        }