protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
        {
            DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory);

            // Ensure that we track the necessary type symbol if we are working with a constructed type symbol.
            // The emitter will ensure we don't emit both, but this allows us assert that we only generate
            // relocs to nodes we emit.
            dependencyList.Add(factory.NecessaryTypeSymbol(_type), "Necessary type symbol related to CanonicalEETypeNode");

            DefType closestDefType = _type.GetClosestDefType();

            if (InterfaceDispatchMapNode.MightHaveInterfaceDispatchMap(_type, factory))
            {
                dependencyList.Add(factory.InterfaceDispatchMap(_type), "Canonical interface dispatch map");
            }

            dependencyList.Add(factory.VTable(closestDefType), "VTable");

            if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal))
            {
                dependencyList.Add(factory.NativeLayout.TemplateTypeLayout(_type), "Universal generic types always have template layout");
            }

            // Track generic virtual methods that will get added to the GVM tables
            if (TypeGVMEntriesNode.TypeNeedsGVMTableEntries(_type))
            {
                dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type), "Type with generic virtual methods"));

                AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList);
            }

            return(dependencyList);
        }
        protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
        {
            DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory);

            // Ensure that we track the necessary type symbol if we are working with a constructed type symbol.
            // The emitter will ensure we don't emit both, but this allows us assert that we only generate
            // relocs to nodes we emit.
            dependencyList.Add(factory.NecessaryTypeSymbol(_type), "NecessaryType for constructed type");

            DefType closestDefType = _type.GetClosestDefType();

            if (InterfaceDispatchMapNode.MightHaveInterfaceDispatchMap(_type, factory))
            {
                dependencyList.Add(factory.InterfaceDispatchMap(_type), "Interface dispatch map");
            }

            if (_type.IsArray)
            {
                // Array EEType depends on System.Array's virtuals. Array EETypes don't point to
                // their base type (i.e. there's no reloc based dependency making this "just work").
                dependencyList.Add(factory.ConstructedTypeSymbol(_type.BaseType), "Array base type");

                ArrayType arrayType = (ArrayType)_type;
                if (arrayType.IsMdArray && arrayType.Rank == 1)
                {
                    // Allocating an MDArray of Rank 1 with zero lower bounds results in allocating
                    // an SzArray instead. Make sure the type loader can find the SzArray type.
                    dependencyList.Add(factory.ConstructedTypeSymbol(arrayType.ElementType.MakeArrayType()), "Rank 1 array");
                }
            }

            dependencyList.Add(factory.VTable(closestDefType), "VTable");

            if (closestDefType.HasInstantiation && factory.MetadataManager.SupportsReflection)
            {
                TypeDesc canonType           = _type.ConvertToCanonForm(CanonicalFormKind.Specific);
                TypeDesc canonClosestDefType = closestDefType.ConvertToCanonForm(CanonicalFormKind.Specific);

                // Add a dependency on the template for this type, if the canonical type should be generated into this binary.
                // If the type is an array type, the check should be on its underlying Array<T> type. This is because a copy of
                // an array type gets placed into each module but the Array<T> type only exists in the defining module and only
                // one template is needed for the Array<T> type by the dynamic type loader.
                if (canonType.IsCanonicalSubtype(CanonicalFormKind.Any) && !factory.NecessaryTypeSymbol(canonClosestDefType).RepresentsIndirectionCell)
                {
                    dependencyList.Add(factory.NativeLayout.TemplateTypeLayout(canonType), "Template Type Layout");
                }
            }

            // Generated type contains generic virtual methods that will get added to the GVM tables
            if (TypeGVMEntriesNode.TypeNeedsGVMTableEntries(_type))
            {
                dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type), "Type with generic virtual methods"));

                AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList);
            }

            if (factory.TypeSystemContext.HasLazyStaticConstructor(_type))
            {
                // The fact that we generated an EEType means that someone can call RuntimeHelpers.RunClassConstructor.
                // We need to make sure this is possible.
                dependencyList.Add(new DependencyListEntry(factory.TypeNonGCStaticsSymbol((MetadataType)_type), "Class constructor"));
            }

            // Ask the metadata manager if we have any dependencies due to reflectability.
            factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencyList, factory, _type);

            factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type);

            return(dependencyList);
        }
        internal uint AddDispatchMap(InterfaceDispatchMapNode node)
        {
            _dispatchMaps.Add(node);

            return((uint)_dispatchMaps.Count - 1);
        }
        internal uint AddDispatchMap(InterfaceDispatchMapNode node)
        {
            _dispatchMaps.Add(node);

            return (uint)_dispatchMaps.Count - 1;
        }
Beispiel #5
0
        protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
        {
            DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory);

            // Ensure that we track the necessary type symbol if we are working with a constructed type symbol.
            // The emitter will ensure we don't emit both, but this allows us assert that we only generate
            // relocs to nodes we emit.
            dependencyList.Add(factory.NecessaryTypeSymbol(_type), "NecessaryType for constructed type");

            DefType closestDefType = _type.GetClosestDefType();

            if (InterfaceDispatchMapNode.MightHaveInterfaceDispatchMap(_type, factory))
            {
                dependencyList.Add(factory.InterfaceDispatchMap(_type), "Interface dispatch map");
            }

            if (_type.IsArray)
            {
                // Array EEType depends on System.Array's virtuals. Array EETypes don't point to
                // their base type (i.e. there's no reloc based dependency making this "just work").
                dependencyList.Add(factory.ConstructedTypeSymbol(_type.BaseType), "Array base type");

                ArrayType arrayType = (ArrayType)_type;
                if (arrayType.IsMdArray && arrayType.Rank == 1)
                {
                    // Allocating an MDArray of Rank 1 with zero lower bounds results in allocating
                    // an SzArray instead. Make sure the type loader can find the SzArray type.
                    dependencyList.Add(factory.ConstructedTypeSymbol(arrayType.ElementType.MakeArrayType()), "Rank 1 array");
                }
            }

            dependencyList.Add(factory.VTable(closestDefType), "VTable");

            if (factory.TypeSystemContext.SupportsUniversalCanon)
            {
                foreach (var instantiationType in _type.Instantiation)
                {
                    if (instantiationType.IsValueType)
                    {
                        // All valuetype generic parameters of a constructed type may be effectively constructed. This is generally not that
                        // critical, but in the presence of universal generics the compiler may generate a Box followed by calls to ToString,
                        // GetHashcode or Equals in ways that cannot otherwise be detected by dependency analysis. Thus force all struct type
                        // generic parameters to be considered constructed when walking dependencies of a constructed generic
                        dependencyList.Add(factory.ConstructedTypeSymbol(instantiationType.ConvertToCanonForm(CanonicalFormKind.Specific)),
                                           "Struct generic parameters in constructed types may be assumed to be used as constructed in constructed generic types");
                    }
                }
            }

            // Generated type contains generic virtual methods that will get added to the GVM tables
            if (TypeGVMEntriesNode.TypeNeedsGVMTableEntries(_type))
            {
                dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type), "Type with generic virtual methods"));

                AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList);
            }

            if (factory.PreinitializationManager.HasLazyStaticConstructor(_type))
            {
                // The fact that we generated an EEType means that someone can call RuntimeHelpers.RunClassConstructor.
                // We need to make sure this is possible.
                dependencyList.Add(new DependencyListEntry(factory.TypeNonGCStaticsSymbol((MetadataType)_type), "Class constructor"));
            }

            // Ask the metadata manager if we have any dependencies due to reflectability.
            factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencyList, factory, _type);

            factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type);

            // Keep track of the default constructor map dependency for this type if it has a default constructor
            MethodDesc defaultCtor = closestDefType.GetDefaultConstructor();

            if (defaultCtor != null)
            {
                dependencyList.Add(new DependencyListEntry(
                                       factory.MethodEntrypoint(defaultCtor.GetCanonMethodTarget(CanonicalFormKind.Specific), closestDefType.IsValueType),
                                       "DefaultConstructorNode"));
            }

            return(dependencyList);
        }