From c9f5ca2f34ee05403238797276279b28a417934c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 14 Mar 2023 14:57:45 +0900 Subject: [PATCH] Do not generate relocs to empty type dictionaries (#83367) If the generic dictionary is empty, there's no legitimate reason to access it. Saves 20 kB on BasicMinimalApi. Also deleting a multimodule extensibility point that was getting in the way. We didn't use it and I don't see a future need for it either. --- .../Compiler/DependencyAnalysis/EETypeNode.cs | 14 +++++++++++++- .../ExternSymbolsImportedNodeProvider.cs | 5 ----- .../DependencyAnalysis/GenericDictionaryNode.cs | 1 + .../DependencyAnalysis/ImportedNodeProvider.cs | 6 ------ .../Compiler/DependencyAnalysis/NodeFactory.cs | 18 ++++++------------ 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index 3072018..24974d4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -960,9 +960,21 @@ namespace ILCompiler.DependencyAnalysis || implType.IsCanonicalSubtype(CanonicalFormKind.Universal) || factory.LazyGenericsPolicy.UsesLazyGenerics(declType) || isInterfaceWithAnEmptySlot) + { objData.EmitZeroPointer(); + } else - objData.EmitPointerReloc(factory.TypeGenericDictionary(declType)); + { + TypeGenericDictionaryNode dictionaryNode = factory.TypeGenericDictionary(declType); + DictionaryLayoutNode layoutNode = dictionaryNode.GetDictionaryLayout(factory); + + // Don't bother emitting a reloc to an empty dictionary. We'll only know whether the dictionary is + // empty at final object emission time, so don't ask if we're not emitting yet. + if (!relocsOnly && layoutNode.IsEmpty) + objData.EmitZeroPointer(); + else + objData.EmitPointerReloc(dictionaryNode); + } } VTableSliceNode declVTable = factory.VTable(declType); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternSymbolsImportedNodeProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternSymbolsImportedNodeProvider.cs index 2af223e..b50d07c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternSymbolsImportedNodeProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternSymbolsImportedNodeProvider.cs @@ -23,11 +23,6 @@ namespace ILCompiler.DependencyAnalysis return new ExternSymbolNode(NonGCStaticsNode.GetMangledName(type, factory.NameMangler)); } - public override ISortableSymbolNode ImportedTypeDictionaryNode(NodeFactory factory, TypeDesc type) - { - throw new NotImplementedException(); - } - public override ISortableSymbolNode ImportedMethodDictionaryNode(NodeFactory factory, MethodDesc method) { throw new NotImplementedException(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs index bcd3797..ddc8194 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs @@ -117,6 +117,7 @@ namespace ILCompiler.DependencyAnalysis public override bool HasConditionalStaticDependencies => true; + public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => GetDictionaryLayout(factory).IsEmpty; protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ImportedNodeProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ImportedNodeProvider.cs index 9433faa..a7cef89 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ImportedNodeProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ImportedNodeProvider.cs @@ -14,7 +14,6 @@ namespace ILCompiler.DependencyAnalysis public abstract IEETypeNode ImportedEETypeNode(NodeFactory factory, TypeDesc type); public abstract ISortableSymbolNode ImportedGCStaticNode(NodeFactory factory, MetadataType type); public abstract ISortableSymbolNode ImportedNonGCStaticNode(NodeFactory factory, MetadataType type); - public abstract ISortableSymbolNode ImportedTypeDictionaryNode(NodeFactory factory, TypeDesc type); public abstract ISortableSymbolNode ImportedMethodDictionaryNode(NodeFactory factory, MethodDesc method); public abstract IMethodNode ImportedMethodCodeNode(NodeFactory factory, MethodDesc method, bool unboxingStub); } @@ -36,11 +35,6 @@ namespace ILCompiler.DependencyAnalysis throw new NotSupportedException(); } - public override ISortableSymbolNode ImportedTypeDictionaryNode(NodeFactory factory, TypeDesc type) - { - throw new NotSupportedException(); - } - public override ISortableSymbolNode ImportedMethodDictionaryNode(NodeFactory factory, MethodDesc method) { throw new NotSupportedException(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index 487f25f..70713b3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -439,17 +439,11 @@ namespace ILCompiler.DependencyAnalysis } }); - _typeGenericDictionaries = new NodeCache(type => + _typeGenericDictionaries = new NodeCache(type => { - if (CompilationModuleGroup.ContainsTypeDictionary(type)) - { - Debug.Assert(!this.LazyGenericsPolicy.UsesLazyGenerics(type)); - return new TypeGenericDictionaryNode(type, this); - } - else - { - return _importedNodeProvider.ImportedTypeDictionaryNode(this, type); - } + Debug.Assert(CompilationModuleGroup.ContainsTypeDictionary(type)); + Debug.Assert(!this.LazyGenericsPolicy.UsesLazyGenerics(type)); + return new TypeGenericDictionaryNode(type, this); }); _typesWithMetadata = new NodeCache(type => @@ -847,8 +841,8 @@ namespace ILCompiler.DependencyAnalysis return _methodGenericDictionaries.GetOrAdd(method); } - private NodeCache _typeGenericDictionaries; - public ISortableSymbolNode TypeGenericDictionary(TypeDesc type) + private NodeCache _typeGenericDictionaries; + public TypeGenericDictionaryNode TypeGenericDictionary(TypeDesc type) { return _typeGenericDictionaries.GetOrAdd(type); } -- 2.7.4