diff --git a/src/coreclr/nativeaot/Runtime/AsmOffsets.h b/src/coreclr/nativeaot/Runtime/AsmOffsets.h index 616c4847235e5d..b31402f48d8413 100644 --- a/src/coreclr/nativeaot/Runtime/AsmOffsets.h +++ b/src/coreclr/nativeaot/Runtime/AsmOffsets.h @@ -46,6 +46,7 @@ ASM_CONST( 6, 6, ARM64_ATOMICS_FEATURE_FLAG_BIT) ASM_OFFSET( 0, 0, MethodTable, m_usComponentSize) ASM_OFFSET( 0, 0, MethodTable, m_uFlags) ASM_OFFSET( 4, 4, MethodTable, m_uBaseSize) +ASM_OFFSET( C, 10, MethodTable, m_usNumVtableSlots) ASM_OFFSET( 14, 18, MethodTable, m_VTable) ASM_OFFSET( 0, 0, Thread, m_eeAllocContext) diff --git a/src/coreclr/nativeaot/Runtime/MethodTable.cpp b/src/coreclr/nativeaot/Runtime/MethodTable.cpp index 60e4e595fc79ea..70b9afafb5506e 100644 --- a/src/coreclr/nativeaot/Runtime/MethodTable.cpp +++ b/src/coreclr/nativeaot/Runtime/MethodTable.cpp @@ -40,8 +40,10 @@ bool MethodTable::Validate(bool assertOnFail /* default: true */) { case CanonicalEEType: { + MethodTable* pBaseType = GetNonArrayBaseType(); + // If the parent type is NULL this had better look like Object. - if (!IsInterface() && (m_RelatedType.m_pBaseType == NULL)) + if (pBaseType == NULL) { if (IsValueType() || HasFinalizer() || @@ -51,6 +53,24 @@ bool MethodTable::Validate(bool assertOnFail /* default: true */) REPORT_FAILURE(); } } + else if (GetNumVtableSlots() == 0 + && !IsGCStaticMethodTable()) + { + // We only really expect zero vtable slots for GCStatic MethodTables, however + // to cover the unlikely case that we managed to trim out Equals/GetHashCode/ToString, + // check an invariant that says if a derived type has zero vtable slots, all bases need + // to have zero slots. + MethodTable* pCurrentType = pBaseType; + do + { + if (pCurrentType->GetNumVtableSlots() > GetNumVtableSlots()) + { + REPORT_FAILURE(); + } + pCurrentType = pCurrentType->GetNonArrayBaseType(); + } + while (pCurrentType != NULL); + } break; } @@ -59,7 +79,8 @@ bool MethodTable::Validate(bool assertOnFail /* default: true */) // The only parameter EETypes that can exist on the heap are arrays // Array types must have a related type. - if (m_RelatedType.m_pRelatedParameterType == NULL) + MethodTable* pParameterType = GetRelatedParameterType(); + if (pParameterType == NULL) REPORT_FAILURE(); // Component size cannot be zero in this case. @@ -73,6 +94,38 @@ bool MethodTable::Validate(bool assertOnFail /* default: true */) REPORT_FAILURE(); } + // Zero vtable slots is suspicious. To cover the unlikely case that we managed to trim + // out Equals/GetHashCode/ToString, compare with number of slots of Object class. + if (GetNumVtableSlots() == 0) + { + // Drill into the type to find System.Object + + MethodTable* pCurrentType = pParameterType; + + while (pCurrentType->IsParameterizedType()) + pCurrentType = pCurrentType->GetRelatedParameterType(); + + // We don't have facilities to unwrap function pointers, so just skip for now. + // We won't get System.Object from interfaces, skip too. + if (!pCurrentType->IsFunctionPointer() && !pCurrentType->IsInterface()) + { + do + { + MethodTable* pBaseType = pCurrentType->GetNonArrayBaseType(); + if (pBaseType == NULL) + { + // Found System.Object, now compare number of slots + if (pCurrentType->GetNumVtableSlots() > GetNumVtableSlots()) + { + REPORT_FAILURE(); + } + } + + pCurrentType = pBaseType; + } while (pCurrentType != NULL); + } + } + break; } diff --git a/src/coreclr/nativeaot/Runtime/eventtrace_bulktype.cpp b/src/coreclr/nativeaot/Runtime/eventtrace_bulktype.cpp index 31d0d43aadbdf2..f21b502a7b606a 100644 --- a/src/coreclr/nativeaot/Runtime/eventtrace_bulktype.cpp +++ b/src/coreclr/nativeaot/Runtime/eventtrace_bulktype.cpp @@ -283,9 +283,9 @@ int BulkTypeEventLogger::LogSingleType(MethodTable * pEEType) // Determine this MethodTable's module. RuntimeInstance * pRuntimeInstance = GetRuntimeInstance(); - // EEType for GC statics are not fully populated and they do not have a valid TypeManager. We will identify them by checking for `ElementType_Unknown`. + // EEType for GC statics are not fully populated and they do not have a valid TypeManager. ULONGLONG osModuleHandle = 0; - if (pEEType->GetElementType() != ElementType_Unknown) + if (!pEEType->IsGCStaticMethodTable()) { osModuleHandle = (ULONGLONG) pEEType->GetTypeManagerPtr()->AsTypeManager()->GetOsModuleHandle(); } diff --git a/src/coreclr/nativeaot/Runtime/inc/MethodTable.h b/src/coreclr/nativeaot/Runtime/inc/MethodTable.h index 89ff445f6174d9..0e8b6929c6c31c 100644 --- a/src/coreclr/nativeaot/Runtime/inc/MethodTable.h +++ b/src/coreclr/nativeaot/Runtime/inc/MethodTable.h @@ -205,6 +205,11 @@ class MethodTable Kinds GetKind(); + bool IsGCStaticMethodTable() + { + return GetElementType() == ElementType_Unknown; + } + bool IsArray() { EETypeElementType elementType = GetElementType(); diff --git a/src/coreclr/runtime/amd64/AllocFast.S b/src/coreclr/runtime/amd64/AllocFast.S index 02091bea31083e..4fa6638ed5f09e 100644 --- a/src/coreclr/runtime/amd64/AllocFast.S +++ b/src/coreclr/runtime/amd64/AllocFast.S @@ -12,6 +12,18 @@ LEAF_ENTRY RhpNewFast, _TEXT push_nonvol_reg rbx mov rbx, rdi +#ifdef FEATURE_NATIVEAOT + mov ax, [rdi + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz LOCAL_LABEL(RhpNewFast_ValidMethodTable) + mov eax, [rdi] + and eax, 0x7C000000 + jz LOCAL_LABEL(RhpNewFast_ValidMethodTable) + int 3 +LOCAL_LABEL(RhpNewFast_ValidMethodTable): +#endif + + // rax = ee_alloc_context pointer; trashes volatile registers INLINE_GET_ALLOC_CONTEXT_BASE @@ -81,6 +93,17 @@ NESTED_ENTRY RhpNewObject, _TEXT, NoHandler // RCX: transition frame +#ifdef FEATURE_NATIVEAOT + mov ax, [rdi + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz LOCAL_LABEL(RhpNewObject_ValidMethodTable) + mov eax, [rdi] + and eax, 0x7C000000 + jz LOCAL_LABEL(RhpNewObject_ValidMethodTable) + int 3 +LOCAL_LABEL(RhpNewObject_ValidMethodTable): +#endif + // Preserve the MethodTable in RBX mov rbx, rdi @@ -176,6 +199,14 @@ NESTED_END RhpNewObject, _TEXT // RSI == character/element count LEAF_ENTRY RhNewString, _TEXT +#ifdef FEATURE_NATIVEAOT + mov ax, [rdi + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz LOCAL_LABEL(RhNewString_ValidMethodTable) + int 3 +LOCAL_LABEL(RhNewString_ValidMethodTable): +#endif + // we want to limit the element count to the non-negative 32-bit int range cmp rsi, MAX_STRING_LENGTH ja LOCAL_LABEL(StringSizeOverflow) @@ -203,6 +234,14 @@ LEAF_END RhNewString, _TEXT // ESI == element count LEAF_ENTRY RhpNewArrayFast, _TEXT +#ifdef FEATURE_NATIVEAOT + mov ax, [rdi + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz LOCAL_LABEL(RhpNewArrayFast_ValidMethodTable) + int 3 +LOCAL_LABEL(RhpNewArrayFast_ValidMethodTable): +#endif + // we want to limit the element count to the non-negative 32-bit int range cmp rsi, 0x07fffffff ja LOCAL_LABEL(ArraySizeOverflow) @@ -232,6 +271,14 @@ LEAF_END RhpNewArrayFast, _TEXT // ESI == element count LEAF_ENTRY RhpNewPtrArrayFast, _TEXT +#ifdef FEATURE_NATIVEAOT + mov ax, [rdi + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz LOCAL_LABEL(RhpNewPtrArrayFast_ValidMethodTable) + int 3 +LOCAL_LABEL(RhpNewPtrArrayFast_ValidMethodTable): +#endif + // Delegate overflow handling to the generic helper conservatively // The constant 0x8000000 is (0x40000000 / sizeof(void*)) // Some assemblers don't like an expression here, so the @@ -261,6 +308,14 @@ NESTED_ENTRY RhpNewVariableSizeObject, _TEXT, NoHandler PUSH_COOP_PINVOKE_FRAME rcx +#ifdef FEATURE_NATIVEAOT + mov ax, [rdi + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz LOCAL_LABEL(RhpNewVariableSizeObject_ValidMethodTable) + int 3 +LOCAL_LABEL(RhpNewVariableSizeObject_ValidMethodTable): +#endif + // rcx: transition frame // Preserve the MethodTable in RBX diff --git a/src/coreclr/runtime/amd64/AllocFast.asm b/src/coreclr/runtime/amd64/AllocFast.asm index cda88f3bf8f1ec..2116bb6914d536 100644 --- a/src/coreclr/runtime/amd64/AllocFast.asm +++ b/src/coreclr/runtime/amd64/AllocFast.asm @@ -9,6 +9,17 @@ include AsmMacros_Shared.inc ;; RCX == MethodTable LEAF_ENTRY RhpNewFast, _TEXT +ifdef FEATURE_NATIVEAOT + mov ax, [rcx + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz RhpNewFast_ValidMethodTable + mov eax, [rcx] + and eax, 7C000000h + jz RhpNewFast_ValidMethodTable + int 3 +RhpNewFast_ValidMethodTable: +endif + ;; rdx = ee_alloc_context pointer, TRASHES rax INLINE_GET_ALLOC_CONTEXT_BASE rdx, rax @@ -66,6 +77,17 @@ NESTED_ENTRY RhpNewObject, _TEXT ; R9: transition frame +ifdef FEATURE_NATIVEAOT + mov ax, [rcx + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz RhpNewObject_ValidMethodTable + mov eax, [rcx] + and eax, 7C000000h + jz RhpNewObject_ValidMethodTable + int 3 +RhpNewObject_ValidMethodTable: +endif + ;; Preserve the MethodTable in RSI mov rsi, rcx @@ -131,6 +153,15 @@ ENDM ; NEW_ARRAY_FAST ;; RDX == character/element count LEAF_ENTRY RhNewString, _TEXT +ifdef FEATURE_NATIVEAOT + mov ax, [rcx + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz RhNewString_ValidMethodTable + int 3 +RhNewString_ValidMethodTable: +endif + + ; we want to limit the element count to the non-negative 32-bit int range cmp rdx, MAX_STRING_LENGTH ja StringSizeOverflow @@ -158,6 +189,14 @@ LEAF_END RhNewString, _TEXT ;; EDX == element count LEAF_ENTRY RhpNewArrayFast, _TEXT +ifdef FEATURE_NATIVEAOT + mov ax, [rcx + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz RhpNewArrayFast_ValidMethodTable + int 3 +RhpNewArrayFast_ValidMethodTable: +endif + ; we want to limit the element count to the non-negative 32-bit int range cmp rdx, 07fffffffh ja ArraySizeOverflow @@ -187,6 +226,14 @@ LEAF_END RhpNewArrayFast, _TEXT ;; EDX == element count LEAF_ENTRY RhpNewPtrArrayFast, _TEXT +ifdef FEATURE_NATIVEAOT + mov ax, [rcx + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz RhpNewPtrArrayFast_ValidMethodTable + int 3 +RhpNewPtrArrayFast_ValidMethodTable: +endif + ; Delegate overflow handling to the generic helper conservatively cmp rdx, (40000000h / 8) ; sizeof(void*) @@ -213,6 +260,14 @@ NESTED_ENTRY RhpNewVariableSizeObject, _TEXT PUSH_COOP_PINVOKE_FRAME r9 +ifdef FEATURE_NATIVEAOT + mov ax, [rcx + OFFSETOF__MethodTable__m_usNumVtableSlots] + test ax, ax + jnz RhpNewVariableSizeObject_ValidMethodTable + int 3 +RhpNewVariableSizeObject_ValidMethodTable: +endif + ; r9: transition frame ; Preserve the MethodTable in RSI diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs index c57f8ad072c233..3df053b694850e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs @@ -328,7 +328,20 @@ public NativeLayoutParameterizedTypeSignatureVertexNode(NodeFactory factory, Typ } public override IEnumerable GetStaticDependencies(NodeFactory context) { - return new DependencyListEntry[] { new DependencyListEntry(_parameterTypeSig, "NativeLayoutParameterizedTypeSignatureVertexNode parameter type signature") }; + if (!_type.ContainsSignatureVariables()) + { + if (_type.IsRuntimeDeterminedSubtype) + { + if (GenericTypesTemplateMap.IsArrayTypeEligibleForTemplate(_type)) + yield return new DependencyListEntry(context.NativeLayout.TemplateTypeLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Array template"); + } + else + { + yield return new DependencyListEntry(context.NecessaryTypeSymbol(_type), "Non-shared array"); + } + } + + yield return new DependencyListEntry(_parameterTypeSig, "NativeLayoutParameterizedTypeSignatureVertexNode parameter type signature"); } public override Vertex WriteVertex(NodeFactory factory) { @@ -428,6 +441,18 @@ public override IEnumerable GetStaticDependencies(NodeFacto { DependencyList dependencies = new DependencyList(); + if (!_type.ContainsSignatureVariables()) + { + if (_type.IsRuntimeDeterminedSubtype) + { + dependencies.Add(context.NativeLayout.TemplateTypeLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Generic type template"); + } + else + { + dependencies.Add(context.NecessaryTypeSymbol(_type), "Non-shared generic type"); + } + } + dependencies.Add(new DependencyListEntry(_genericTypeDefSig, "NativeLayoutInstantiatedTypeSignatureVertexNode generic definition signature")); foreach (var arg in _instantiationArgs) dependencies.Add(new DependencyListEntry(arg, "NativeLayoutInstantiatedTypeSignatureVertexNode instantiation argument signature")); @@ -650,27 +675,6 @@ protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory) IMethodNode methodEntryPointNode = factory.AddressTakenMethodEntrypoint(_method, IsUnboxingStub); return methodEntryPointNode; } - - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - DependencyList dependencies = (DependencyList)base.GetStaticDependencies(context); - - foreach (var arg in _method.Instantiation) - { - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(arg)) - { - dependencies.Add(new DependencyListEntry(dependency, "Dependencies to make a generic method template viable Method Instantiation")); - } - } - - - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_method.OwningType)) - { - dependencies.Add(new DependencyListEntry(dependency, "Dependencies to make a generic method template viable OwningType")); - } - - return dependencies; - } } public sealed class NativeLayoutDictionarySignatureNode : NativeLayoutSavedVertexNode @@ -788,19 +792,6 @@ public NativeLayoutTemplateMethodLayoutVertexNode(NodeFactory factory, MethodDes public override IEnumerable GetStaticDependencies(NodeFactory context) { - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_method.OwningType)) - { - yield return new DependencyListEntry(dependency, "method OwningType itself must be template loadable"); - } - - foreach (var type in _method.Instantiation) - { - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(type)) - { - yield return new DependencyListEntry(dependency, "method's instantiation arguments must be template loadable"); - } - } - foreach (GenericParameterDesc genericParam in _method.GetTypicalMethodDefinition().Instantiation) { foreach (TypeDesc typeConstraint in genericParam.TypeConstraints) @@ -905,23 +896,8 @@ public override IEnumerable GetStaticDependencies(NodeFacto yield return new DependencyListEntry(typeNode, "Template MethodTable"); - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_type)) - { - yield return new DependencyListEntry(dependency, "type itslef must be template loadable"); - } - yield return new DependencyListEntry(context.GenericDictionaryLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific).GetClosestDefType()), "Dictionary layout"); - foreach (TypeDesc iface in _type.RuntimeInterfaces) - { - yield return new DependencyListEntry(context.NativeLayout.TypeSignatureVertex(iface), "template interface list"); - - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(iface)) - { - yield return new DependencyListEntry(dependency, "interface type dependency must be template loadable"); - } - } - if (context.PreinitializationManager.HasLazyStaticConstructor(_type.ConvertToCanonForm(CanonicalFormKind.Specific))) { yield return new DependencyListEntry(context.MethodEntrypoint(_type.GetStaticConstructor().GetCanonMethodTarget(CanonicalFormKind.Specific)), "cctor for template"); @@ -960,16 +936,17 @@ public override IEnumerable GetStaticDependencies(NodeFacto if (_type.BaseType != null && _type.BaseType.IsRuntimeDeterminedSubtype) { yield return new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(_type.BaseType)), "template base type"); - - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_type.BaseType)) - { - yield return new DependencyListEntry(dependency, "base type must be template loadable"); - } } } - public override bool HasConditionalStaticDependencies => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; + public override bool HasConditionalStaticDependencies => _type.RuntimeInterfaces.Length > 0; + public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + { + foreach (TypeDesc iface in _type.RuntimeInterfaces) + { + yield return new CombinedDependencyListEntry(factory.NativeLayout.TypeSignatureVertex(iface), factory.InterfaceUse(iface.GetTypeDefinition()), "template interface list"); + } + } private static int CompareDictionaryEntries(KeyValuePair left, KeyValuePair right) { @@ -992,11 +969,16 @@ public override Vertex WriteVertex(NodeFactory factory) foreach (TypeDesc iface in _type.RuntimeInterfaces) { - implementedInterfacesList.Add(factory.NativeLayout.TypeSignatureVertex(iface)); + if (factory.InterfaceUse(iface.GetTypeDefinition()).Marked) + implementedInterfacesList.Add(factory.NativeLayout.TypeSignatureVertex(iface)); } - NativeLayoutPlacedVertexSequenceVertexNode implementedInterfaces = factory.NativeLayout.PlacedVertexSequence(implementedInterfacesList); - layoutInfo.Append(BagElementKind.ImplementedInterfaces, implementedInterfaces.WriteVertex(factory)); + if (implementedInterfacesList.Count > 0) + { + NativeLayoutPlacedVertexSequenceVertexNode implementedInterfaces = factory.NativeLayout.PlacedVertexSequence(implementedInterfacesList); + + layoutInfo.Append(BagElementKind.ImplementedInterfaces, implementedInterfaces.WriteVertex(factory)); + } } if (!factory.LazyGenericsPolicy.UsesLazyGenerics(_type) && templateLayout.Count > 0) @@ -1103,6 +1085,7 @@ public abstract class NativeLayoutTypeSignatureBasedGenericDictionarySlotNode : public NativeLayoutTypeSignatureBasedGenericDictionarySlotNode(NodeFactory factory, TypeDesc type) { + Debug.Assert(type.IsRuntimeDeterminedSubtype); _signature = factory.NativeLayout.TypeSignatureVertex(type); _type = type; } @@ -1113,11 +1096,6 @@ public NativeLayoutTypeSignatureBasedGenericDictionarySlotNode(NodeFactory facto public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) { yield return new DependencyListEntry(_signature, "TypeSignature"); - - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_type)) - { - yield return new DependencyListEntry(dependency, "template construction dependency"); - } } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1202,10 +1180,7 @@ public sealed override IEnumerable GetStaticDependencies(No { yield return new DependencyListEntry(_signature, "TypeSignature"); - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_type)) - { - yield return new DependencyListEntry(dependency, "template construction dependency"); - } + yield return new DependencyListEntry(factory.NativeLayout.TemplateTypeLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Template"); } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1239,6 +1214,7 @@ public sealed class NativeLayoutInterfaceDispatchGenericDictionarySlotNode : Nat public NativeLayoutInterfaceDispatchGenericDictionarySlotNode(NodeFactory factory, MethodDesc method) { + Debug.Assert(method.IsRuntimeDeterminedExactMethod); _signature = factory.NativeLayout.TypeSignatureVertex(method.OwningType); _method = method; } @@ -1250,18 +1226,11 @@ public sealed override IEnumerable GetStaticDependencies(No { yield return new DependencyListEntry(_signature, "TypeSignature"); - MethodDesc method = _method; - if (method.IsRuntimeDeterminedExactMethod) - method = method.GetCanonMethodTarget(CanonicalFormKind.Specific); - - if (!factory.VTable(method.OwningType).HasKnownVirtualMethodUse) - { - yield return new DependencyListEntry(factory.VirtualMethodUse(method), "Slot number"); - } + MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Specific); - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(method.OwningType)) + if (!factory.VTable(canonMethod.OwningType).HasKnownVirtualMethodUse) { - yield return new DependencyListEntry(dependency, "template construction dependency"); + yield return new DependencyListEntry(factory.VirtualMethodUse(canonMethod), "Slot number"); } } @@ -1293,17 +1262,6 @@ public sealed override IEnumerable GetStaticDependencies(No { var dependencies = new DependencyList(); - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) - { - dependencies.Add(dependency, "template construction dependency for method OwningType"); - } - - foreach (var type in _method.Instantiation) - { - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type)) - dependencies.Add(dependency, "template construction dependency for method Instantiation types"); - } - GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); dependencies.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); @@ -1338,11 +1296,6 @@ public sealed override IEnumerable GetStaticDependencies(No { factory.NativeLayout.TypeSignatureVertex(_field.OwningType), "Owning type of field" } }; - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_field.OwningType)) - { - result.Add(dependency, "template construction dependency"); - } - var canonOwningType = (InstantiatedType)_field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); FieldDesc canonField = factory.TypeSystemContext.GetFieldForInstantiatedType(_field.GetTypicalFieldDefinition(), canonOwningType); factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, canonField); @@ -1377,17 +1330,6 @@ public sealed override IEnumerable GetStaticDependencies(No { var result = new DependencyList(); - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) - { - result.Add(dependency, "template construction dependency for method OwningType"); - } - - foreach (var type in _method.Instantiation) - { - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type)) - result.Add(dependency, "template construction dependency for method Instantiation types"); - } - factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); result.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); @@ -1452,20 +1394,6 @@ public sealed override IEnumerable GetStaticDependencies(No yield return new DependencyListEntry(constrainedMethodDescriptorNode, "ConstrainedMethodType"); - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constrainedMethod.OwningType)) - { - yield return new DependencyListEntry(dependency, "template construction dependency constrainedMethod OwningType"); - } - - foreach (var type in _constrainedMethod.Instantiation) - { - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type)) - yield return new DependencyListEntry(dependency, "template construction dependency constrainedMethod Instantiation type"); - } - - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constraintType)) - yield return new DependencyListEntry(dependency, "template construction dependency constraintType"); - if (_constrainedMethod.IsVirtual && _constrainedMethod.HasInstantiation) { MethodDesc canonMethod = _constrainedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); @@ -1534,17 +1462,6 @@ public sealed override IEnumerable GetStaticDependencies(No { DependencyList dependencies = new DependencyList(); - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) - { - dependencies.Add(dependency, "template construction dependency for method OwningType"); - } - - foreach (var type in _method.Instantiation) - { - foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type)) - dependencies.Add(dependency, "template construction dependency for method Instantiation types"); - } - GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); dependencies.Add(_wrappedNode, "wrappednode"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs index 5918b71a451b34..4d74a095b6ecda 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs @@ -143,63 +143,6 @@ private void CreateNodeCaches() }); } - // Produce a set of dependencies that is necessary such that if this type - // needs to be used referenced from a NativeLayout template, that the template - // will be properly constructable. (This is done by ensuring that all - // canonical types in the deconstruction of the type are ConstructedEEType instead - // of just necessary. (Which is what the actual templates signatures will ensure) - public IEnumerable TemplateConstructableTypes(TypeDesc type) - { - // Array types are the only parameterized types that have templates - if (type.IsSzArray && !type.IsArrayTypeWithoutGenericInterfaces()) - { - TypeDesc arrayCanonicalType = type.ConvertToCanonForm(CanonicalFormKind.Specific); - - // Add a dependency on the template for this type, if the canonical type should be generated into this binary. - if (arrayCanonicalType.IsCanonicalSubtype(CanonicalFormKind.Any) && !_factory.NecessaryTypeSymbol(arrayCanonicalType).RepresentsIndirectionCell) - { - yield return _factory.NativeLayout.TemplateTypeLayout(arrayCanonicalType); - } - - yield return _factory.MaximallyConstructableType(arrayCanonicalType); - } - - while (type.IsParameterizedType) - { - type = ((ParameterizedType)type).ParameterType; - } - - if (type.IsFunctionPointer) - { - MethodSignature sig = ((FunctionPointerType)type).Signature; - foreach (var dependency in TemplateConstructableTypes(sig.ReturnType)) - yield return dependency; - - foreach (var param in sig) - foreach (var dependency in TemplateConstructableTypes(param)) - yield return dependency; - - // Nothing else to do for function pointers - yield break; - } - - TypeDesc canonicalType = type.ConvertToCanonForm(CanonicalFormKind.Specific); - yield return _factory.MaximallyConstructableType(canonicalType); - - // Add a dependency on the template for this type, if the canonical type should be generated into this binary. - if (canonicalType.IsCanonicalSubtype(CanonicalFormKind.Any) && !_factory.NecessaryTypeSymbol(canonicalType).RepresentsIndirectionCell) - { - if (!_factory.TypeSystemContext.IsCanonicalDefinitionType(canonicalType, CanonicalFormKind.Any)) - yield return _factory.NativeLayout.TemplateTypeLayout(canonicalType); - } - - foreach (TypeDesc instantiationType in type.Instantiation) - { - foreach (var dependency in TemplateConstructableTypes(instantiationType)) - yield return dependency; - } - } - private NodeCache _typeSignatures; internal NativeLayoutTypeSignatureVertexNode TypeSignatureVertex(TypeDesc type) { diff --git a/src/libraries/System.Linq.Expressions/tests/AssemblyInfo.cs b/src/libraries/System.Linq.Expressions/tests/AssemblyInfo.cs index b3954f21c16df4..5e6be3f2923350 100644 --- a/src/libraries/System.Linq.Expressions/tests/AssemblyInfo.cs +++ b/src/libraries/System.Linq.Expressions/tests/AssemblyInfo.cs @@ -3,4 +3,4 @@ using Xunit; -[assembly: SkipOnCoreClr("Long running tests: https://github.com/dotnet/runtime/issues/12927", ~RuntimeConfiguration.Release)] +//[assembly: SkipOnCoreClr("Long running tests: https://github.com/dotnet/runtime/issues/12927", ~RuntimeConfiguration.Release)] diff --git a/src/tests/nativeaot/SmokeTests/DynamicGenerics/TypeOfRepo.cs b/src/tests/nativeaot/SmokeTests/DynamicGenerics/TypeOfRepo.cs index 160df9bf78e2c1..3a33614ac6595b 100644 --- a/src/tests/nativeaot/SmokeTests/DynamicGenerics/TypeOfRepo.cs +++ b/src/tests/nativeaot/SmokeTests/DynamicGenerics/TypeOfRepo.cs @@ -194,8 +194,6 @@ static TypeOf() s_TypeRepo["D_IFace"] = typeof(Dictionaries.IFace<>); s_TypeRepo["D_IFace3"] = typeof(Dictionaries.IFace3<>); s_TypeRepo["D_SingleUseArrayOnlyGen"] = typeof(Dictionaries.SingleUseArrayOnlyGen<>); - s_TypeRepo["D_GenericStruct"] = typeof(Dictionaries.GenericStruct<>); - s_TypeRepo["D_NullableTest"] = typeof(Dictionaries.NullableTest<>); s_TypeRepo["D_DelegateTarget"] = typeof(Dictionaries.DelegateTarget<>); s_TypeRepo["D_DelWithNullable"] = typeof(Dictionaries.DelWithNullable<>); @@ -448,8 +446,6 @@ static TypeOf() public static Type D_IFace { get { return s_TypeRepo["D_IFace"]; } } public static Type D_IFace3 { get { return s_TypeRepo["D_IFace3"]; } } public static Type D_SingleUseArrayOnlyGen { get { return s_TypeRepo["D_SingleUseArrayOnlyGen"]; } } - public static Type D_GenericStruct { get { return s_TypeRepo["D_GenericStruct"]; } } - public static Type D_NullableTest { get { return s_TypeRepo["D_NullableTest"]; } } public static Type D_DelegateTarget { get { return s_TypeRepo["D_DelegateTarget"]; } } public static Type D_DelWithNullable { get { return s_TypeRepo["D_DelWithNullable"]; } } public static Type TDT_MyStruct { get { return s_TypeRepo["TDT_MyStruct"]; } } diff --git a/src/tests/nativeaot/SmokeTests/DynamicGenerics/dictionaries.cs b/src/tests/nativeaot/SmokeTests/DynamicGenerics/dictionaries.cs index 6355dfc903ff92..cbc9cdd31bcbe5 100644 --- a/src/tests/nativeaot/SmokeTests/DynamicGenerics/dictionaries.cs +++ b/src/tests/nativeaot/SmokeTests/DynamicGenerics/dictionaries.cs @@ -349,12 +349,12 @@ public static void NullableTesting() } static void NullableTesting_Inner(Type arg1, Type arg2) { - var structOf = TypeOf.D_GenericStruct.MakeGenericType(arg1); + var structOf = typeof(GenericStruct<>).MakeGenericType(arg1); - var structInst1 = Activator.CreateInstance(TypeOf.D_GenericStruct.MakeGenericType(arg1)); - var structInst2 = Activator.CreateInstance(TypeOf.D_GenericStruct.MakeGenericType(arg2)); + var structInst1 = Activator.CreateInstance(typeof(GenericStruct<>).MakeGenericType(arg1)); + var structInst2 = Activator.CreateInstance(typeof(GenericStruct<>).MakeGenericType(arg2)); - var nullableTestOf = TypeOf.D_NullableTest.MakeGenericType(structOf); + var nullableTestOf = typeof(NullableTest<>).MakeGenericType(structOf); Base test = (Base)Activator.CreateInstance(nullableTestOf); // Type cast T -> T?