Пример #1
0
 protected override Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
 {
     if (CanonMode == CanonicalizationMode.Standard)
         return StandardCanonicalizationAlgorithm.ConvertInstantiationToCanonForm(instantiation, kind, out changed);
     else
         return RuntimeDeterminedCanonicalizationAlgorithm.ConvertInstantiationToCanonForm(instantiation, kind, out changed);
 }
        /// <summary>
        /// Returns a new instantiation that canonicalizes all types in <paramref name="instantiation"/>
        /// if possible under the policy of '<paramref name="kind"/>'
        /// </summary>
        /// <param name="changed">True if the returned instantiation is different from '<paramref name="instantiation"/>'.</param>
        public static Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
        {
            TypeDesc[] newInstantiation = null;

            for (int i = 0; i < instantiation.Length; i++)
            {
                TypeDesc typeToConvert = instantiation[i];
                TypeDesc convertedType = ConvertToCanon(typeToConvert, kind);

                if (typeToConvert != convertedType || newInstantiation != null)
                {
                    if (newInstantiation == null)
                    {
                        newInstantiation = new TypeDesc[instantiation.Length];
                        for (int j = 0; j < i; j++)
                            newInstantiation[j] = instantiation[j];
                    }

                    newInstantiation[i] = convertedType;
                }
            }

            changed = newInstantiation != null;
            if (changed)
            {
                return new Instantiation(newInstantiation);
            }

            return instantiation;
        }
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            TypeDesc canonicalizedTypeOfTargetMethod = OwningType.ConvertToCanonForm(kind);
            if (canonicalizedTypeOfTargetMethod == OwningType)
                return this;

            return Context.GetMethodForInstantiatedType(GetTypicalMethodDefinition(), (InstantiatedType)canonicalizedTypeOfTargetMethod);
        }
Пример #4
0
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            TypeDesc canonicalizedTypeOfTargetMethod = _owningType.ConvertToCanonForm(kind);
            if (canonicalizedTypeOfTargetMethod == _owningType)
                return this;

            return ((ArrayType)canonicalizedTypeOfTargetMethod).GetArrayMethod(_kind);
        }
Пример #5
0
        protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
        {
            TypeDesc paramTypeConverted = CanonUtilites.ConvertToCanon(ParameterType, kind);
            if (paramTypeConverted != ParameterType)
                return Context.GetPointerType(paramTypeConverted);

            return this;
        }
 internal CanonicallyEquivalentEntryLocator(DefType typeToFind, CanonicalFormKind kind)
 {
     _genericArgs = null;
     _genericDefinition = default(RuntimeTypeHandle);
     _typeToFind = default(RuntimeTypeHandle);
     _canonKind = kind;
     _defType = typeToFind;
 }
 private static TypeDesc ConvertToCanon(TypeDesc typeToConvert, ref CanonicalFormKind kind)
 {
     TypeSystemContext context = typeToConvert.Context;
     if (kind == CanonicalFormKind.Universal)
     {
         return context.UniversalCanonType;
     }
     else if (kind == CanonicalFormKind.Specific)
     {
         if (typeToConvert == context.UniversalCanonType)
         {
             kind = CanonicalFormKind.Universal;
             return context.UniversalCanonType;
         }
         else if (typeToConvert.IsSignatureVariable)
         {
             return typeToConvert;
         }
         else if (typeToConvert.IsDefType)
         {
             if (!typeToConvert.IsValueType)
                 return context.CanonType;
             else if (typeToConvert.HasInstantiation)
             {
                 TypeDesc convertedType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
                 if (convertedType.IsCanonicalSubtype(CanonicalFormKind.Universal))
                 {
                     kind = CanonicalFormKind.Universal;
                     return context.UniversalCanonType;
                 }
                 return convertedType;
             }
             else
                 return typeToConvert;
         }
         else if (typeToConvert.IsArray)
         {
             return context.CanonType;
         }
         else
         {
             TypeDesc convertedType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
             if (convertedType.IsCanonicalSubtype(CanonicalFormKind.Universal))
             {
                 kind = CanonicalFormKind.Universal;
                 return context.UniversalCanonType;
             }
             return convertedType;
         }
     }
     else
     {
         Debug.Assert(false);
         return null;
     }
 }
 public static bool TryGetMethodInvokeMetadata(
     MetadataReader metadataReader,
     RuntimeTypeHandle declaringTypeHandle,
     MethodHandle methodHandle,
     RuntimeTypeHandle[] genericMethodTypeArgumentHandles,
     ref MethodSignatureComparer methodSignatureComparer,
     CanonicalFormKind canonFormKind,
     out MethodInvokeMetadata methodInvokeMetadata)
 {
     throw new NotImplementedException();
 }
        public override bool IsCanonicalSubtype(CanonicalFormKind policy)
        {
            if (_signature.ReturnType.IsCanonicalSubtype(policy))
                return true;

            for (int i = 0; i < _signature.Length; i++)
                if (_signature[i].IsCanonicalSubtype(policy))
                    return true;

            return false;
        }
Пример #10
0
        /// <summary>
        /// Returns the canonical form of this type
        /// </summary>
        public TypeDesc ConvertToCanonForm(CanonicalFormKind kind)
        {
            TypeDesc canonForm = GetCachedCanonValue(kind);
            if (canonForm == null)
            {
                canonForm = ConvertToCanonFormImpl(kind);
                SetCachedCanonValue(kind, canonForm);
            }

            return canonForm;
        }
Пример #11
0
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            if (!OwningType.HasInstantiation)
                return this;

            DefType canonicalizedTypeOfTargetMethod = (DefType)OwningType.ConvertToCanonForm(kind);
            if (canonicalizedTypeOfTargetMethod == OwningType)
                return this;

            return Context.ResolveRuntimeMethod(this.UnboxingStub, canonicalizedTypeOfTargetMethod, this.NameAndSignature, IntPtr.Zero, false);
        }
Пример #12
0
        protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
        {
            bool needsChange;
            Instantiation canonInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Instantiation, kind, out needsChange);
            if (needsChange)
            {
                MetadataType openType = (MetadataType)GetTypeDefinition();
                return Context.GetInstantiatedType(openType, canonInstantiation);
            }

            return this;
        }
Пример #13
0
        public override bool IsCanonicalSubtype(CanonicalFormKind policy)
        {
            foreach (TypeDesc t in Instantiation)
            {
                if (t.IsCanonicalSubtype(policy))
                {
                    return true;
                }
            }

            return false;
        }
Пример #14
0
        protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
        {
            TypeDesc paramTypeConverted = Context.ConvertToCanon(ParameterType, kind);
            if (paramTypeConverted != ParameterType)
            {
                // Note: don't use the Rank property here, as that hides the difference
                // between a single dimensional MD array and an SZArray.
                return Context.GetArrayType(paramTypeConverted, _rank);
            }

            return this;
        }
        protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
        {
            MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(_signature);
            sigBuilder.ReturnType = Context.ConvertToCanon(_signature.ReturnType, kind);
            for (int i = 0; i < _signature.Length; i++)
                sigBuilder[i] = Context.ConvertToCanon(_signature[i], kind);

            MethodSignature canonSignature = sigBuilder.ToSignature();
            if (canonSignature != _signature)
                return Context.GetFunctionPointerType(canonSignature);

            return this;
        }
Пример #16
0
        InstantiatedMethod GetCachedCanonValue(CanonicalFormKind kind)
        {
            switch (kind)
            {
            case CanonicalFormKind.Specific:
                return(_specificCanonCache);

            case CanonicalFormKind.Universal:
                return(_universalCanonCache);

            default:
                Debug.Fail("Invalid CanonicalFormKind: " + kind);
                return(null);
            }
        }
Пример #17
0
        InstantiatedMethod GetCachedCanonValue(CanonicalFormKind kind)
        {
            switch (kind)
            {
                case CanonicalFormKind.Specific:
                    return _specificCanonCache;

                case CanonicalFormKind.Universal:
                    return _universalCanonCache;

                default:
                    Debug.Fail("Invalid CanonicalFormKind: " + kind);
                    return null;
            }
        }
Пример #18
0
        /// <summary>
        /// Helper API to convert a type to its canonical or universal canonical form.
        /// Note that for now, there is no mixture between specific canonical and universal canonical forms,
        /// meaning that the canonical form or Foo<string, int> can either be Foo<__Canon, int> or
        /// Foo<__UniversalCanon, __UniversalCanon>. It cannot be Foo<__Canon, __UniversalCanon> (yet)
        /// for simplicity. We can always change that rule in the futue and add support for the mixture, but
        /// for now we are keeping it simple.
        /// </summary>
        public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, CanonicalFormKind kind)
        {
            TypeSystemContext context = typeToConvert.Context;

            if (kind == CanonicalFormKind.Universal)
            {
                return(context.UniversalCanonType);
            }
            else if (kind == CanonicalFormKind.Specific)
            {
                if (typeToConvert == context.UniversalCanonType)
                {
                    return(context.UniversalCanonType);
                }
                else if (typeToConvert.IsSignatureVariable)
                {
                    return(typeToConvert);
                }
                else if (typeToConvert.IsDefType)
                {
                    if (!typeToConvert.IsValueType)
                    {
                        return(context.CanonType);
                    }
                    else if (typeToConvert.HasInstantiation)
                    {
                        return(typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific));
                    }
                    else
                    {
                        return(typeToConvert);
                    }
                }
                else if (typeToConvert.IsArray)
                {
                    return(context.CanonType);
                }
                else
                {
                    return(typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific));
                }
            }
            else
            {
                Debug.Assert(false);
                return(null);
            }
        }
        public static Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
        {
            TypeDesc[] canonInstantiation = null;

            CanonicalFormKind currentKind = kind;
            CanonicalFormKind startLoopKind;

            // This logic is wrapped in a loop because we might potentially need to restart canonicalization if the policy
            // changes due to one of the instantiation arguments already being universally canonical.
            do
            {
                startLoopKind = currentKind;

                for (int instantiationIndex = 0; instantiationIndex < instantiation.Length; instantiationIndex++)
                {
                    TypeDesc typeToConvert = instantiation[instantiationIndex];
                    TypeDesc canonForm = ConvertToCanon(typeToConvert, ref currentKind);
                    if (typeToConvert != canonForm || canonInstantiation != null)
                    {
                        if (canonInstantiation == null)
                        {
                            canonInstantiation = new TypeDesc[instantiation.Length];
                            for (int i = 0; i < instantiationIndex; i++)
                                canonInstantiation[i] = instantiation[i];
                        }

                        canonInstantiation[instantiationIndex] = canonForm;
                    }
                }

                // Optimization: even if canonical policy changed, we don't actually need to re-run the loop
                // for instantiations that only have a single element.
                if (instantiation.Length == 1)
                {
                    break;
                }

            } while (currentKind != startLoopKind);


            changed = canonInstantiation != null;
            if (changed)
            {
                return new Instantiation(canonInstantiation);
            }

            return instantiation;
        }
Пример #20
0
        public CanonicallyEquivalentEntryLocator(RuntimeTypeHandle typeToFind, CanonicalFormKind kind)
        {
            if (RuntimeAugments.IsGenericType(typeToFind))
            {
                _genericDefinition = RuntimeAugments.GetGenericInstantiation(typeToFind, out _genericArgs);
            }
            else
            {
                _genericArgs       = null;
                _genericDefinition = default(RuntimeTypeHandle);
            }

            _typeToFind = typeToFind;
            _canonKind  = kind;
            _defType    = null;
        }
Пример #21
0
 /// <summary>
 /// Returns true if and only if the '<paramref name="type"/>' is __Canon or __UniversalCanon
 /// that matches the <paramref name="kind"/> parameter.
 /// </summary>
 public bool IsCanonicalDefinitionType(TypeDesc type, CanonicalFormKind kind)
 {
     if (kind == CanonicalFormKind.Any)
     {
         return type == CanonType || type == UniversalCanonType;
     }
     else if (kind == CanonicalFormKind.Specific)
     {
         return type == CanonType;
     }
     else
     {
         Debug.Assert(kind == CanonicalFormKind.Universal);
         return type == UniversalCanonType;
     }
 }
        public CanonicallyEquivalentEntryLocator(RuntimeTypeHandle typeToFind, CanonicalFormKind kind)
        {
            if (RuntimeAugments.IsGenericType(typeToFind))
            {
                _genericDefinition = RuntimeAugments.GetGenericInstantiation(typeToFind, out _genericArgs);
            }
            else
            {
                _genericArgs = null;
                _genericDefinition = default(RuntimeTypeHandle);
            }

            _typeToFind = typeToFind;
            _canonKind = kind;
            _defType = null;
        }
Пример #23
0
 /// <summary>
 /// Returns true if and only if the '<paramref name="type"/>' is __Canon or __UniversalCanon
 /// that matches the <paramref name="kind"/> parameter.
 /// </summary>
 public bool IsCanonicalDefinitionType(TypeDesc type, CanonicalFormKind kind)
 {
     if (kind == CanonicalFormKind.Any)
     {
         return(type == CanonType || type == UniversalCanonType);
     }
     else if (kind == CanonicalFormKind.Specific)
     {
         return(type == CanonType);
     }
     else
     {
         Debug.Assert(kind == CanonicalFormKind.Universal);
         return(type == UniversalCanonType);
     }
 }
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            if (!OwningType.HasInstantiation)
            {
                return(this);
            }

            DefType canonicalizedTypeOfTargetMethod = (DefType)OwningType.ConvertToCanonForm(kind);

            if (canonicalizedTypeOfTargetMethod == OwningType)
            {
                return(this);
            }

            return(Context.ResolveRuntimeMethod(this.UnboxingStub, canonicalizedTypeOfTargetMethod, this.NameAndSignature, IntPtr.Zero, false));
        }
        /// <summary>
        /// True if either the containing type instantiation or any of this method's generic arguments
        /// are canonical
        /// </summary>
        public override bool IsCanonicalMethod(CanonicalFormKind policy)
        {
            if (OwningType.HasInstantiation && OwningType.IsCanonicalSubtype(policy))
            {
                return(true);
            }

            foreach (TypeDesc type in Instantiation)
            {
                if (type.IsCanonicalSubtype(policy))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #26
0
        public override bool IsCanonicalSubtype(CanonicalFormKind policy)
        {
            if (_signature.ReturnType.IsCanonicalSubtype(policy))
            {
                return(true);
            }

            for (int i = 0; i < _signature.Length; i++)
            {
                if (_signature[i].IsCanonicalSubtype(policy))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #27
0
        /// <summary>
        /// True if either the containing type instantiation or any of this method's generic arguments
        /// are canonical
        /// </summary>
        public override bool IsCanonicalMethod(CanonicalFormKind policy)
        {
            if (OwningType.HasInstantiation && OwningType.IsCanonicalSubtype(policy))
            {
                return true;
            }

            foreach (TypeDesc type in Instantiation)
            {
                if (type.IsCanonicalSubtype(policy))
                {
                    return true;
                }
            }

            return false;
        }
Пример #28
0
        void SetCachedCanonValue(CanonicalFormKind kind, TypeDesc value)
        {
            switch (kind)
            {
            case CanonicalFormKind.Specific:
                Debug.Assert(_specificCanonCache == null || _specificCanonCache == value);
                _specificCanonCache = value;
                break;

            case CanonicalFormKind.Universal:
                Debug.Assert(_universalCanonCache == null || _universalCanonCache == value);
                _universalCanonCache = value;
                break;

            default:
                Debug.Fail("Invalid CanonicalFormKind: " + kind);
                break;
            }
        }
Пример #29
0
        protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
        {
            MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(_signature);

            sigBuilder.ReturnType = Context.ConvertToCanon(_signature.ReturnType, kind);
            for (int i = 0; i < _signature.Length; i++)
            {
                sigBuilder[i] = Context.ConvertToCanon(_signature[i], kind);
            }

            MethodSignature canonSignature = sigBuilder.ToSignature();

            if (canonSignature != _signature)
            {
                return(Context.GetFunctionPointerType(canonSignature));
            }

            return(this);
        }
Пример #30
0
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);

            if (canonicalMethodResult != null)
            {
                return(canonicalMethodResult);
            }

            MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);

            // TODO: We should avoid the array allocation if conversion to canon is not change (take hint from MethodDesc.InstantiateSignature)
            Instantiation newInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Context, Instantiation, kind);

            canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, newInstantiation);

            SetCachedCanonValue(kind, canonicalMethodResult);
            return(GetCachedCanonValue(kind));
        }
Пример #31
0
        void SetCachedCanonValue(CanonicalFormKind kind, InstantiatedMethod value)
        {
            switch(kind)
            {
                case CanonicalFormKind.Specific:
                    Debug.Assert(_specificCanonCache == null || _specificCanonCache == value);
                    _specificCanonCache = value;
                    break;

                case CanonicalFormKind.Universal:
                    Debug.Assert(_universalCanonCache == null || _universalCanonCache == value);
                    _universalCanonCache = value;
                    break;

                default:
                    Debug.Fail("Invalid CanonicalFormKind: " + kind);
                    break;
            }
        }
Пример #32
0
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);
            if (canonicalMethodResult == null)
            {
                bool needsChange;
                Instantiation canonInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Instantiation, kind, out needsChange);
                if (needsChange)
                {
                    MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);
                    canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation);
                }
                else
                {
                    canonicalMethodResult = this;
                }

                SetCachedCanonValue(kind, canonicalMethodResult);
            }
            
            return canonicalMethodResult;
        }
Пример #33
0
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);
            if (canonicalMethodResult == null)
            {
                bool instantiationChanged;
                Instantiation canonInstantiation = Context.ConvertInstantiationToCanonForm(Instantiation, kind, out instantiationChanged);
                MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);

                if (instantiationChanged || (openMethodOnCanonicalizedType != _methodDef))
                {
                    canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation);
                }
                else
                {
                    canonicalMethodResult = this;
                }

                SetCachedCanonValue(kind, canonicalMethodResult);
            }
            
            return canonicalMethodResult;
        }
Пример #34
0
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);

            if (canonicalMethodResult == null)
            {
                bool          needsChange;
                Instantiation canonInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Instantiation, kind, out needsChange);
                if (needsChange)
                {
                    MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);
                    canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation);
                }
                else
                {
                    canonicalMethodResult = this;
                }

                SetCachedCanonValue(kind, canonicalMethodResult);
            }

            return(canonicalMethodResult);
        }
Пример #35
0
 /// <summary>
 /// Helper API to convert a type to its canonical or universal canonical form.
 /// Note that for now, there is no mixture between specific canonical and universal canonical forms,
 /// meaning that the canonical form or Foo<string, int> can either be Foo<__Canon, int> or
 /// Foo<__UniversalCanon, __UniversalCanon>. It cannot be Foo<__Canon, __UniversalCanon> (yet)
 /// for simplicity. We can always change that rule in the futue and add support for the mixture, but
 /// for now we are keeping it simple.
 /// </summary>
 public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, CanonicalFormKind kind)
 {
     TypeSystemContext context = typeToConvert.Context;
     if (kind == CanonicalFormKind.Universal)
     {
         return context.UniversalCanonType;
     }
     else if (kind == CanonicalFormKind.Specific)
     {
         if (typeToConvert == context.UniversalCanonType)
         {
             return context.UniversalCanonType;
         }
         else if (typeToConvert.IsDefType)
         {
             if (!typeToConvert.IsValueType)
                 return context.CanonType;
             else if (typeToConvert.HasInstantiation)
                 return typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
             else
                 return typeToConvert;
         }
         else if (typeToConvert.IsArray)
         {
             return context.CanonType;
         }
         else
         {
             return typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
         }
     }
     else
     {
         Debug.Assert(false);
         return null;
     }
 }
Пример #36
0
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);

            if (canonicalMethodResult == null)
            {
                bool          instantiationChanged;
                Instantiation canonInstantiation            = Context.ConvertInstantiationToCanonForm(Instantiation, kind, out instantiationChanged);
                MethodDesc    openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);

                if (instantiationChanged || (openMethodOnCanonicalizedType != _methodDef))
                {
                    canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation);
                }
                else
                {
                    canonicalMethodResult = this;
                }

                SetCachedCanonValue(kind, canonicalMethodResult);
            }

            return(canonicalMethodResult);
        }
Пример #37
0
 public override bool IsCanonicalMethod(CanonicalFormKind policy)
 {
     return _owningType.IsCanonicalSubtype(policy);
 }
Пример #38
0
        /// <summary>
        /// Returns a new instantiation that canonicalizes all types in <paramref name="instantiation"/>
        /// if possible under the policy of '<paramref name="kind"/>'
        /// </summary>
        /// <param name="instantiation">Instantiation to canonicalize.</param>
        /// <param name="kind">The type of cannonicalization to apply.</param>
        /// <param name="changed">True if the returned instantiation is different from '<paramref name="instantiation"/>'.</param>
        public static Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
        {
            TypeDesc[] canonInstantiation = null;

            CanonicalFormKind currentKind = kind;
            CanonicalFormKind startLoopKind;

            // This logic is wrapped in a loop because we might potentially need to restart canonicalization if the policy
            // changes due to one of the instantiation arguments already being universally canonical.
            do
            {
                startLoopKind = currentKind;

                for (int instantiationIndex = 0; instantiationIndex < instantiation.Length; instantiationIndex++)
                {
                    TypeDesc typeToConvert = instantiation[instantiationIndex];
                    TypeDesc canonForm     = ConvertToCanon(typeToConvert, ref currentKind);
                    if (typeToConvert != canonForm || canonInstantiation != null)
                    {
                        if (canonInstantiation == null)
                        {
                            canonInstantiation = new TypeDesc[instantiation.Length];
                            for (int i = 0; i < instantiationIndex; i++)
                            {
                                canonInstantiation[i] = instantiation[i];
                            }
                        }

                        canonInstantiation[instantiationIndex] = canonForm;
                    }
                }

                // Optimization: even if canonical policy changed, we don't actually need to re-run the loop
                // for instantiations that only have a single element.
                if (instantiation.Length == 1)
                {
                    break;
                }
            } while (currentKind != startLoopKind);


            changed = canonInstantiation != null;
            if (changed)
            {
                return(new Instantiation(canonInstantiation));
            }

            return(instantiation);
        }
Пример #39
0
 // Helper API to convert a type to its canonical or universal canonical form.
 // Note that for now, there is no mixture between specific canonical and universal canonical forms,
 // meaning that the canonical form or Foo<string, int> can either be Foo<__Canon, int> or
 // Foo<__UniversalCanon, __UniversalCanon>. It cannot be Foo<__Canon, __UniversalCanon> (yet)
 // for simplicity. We can always change that rule in the futue and add support for the mixture, but
 // for now we are keeping it simple.
 public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, CanonicalFormKind kind)
 {
     // Wrap the call to the version that potentially modifies the parameter. External
     // callers are not interested in that.
     return(ConvertToCanon(typeToConvert, ref kind));
 }
Пример #40
0
 protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
 {
     Debug.Assert(kind == CanonicalFormKind.Universal);
     return this;
 }
Пример #41
0
        /// <summary>
        /// Returns a new instantiation that canonicalizes all types in <paramref name="instantiation"/>
        /// if possible under the policy of '<paramref name="kind"/>'
        /// </summary>
        /// <param name="changed">True if the returned instantiation is different from '<paramref name="instantiation"/>'.</param>
        public static Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
        {
            TypeDesc[] newInstantiation = null;

            for (int i = 0; i < instantiation.Length; i++)
            {
                TypeDesc typeToConvert = instantiation[i];
                TypeDesc convertedType = ConvertToCanon(typeToConvert, kind);

                if (typeToConvert != convertedType || newInstantiation != null)
                {
                    if (newInstantiation == null)
                    {
                        newInstantiation = new TypeDesc[instantiation.Length];
                        for (int j = 0; j < i; j++)
                        {
                            newInstantiation[j] = instantiation[j];
                        }
                    }

                    newInstantiation[i] = convertedType;
                }
            }

            changed = newInstantiation != null;
            if (changed)
            {
                return(new Instantiation(newInstantiation));
            }

            return(instantiation);
        }
Пример #42
0
 public override bool IsCanonicalSubtype(CanonicalFormKind policy)
 {
     Debug.Assert(!HasInstantiation, "Why is this generic?");
     return(false);
 }
Пример #43
0
        protected override Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
        {
            if (_genericsMode == SharedGenericsMode.CanonicalReferenceTypes)
            {
                return(RuntimeDeterminedCanonicalizationAlgorithm.ConvertInstantiationToCanonForm(instantiation, kind, out changed));
            }

            Debug.Assert(_genericsMode == SharedGenericsMode.Disabled);
            changed = false;
            return(instantiation);
        }
 public sealed override bool IsCanonicalSubtype(CanonicalFormKind policy)
 {
     Debug.Assert(false, "IsCanonicalSubtype of an indefinite type");
     return(false);
 }
 protected sealed override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
 {
     Debug.Assert(false, "ConvertToCanonFormImpl for an indefinite type");
     return(this);
 }
Пример #46
0
 /// <summary>
 /// Converts an instantiation into its canonical form. Returns the canonical instantiation. The '<paramref name="changed"/>'
 /// parameter indicates whether the returned canonical instantiation is different from the specific instantiation
 /// passed as the input.
 /// </summary>
 protected internal virtual Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
 {
     throw new NotSupportedException();
 }
Пример #47
0
 public CanonicallyEquivalentEntryLocator(RuntimeTypeHandle typeToFind, CanonicalFormKind kind)
 {
     _typeToFind = typeToFind;
 }
Пример #48
0
 public CanonicallyEquivalentEntryLocator(RuntimeTypeHandle typeToFind, CanonicalFormKind kind)
 {
     _typeToFind = typeToFind;
 }
Пример #49
0
        /// <summary>
        /// Returns a new instantiation that canonicalizes all types in <paramref name="instantiation"/>
        /// if possible under the policy of <paramref name="kind"/>
        /// </summary>
        public static Instantiation ConvertInstantiationToCanonForm(TypeSystemContext context, Instantiation instantiation, CanonicalFormKind kind)
        {
            TypeDesc[] newInstantiation = new TypeDesc[instantiation.Length];

            for (int i = 0; i < instantiation.Length; i++)
            {
                newInstantiation[i] = ConvertToCanon(instantiation[i], kind);
            }

            return(new Instantiation(newInstantiation));
        }
Пример #50
0
 /// <summary>
 /// Returns true if canonicalizing this instantiation produces a different instantiation
 /// </summary>
 /// <param name="kind">Canonicalization policy to apply</param>
 public static bool ConversionToCanonFormIsAChange(TypeSystemContext context, Instantiation instantiation, CanonicalFormKind kind)
 {
     foreach (TypeDesc type in instantiation)
     {
         TypeDesc potentialCanonType = ConvertToCanon(type, kind);
         if (type != potentialCanonType)
         {
             return(true);
         }
     }
     return(false);
 }
Пример #51
0
        /// <summary>
        /// Converts an instantiation into its canonical form.
        /// </summary>
        public Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind)
        {
            bool changed;

            return(ConvertInstantiationToCanonForm(instantiation, kind, out changed));
        }
Пример #52
0
        public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, ref CanonicalFormKind kind)
        {
            TypeSystemContext context = typeToConvert.Context;

            if (kind == CanonicalFormKind.Universal)
            {
                return(context.UniversalCanonType);
            }
            else if (kind == CanonicalFormKind.Specific)
            {
                if (typeToConvert == context.UniversalCanonType)
                {
                    kind = CanonicalFormKind.Universal;
                    return(context.UniversalCanonType);
                }
                else if (typeToConvert.IsSignatureVariable)
                {
                    return(typeToConvert);
                }
                else if (typeToConvert.IsDefType)
                {
                    if (!typeToConvert.IsValueType)
                    {
                        return(context.CanonType);
                    }
                    else if (typeToConvert.HasInstantiation)
                    {
                        // This is a generic struct type. If the generic struct is instantiated over universal canon,
                        // the entire struct becomes universally canonical.
                        if (typeToConvert.IsCanonicalSubtype(CanonicalFormKind.Universal))
                        {
                            kind = CanonicalFormKind.Universal;
                            return(context.UniversalCanonType);
                        }

                        TypeDesc canonicalType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);

                        // We could still have ended up with a universal canonical form here because conversion to
                        // canon form strips runtime determined types from their constituents.
                        // MyStruct<T__UniversalCanon> (which is not universally canonical) becomes MyStruct<__UniversalCanon>.
                        if (canonicalType.IsCanonicalSubtype(CanonicalFormKind.Universal))
                        {
                            kind = CanonicalFormKind.Universal;
                            return(context.UniversalCanonType);
                        }

                        return(canonicalType);
                    }
                    else if (typeToConvert.IsRuntimeDeterminedType)
                    {
                        // For non-universal canon cases, RuntimeDeterminedType's passed into this function are either
                        // reference types (which are turned into normal Canon), or instantiated types (which are handled
                        // by the above case.). But for UniversalCanon, we can have non-instantiated universal canon
                        // which will reach this case.

                        // We should only ever reach this for T__UniversalCanon.
                        Debug.Assert(((RuntimeDeterminedType)typeToConvert).CanonicalType == context.UniversalCanonType);

                        kind = CanonicalFormKind.Universal;
                        return(context.UniversalCanonType);
                    }
                    else
                    {
                        return(typeToConvert);
                    }
                }
                else if (typeToConvert.IsArray)
                {
                    return(context.CanonType);
                }
                else
                {
                    if (typeToConvert.IsCanonicalSubtype(CanonicalFormKind.Universal))
                    {
                        kind = CanonicalFormKind.Universal;
                        return(context.UniversalCanonType);
                    }

                    return(typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific));
                }
            }
            else
            {
                Debug.Assert(false);
                return(null);
            }
        }
Пример #53
0
 protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
 {
     Debug.Assert(false, "ConvertToCanonFormImpl for an indefinite type");
     return this;
 }
Пример #54
0
        /// <summary>
        /// Try to look up field acccess info for given canon in metadata blobs for all available modules.
        /// </summary>
        /// <param name="metadataReader">Metadata reader for the declaring type</param>
        /// <param name="declaringTypeHandle">Declaring type for the method</param>
        /// <param name="fieldHandle">Field handle</param>
        /// <param name="canonFormKind">Canonical form to use</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static bool TryGetFieldAccessMetadataFromFieldAccessMap(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            CanonicalFormKind canonFormKind,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind);
            IntPtr            fieldHandleModule            = ModuleList.Instance.GetModuleForMetadataReader(metadataReader);
            bool              isDynamicType = RuntimeAugments.IsDynamicType(declaringTypeHandle);
            string            fieldName     = null;
            RuntimeTypeHandle declaringTypeHandleDefinition = Instance.GetTypeDefinition(declaringTypeHandle);

            foreach (IntPtr mappingTableModule in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)))
            {
                NativeReader fieldMapReader;
                if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader))
                {
                    continue;
                }

                NativeParser    fieldMapParser = new NativeParser(fieldMapReader, 0);
                NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser);

                ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
                if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule))
                {
                    continue;
                }

                var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    // Grammar of a hash table entry:
                    // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset

                    FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned();

                    if ((canonFormKind == CanonicalFormKind.Universal) != entryFlags.HasFlag(FieldTableFlags.IsUniversalCanonicalEntry))
                    {
                        continue;
                    }

                    RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) &&
                        !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle))
                    {
                        continue;
                    }

                    if (entryFlags.HasFlag(FieldTableFlags.HasMetadataHandle))
                    {
                        Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle();
                        if (!fieldHandle.Equals(entryFieldHandle))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (fieldName == null)
                        {
                            MetadataReader       mdReader;
                            TypeDefinitionHandle typeDefHandleUnused;
                            bool success = Instance.TryGetMetadataForNamedType(
                                declaringTypeHandleDefinition,
                                out mdReader,
                                out typeDefHandleUnused);
                            Debug.Assert(success);

                            fieldName = mdReader.GetString(fieldHandle.GetField(mdReader).Name);
                        }

                        string entryFieldName = entryParser.GetString();

                        if (fieldName != entryFieldName)
                        {
                            continue;
                        }
                    }

                    int    cookieOrOffsetOrOrdinal = (int)entryParser.GetUnsigned();
                    int    fieldOffset;
                    IntPtr fieldAddressCookie = IntPtr.Zero;

                    if (canonFormKind == CanonicalFormKind.Universal)
                    {
                        if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, (uint)cookieOrOffsetOrOrdinal, out fieldOffset))
                        {
                            Debug.Assert(false);
                            return(false);
                        }
                    }
                    else
                    {
#if CORERT
                        fieldOffset = cookieOrOffsetOrOrdinal;
#else
                        fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal);
#endif
                    }

                    if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic)
                    {
                        if (canonFormKind != CanonicalFormKind.Universal)
                        {
                            fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule, fieldOffset);
                        }

                        if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle))
                        {
                            // In this case we didn't find an exact match, but we did find a canonically equivalent match
                            // We might be in the dynamic type case, or the canonically equivalent, but not the same case.

                            if (!RuntimeAugments.IsDynamicType(declaringTypeHandle))
                            {
                                int offsetToCreateCookieFor = fieldOffset;
                                // We're working with a statically generated type, but we didn't find an exact match in the tables
                                if (canonFormKind != CanonicalFormKind.Universal)
                                {
                                    offsetToCreateCookieFor = checked ((int)TypeLoaderEnvironment.GetThreadStaticTypeOffsetFromThreadStaticCookie(fieldAddressCookie));
                                }

                                fieldAddressCookie = TypeLoaderEnvironment.Instance.TryGetThreadStaticFieldOffsetCookieForTypeAndFieldOffset(declaringTypeHandle, checked ((uint)offsetToCreateCookieFor));
                            }
                        }
                    }

                    fieldAccessMetadata.MappingTableModule = mappingTableModule;
                    fieldAccessMetadata.Cookie             = fieldAddressCookie;
                    fieldAccessMetadata.Flags  = entryFlags;
                    fieldAccessMetadata.Offset = fieldOffset;
                    return(true);
                }
            }

            return(false);
        }
Пример #55
0
 /// <summary>
 /// Wrapper helper function around the IsCanonicalDefinitionType API on the TypeSystemContext
 /// </summary>
 public static bool IsCanonicalDefinitionType(this TypeDesc type, CanonicalFormKind kind)
 {
     return(type.Context.IsCanonicalDefinitionType(type, kind));
 }
Пример #56
0
        public bool CanInstantiationsShareCode(RuntimeTypeHandle[] genericArgHandles1, RuntimeTypeHandle[] genericArgHandles2, CanonicalFormKind kind)
        {
            if (genericArgHandles1.Length != genericArgHandles2.Length)
                return false;

            bool match = true;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            for (int i = 0; i < genericArgHandles1.Length; i++)
            {
                TypeDesc genericArg1 = context.ResolveRuntimeTypeHandle(genericArgHandles1[i]);
                TypeDesc genericArg2 = context.ResolveRuntimeTypeHandle(genericArgHandles2[i]);

                if (context.ConvertToCanon(genericArg1, kind) != context.ConvertToCanon(genericArg2, kind))
                {
                    match = false;
                    break;
                }
            }

            TypeSystemContextFactory.Recycle(context);

            return match;
        }
Пример #57
0
 public override bool IsCanonicalSubtype(CanonicalFormKind policy)
 {
     return policy == CanonicalFormKind.Universal || 
         policy == CanonicalFormKind.Any;
 }
Пример #58
0
        public bool ConversionToCanonFormIsAChange(RuntimeTypeHandle[] genericArgHandles, CanonicalFormKind kind)
        {
            // Todo: support for universal canon type?

            TypeSystemContext context = TypeSystemContextFactory.Create();

            Instantiation genericArgs = context.ResolveRuntimeTypeHandles(genericArgHandles);
            bool result;
            context.ConvertInstantiationToCanonForm(genericArgs, kind, out result);

            TypeSystemContextFactory.Recycle(context);

            return result;
        }
Пример #59
0
 public override bool IsCanonicalSubtype(CanonicalFormKind policy)
 {
     return policy == CanonicalFormKind.Specific ||
         policy == CanonicalFormKind.Any;
 }
Пример #60
0
 /// <summary>
 /// Converts a constituent of a constructed type to it's canonical form. Note this method is different
 /// from <see cref="TypeDesc.ConvertToCanonForm(CanonicalFormKind)"/>.
 /// </summary>
 protected internal virtual TypeDesc ConvertToCanon(TypeDesc typeToConvert, CanonicalFormKind kind)
 {
     throw new NotSupportedException();
 }