Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2017-06-13 22:33:28 +0300
committerGitHub <noreply@github.com>2017-06-13 22:33:28 +0300
commitf34e790055e0f44fc635690eec5cab56f57c6641 (patch)
tree962dc52e4879e46b6e32996a4ccd2a4ebb3cf11d
parent61b5b72107de609d0ea55375f47f8a7c23902496 (diff)
parent1f3d243d7b39c53e6bfb3cc81a25227d1b0dfb2e (diff)
Merge pull request #3869 from MichalStrehovsky/nmirrorMerge
Merge master to nmirror
-rw-r--r--src/Common/src/TypeSystem/Common/MethodDesc.cs1
-rw-r--r--src/Common/src/TypeSystem/Ecma/EcmaSignatureParser.cs5
-rw-r--r--src/Common/src/TypeSystem/IL/DelegateInfo.cs26
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/Compilation.cs5
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs7
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs96
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs22
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs5
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs12
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs23
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs1
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs5
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs27
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs106
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/ILScanner.cs29
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/LibraryRootProvider.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/VTableSliceProvider.cs28
-rw-r--r--src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs32
-rw-r--r--src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj1
-rw-r--r--src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs2
-rw-r--r--src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs5
-rw-r--r--src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs2
-rw-r--r--src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs1
-rw-r--r--src/JitInterface/src/CorInfoImpl.cs118
-rw-r--r--src/JitInterface/src/CorInfoTypes.cs4
-rw-r--r--src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs5
-rw-r--r--src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj1
-rw-r--r--src/packaging/packages.targets2
-rw-r--r--src/packaging/ryujit/project.json2
-rw-r--r--tests/src/Simple/Generics/Generics.cs3
39 files changed, 337 insertions, 270 deletions
diff --git a/src/Common/src/TypeSystem/Common/MethodDesc.cs b/src/Common/src/TypeSystem/Common/MethodDesc.cs
index 44dca5049..fcab153bb 100644
--- a/src/Common/src/TypeSystem/Common/MethodDesc.cs
+++ b/src/Common/src/TypeSystem/Common/MethodDesc.cs
@@ -19,6 +19,7 @@ namespace Internal.TypeSystem
UnmanagedCallingConventionCdecl = 0x0001,
UnmanagedCallingConventionStdCall = 0x0002,
UnmanagedCallingConventionThisCall = 0x0003,
+ CallingConventionVarargs = 0x0005,
Static = 0x0010,
}
diff --git a/src/Common/src/TypeSystem/Ecma/EcmaSignatureParser.cs b/src/Common/src/TypeSystem/Ecma/EcmaSignatureParser.cs
index 749f1ca22..74d604347 100644
--- a/src/Common/src/TypeSystem/Ecma/EcmaSignatureParser.cs
+++ b/src/Common/src/TypeSystem/Ecma/EcmaSignatureParser.cs
@@ -169,10 +169,7 @@ namespace Internal.TypeSystem.Ecma
Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)SignatureCallingConvention.CDecl);
Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)SignatureCallingConvention.StdCall);
Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)SignatureCallingConvention.ThisCall);
-
- // Vararg methods are not supported in .NET Core
- if (signatureCallConv == SignatureCallingConvention.VarArgs)
- throw new TypeSystemException.BadImageFormatException();
+ Debug.Assert((int)MethodSignatureFlags.CallingConventionVarargs == (int)SignatureCallingConvention.VarArgs);
flags = (MethodSignatureFlags)signatureCallConv;
}
diff --git a/src/Common/src/TypeSystem/IL/DelegateInfo.cs b/src/Common/src/TypeSystem/IL/DelegateInfo.cs
index fd3227729..bcf1f2afe 100644
--- a/src/Common/src/TypeSystem/IL/DelegateInfo.cs
+++ b/src/Common/src/TypeSystem/IL/DelegateInfo.cs
@@ -119,12 +119,30 @@ namespace Internal.IL
{
TypeDesc firstParam = delegateSignature[0];
- bool generateOpenInstanceMethod = true;
+ bool generateOpenInstanceMethod;
- if (firstParam.IsValueType ||
- (!firstParam.IsDefType && !firstParam.IsSignatureVariable) /* no arrays, pointers, byrefs, etc. */)
+ switch (firstParam.Category)
{
- generateOpenInstanceMethod = false;
+ case TypeFlags.Pointer:
+ case TypeFlags.FunctionPointer:
+ generateOpenInstanceMethod = false;
+ break;
+
+ case TypeFlags.ByRef:
+ firstParam = ((ByRefType)firstParam).ParameterType;
+ generateOpenInstanceMethod = firstParam.IsSignatureVariable || firstParam.IsValueType;
+ break;
+
+ case TypeFlags.Array:
+ case TypeFlags.SzArray:
+ case TypeFlags.SignatureTypeVariable:
+ generateOpenInstanceMethod = true;
+ break;
+
+ default:
+ Debug.Assert(firstParam.IsDefType);
+ generateOpenInstanceMethod = !firstParam.IsValueType;
+ break;
}
if (generateOpenInstanceMethod)
diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
index a9770431a..2d69417b1 100644
--- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
@@ -176,6 +176,11 @@ namespace ILCompiler
return intrinsicMethod;
}
+ public bool HasFixedSlotVTable(TypeDesc type)
+ {
+ return NodeFactory.VTable(type).HasFixedSlots;
+ }
+
void ICompilation.Compile(string outputFile, ObjectDumper dumper)
{
if (dumper != null)
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs
index 838606a9d..6a8df8d8f 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs
@@ -24,6 +24,7 @@ namespace ILCompiler
protected OptimizationMode _optimizationMode = OptimizationMode.None;
protected bool _generateDebugInfo = false;
protected MetadataManager _metadataManager;
+ protected VTableSliceProvider _vtableSliceProvider = new LazyVTableSliceProvider();
public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler)
{
@@ -63,6 +64,12 @@ namespace ILCompiler
return this;
}
+ public CompilationBuilder UseVTableSliceProvider(VTableSliceProvider provider)
+ {
+ _vtableSliceProvider = provider;
+ return this;
+ }
+
public CompilationBuilder UseDebugInfo(bool generateDebugInfo)
{
_generateDebugInfo = generateDebugInfo;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs b/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs
index eb69b1146..005af801a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs
@@ -96,7 +96,7 @@ namespace ILCompiler
return factory.GenericLookup.MethodEntry(TargetMethod, TargetMethodIsUnboxingThunk);
case TargetKind.InterfaceDispatch:
- return factory.GenericLookup.VirtualMethodAddress(TargetMethod);
+ return factory.GenericLookup.VirtualCall(TargetMethod);
case TargetKind.MethodHandle:
return factory.GenericLookup.MethodHandle(TargetMethod);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
index 3d1378efe..ad73f0a6f 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
@@ -48,7 +48,7 @@ namespace ILCompiler.DependencyAnalysis
if (_type.RuntimeInterfaces.Length > 0)
dependencyList.Add(factory.InterfaceDispatchMap(_type), "Canonical interface dispatch map");
- dependencyList.Add(factory.VTable(_type), "VTable");
+ dependencyList.Add(factory.VTable(closestDefType), "VTable");
if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal))
dependencyList.Add(factory.NativeLayout.TemplateTypeLayout(_type), "Universal generic types always have template layout");
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
index e7889f2aa..1106bea0b 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
@@ -66,7 +66,7 @@ namespace ILCompiler.DependencyAnalysis
}
}
- dependencyList.Add(factory.VTable(_type), "VTable");
+ dependencyList.Add(factory.VTable(closestDefType), "VTable");
if (closestDefType.HasInstantiation)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
index 979868dd2..e88e44806 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
@@ -231,10 +231,10 @@ namespace ILCompiler.DependencyAnalysis
private void AddVirtualMethodUseDependencies(DependencyList dependencyList, NodeFactory factory)
{
- if (_type.RuntimeInterfaces.Length > 0 && !factory.VTable(_type).HasFixedSlots)
- {
- DefType closestDefType = _type.GetClosestDefType();
+ DefType closestDefType = _type.GetClosestDefType();
+ if (_type.RuntimeInterfaces.Length > 0 && !factory.VTable(closestDefType).HasFixedSlots)
+ {
foreach (var implementedInterface in _type.RuntimeInterfaces)
{
// If the type implements ICastable, the methods are implicitly necessary
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
index 05d2bb9e7..6b8765c10 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
@@ -610,7 +610,7 @@ namespace ILCompiler.DependencyAnalysis
if (factory.Target.Abi == TargetAbi.CoreRT)
{
MethodDesc instantiatedMethod = _method.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
- return factory.ReadyToRunHelper(ReadyToRunHelperId.VirtualCall, instantiatedMethod);
+ return factory.InterfaceDispatchCell(instantiatedMethod);
}
else
{
@@ -629,27 +629,12 @@ namespace ILCompiler.DependencyAnalysis
public override NativeLayoutVertexNode TemplateDictionaryNode(NodeFactory factory)
{
- if (factory.Target.Abi == TargetAbi.CoreRT)
- {
- return factory.NativeLayout.NotSupportedDictionarySlot;
- }
- else
- {
- return factory.NativeLayout.InterfaceCellDictionarySlot(_method);
- }
+ return factory.NativeLayout.InterfaceCellDictionarySlot(_method);
}
public override void WriteDictionaryTocData(NodeFactory factory, IGenericLookupResultTocWriter writer)
{
- if (factory.Target.Abi == TargetAbi.CoreRT)
- {
- // TODO
- throw new NotImplementedException();
- }
- else
- {
- writer.WriteData(LookupResultReferenceType(factory), LookupResultType.InterfaceDispatchCell, _method);
- }
+ writer.WriteData(LookupResultReferenceType(factory), LookupResultType.InterfaceDispatchCell, _method);
}
protected override int CompareToImpl(GenericLookupResult other, TypeSystemComparer comparer)
@@ -659,81 +644,6 @@ namespace ILCompiler.DependencyAnalysis
}
/// <summary>
- /// Generic lookup result that points to a virtual function address load stub.
- /// </summary>
- internal sealed class VirtualResolveGenericLookupResult : GenericLookupResult
- {
- private MethodDesc _method;
-
- protected override int ClassCode => -12619218;
-
- public VirtualResolveGenericLookupResult(MethodDesc method)
- {
- Debug.Assert(method.IsRuntimeDeterminedExactMethod);
- Debug.Assert(method.IsVirtual);
-
- // Normal virtual methods don't need a generic lookup.
- Debug.Assert(method.OwningType.IsInterface || method.HasInstantiation);
-
- _method = method;
- }
-
- public override ISymbolNode GetTarget(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation, GenericDictionaryNode dictionary)
- {
- if (factory.Target.Abi == TargetAbi.CoreRT)
- {
- MethodDesc instantiatedMethod = _method.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
- return factory.InterfaceDispatchCell(instantiatedMethod);
- }
- else
- {
- MethodDesc instantiatedMethod = _method.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(dictionary.TypeInstantiation, dictionary.MethodInstantiation);
- return factory.InterfaceDispatchCell(instantiatedMethod, dictionary.GetMangledName(factory.NameMangler));
- }
- }
-
- public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
- {
- sb.Append("VirtualResolve_");
- sb.Append(nameMangler.GetMangledMethodName(_method));
- }
-
- public override string ToString() => $"VirtualResolve: {_method}";
-
- public override NativeLayoutVertexNode TemplateDictionaryNode(NodeFactory factory)
- {
- if (factory.Target.Abi == TargetAbi.CoreRT)
- {
- // We should be able to get rid of this custom ABI handling
- // once https://github.com/dotnet/corert/issues/3248 is fixed.
- return factory.NativeLayout.NotSupportedDictionarySlot;
- }
- else
- {
- return factory.NativeLayout.InterfaceCellDictionarySlot(_method);
- }
- }
-
- public override void WriteDictionaryTocData(NodeFactory factory, IGenericLookupResultTocWriter writer)
- {
- if (factory.Target.Abi == TargetAbi.CoreRT)
- {
- // TODO
- throw new NotImplementedException();
- }
- else
- {
- writer.WriteData(LookupResultReferenceType(factory), LookupResultType.InterfaceDispatchCell, _method);
- }
- }
-
- protected override int CompareToImpl(GenericLookupResult other, TypeSystemComparer comparer)
- {
- return comparer.Compare(_method, ((VirtualResolveGenericLookupResult)other)._method);
- }
- }
-
- /// <summary>
/// Generic lookup result that points to the non-GC static base of a type.
/// </summary>
internal sealed class TypeNonGCStaticBaseGenericLookupResult : GenericLookupResult
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs
index a920c6732..67c91ccab 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs
@@ -16,7 +16,7 @@ namespace ILCompiler.DependencyAnalysis
public sealed class ILScanNodeFactory : NodeFactory
{
public ILScanNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, MetadataManager metadataManager, NameMangler nameMangler)
- : base(context, compilationModuleGroup, metadataManager, nameMangler, new LazyGenericsDisabledPolicy())
+ : base(context, compilationModuleGroup, metadataManager, nameMangler, new LazyGenericsDisabledPolicy(), new LazyVTableSliceProvider())
{
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
index 007ee65ed..acb7072b7 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Diagnostics;
using Internal.Runtime;
@@ -13,8 +12,8 @@ namespace ILCompiler.DependencyAnalysis
{
public class InterfaceDispatchCellNode : ObjectNode, ISymbolDefinitionNode
{
- MethodDesc _targetMethod;
- string _callSiteIdentifier;
+ private readonly MethodDesc _targetMethod;
+ private readonly string _callSiteIdentifier;
public InterfaceDispatchCellNode(MethodDesc targetMethod, string callSiteIdentifier)
{
@@ -49,7 +48,22 @@ namespace ILCompiler.DependencyAnalysis
public override ObjectNodeSection Section => ObjectNodeSection.DataSection;
public override bool StaticDependenciesAreComputed => true;
-
+
+ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
+ {
+ DependencyList result = new DependencyList();
+
+ if (!factory.VTable(_targetMethod.OwningType).HasFixedSlots)
+ {
+ result.Add(factory.VirtualMethodUse(_targetMethod), "Interface method use");
+ }
+
+ // TODO: https://github.com/dotnet/corert/issues/3224
+ result.Add(factory.ReflectableMethod(_targetMethod), "Abstract reflectable method");
+
+ return result;
+ }
+
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
index 3ec7d5fd2..c8f936604 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
@@ -1583,7 +1583,10 @@ namespace ILCompiler.DependencyAnalysis
protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.InterfaceCall;
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
- return new DependencyListEntry[1] { new DependencyListEntry(_signature, "TypeSignature") };
+ yield return new DependencyListEntry(_signature, "TypeSignature");
+
+ if (!factory.VTable(_method.OwningType).HasFixedSlots)
+ yield return new DependencyListEntry(factory.VirtualMethodUse(_method), "Slot number");
}
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs
index 73bb229d8..ba32b6a37 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs
@@ -58,11 +58,6 @@ namespace ILCompiler.DependencyAnalysis
return new VirtualDispatchGenericLookupResult(method);
});
- _virtualResolveHelpers = new NodeCache<MethodDesc, GenericLookupResult>(method =>
- {
- return new VirtualResolveGenericLookupResult(method);
- });
-
_typeThreadStaticBaseIndexSymbols = new NodeCache<TypeDesc, GenericLookupResult>(type =>
{
return new TypeThreadStaticBaseIndexGenericLookupResult(type);
@@ -213,13 +208,6 @@ namespace ILCompiler.DependencyAnalysis
return _virtualCallHelpers.GetOrAdd(method);
}
- private NodeCache<MethodDesc, GenericLookupResult> _virtualResolveHelpers;
-
- public GenericLookupResult VirtualMethodAddress(MethodDesc method)
- {
- return _virtualResolveHelpers.GetOrAdd(method);
- }
-
private NodeCache<MethodKey, GenericLookupResult> _methodEntrypoints;
public GenericLookupResult MethodEntry(MethodDesc method, bool isUnboxingThunk = false)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
index 2fce7836c..2a2d0f7c8 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
@@ -23,14 +23,16 @@ namespace ILCompiler.DependencyAnalysis
private TargetDetails _target;
private CompilerTypeSystemContext _context;
private CompilationModuleGroup _compilationModuleGroup;
+ private VTableSliceProvider _vtableSliceProvider;
private bool _markingComplete;
public NodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup,
- MetadataManager metadataManager, NameMangler nameMangler, LazyGenericsPolicy lazyGenericsPolicy)
+ MetadataManager metadataManager, NameMangler nameMangler, LazyGenericsPolicy lazyGenericsPolicy, VTableSliceProvider vtableSliceProvider)
{
_target = context.Target;
_context = context;
_compilationModuleGroup = compilationModuleGroup;
+ _vtableSliceProvider = vtableSliceProvider;
NameMangler = nameMangler;
InteropStubManager = new InteropStubManager(compilationModuleGroup, context, new InteropStateManager(compilationModuleGroup.GeneratedAssembly));
CreateNodeCaches();
@@ -412,7 +414,7 @@ namespace ILCompiler.DependencyAnalysis
if (CompilationModuleGroup.ShouldProduceFullVTable(type))
return new EagerlyBuiltVTableSliceNode(type);
else
- return new LazilyBuiltVTableSliceNode(type);
+ return _vtableSliceProvider.GetSlice(type);
});
_methodGenericDictionaries = new NodeCache<MethodDesc, ISymbolNode>(method =>
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
index f5f788ee1..e88762751 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
@@ -47,10 +47,8 @@ namespace ILCompiler.DependencyAnalysis
return factory.GenericLookup.TypeThreadStaticBaseIndex((TypeDesc)target);
case ReadyToRunHelperId.MethodDictionary:
return factory.GenericLookup.MethodDictionary((MethodDesc)target);
- case ReadyToRunHelperId.VirtualCall:
+ case ReadyToRunHelperId.VirtualDispatchCell:
return factory.GenericLookup.VirtualCall((MethodDesc)target);
- case ReadyToRunHelperId.ResolveVirtualFunction:
- return factory.GenericLookup.VirtualMethodAddress((MethodDesc)target);
case ReadyToRunHelperId.MethodEntry:
return factory.GenericLookup.MethodEntry((MethodDesc)target);
case ReadyToRunHelperId.DelegateCtor:
@@ -129,25 +127,6 @@ namespace ILCompiler.DependencyAnalysis
}
}
break;
-
- case ReadyToRunHelperId.ResolveVirtualFunction:
- {
- MethodDesc instantiatedTarget = ((MethodDesc)_target).GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
- if (!factory.VTable(instantiatedTarget.OwningType).HasFixedSlots)
- {
- result.Add(
- new DependencyListEntry(
- factory.VirtualMethodUse(instantiatedTarget),
- "Dictionary dependency"));
- }
-
- // TODO: https://github.com/dotnet/corert/issues/3224
- if (instantiatedTarget.IsAbstract)
- {
- result.Add(new DependencyListEntry(factory.ReflectableMethod(instantiatedTarget), "Abstract reflectable method"));
- }
- }
- break;
}
// All generic lookups depend on the thing they point to
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
index 1ab4a73f4..c3bfaf83c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
@@ -31,6 +31,7 @@ namespace ILCompiler.DependencyAnalysis
FieldHandle,
MethodDictionary,
MethodEntry,
+ VirtualDispatchCell,
DefaultConstructor,
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs
index 6e22b73da..243f509a0 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs
@@ -12,8 +12,9 @@ namespace ILCompiler.DependencyAnalysis
{
public sealed class RyuJitNodeFactory : NodeFactory
{
- public RyuJitNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, MetadataManager metadataManager, NameMangler nameMangler)
- : base(context, compilationModuleGroup, metadataManager, nameMangler, new LazyGenericsDisabledPolicy())
+ public RyuJitNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, MetadataManager metadataManager,
+ NameMangler nameMangler, VTableSliceProvider vtableSliceProvider)
+ : base(context, compilationModuleGroup, metadataManager, nameMangler, new LazyGenericsDisabledPolicy(), vtableSliceProvider)
{
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs
index c49d5eb8f..fca8037df 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs
@@ -207,9 +207,8 @@ namespace ILCompiler.DependencyAnalysis
case ReadyToRunHelperId.MethodHandle:
case ReadyToRunHelperId.FieldHandle:
case ReadyToRunHelperId.MethodDictionary:
- case ReadyToRunHelperId.VirtualCall:
- case ReadyToRunHelperId.ResolveVirtualFunction:
case ReadyToRunHelperId.MethodEntry:
+ case ReadyToRunHelperId.VirtualDispatchCell:
case ReadyToRunHelperId.DefaultConstructor:
{
EmitDictionaryLookup(factory, ref encoder, contextRegister, encoder.TargetRegister.Result, _lookupSignature, relocsOnly);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
index 82247a54b..8e7fbab71 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
@@ -31,27 +31,22 @@ namespace ILCompiler.DependencyAnalysis
{
MethodDesc targetMethod = (MethodDesc)Target;
- if (targetMethod.OwningType.IsInterface)
- {
- encoder.EmitLEAQ(Register.R10, factory.InterfaceDispatchCell((MethodDesc)Target));
- AddrMode jmpAddrMode = new AddrMode(Register.R10, null, 0, 0, AddrModeSize.Int64);
- encoder.EmitJmpToAddrMode(ref jmpAddrMode);
- }
- else
- {
- if (relocsOnly)
- break;
+ Debug.Assert(!targetMethod.OwningType.IsInterface);
- AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64);
- encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromThisPtr);
+ AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64);
+ encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromThisPtr);
- int pointerSize = factory.Target.PointerSize;
+ int pointerSize = factory.Target.PointerSize;
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod);
+ int slot = 0;
+ if (!relocsOnly)
+ {
+ slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod);
Debug.Assert(slot != -1);
- AddrMode jmpAddrMode = new AddrMode(encoder.TargetRegister.Result, null, EETypeNode.GetVTableOffset(pointerSize) + (slot * pointerSize), 0, AddrModeSize.Int64);
- encoder.EmitJmpToAddrMode(ref jmpAddrMode);
}
+
+ AddrMode jmpAddrMode = new AddrMode(encoder.TargetRegister.Result, null, EETypeNode.GetVTableOffset(pointerSize) + (slot * pointerSize), 0, AddrModeSize.Int64);
+ encoder.EmitJmpToAddrMode(ref jmpAddrMode);
}
break;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs
index 5b099551c..2d1e3861f 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs
@@ -71,7 +71,7 @@ namespace ILCompiler
}
public UtcNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, IEnumerable<ModuleDesc> inputModules, string metadataFile, string outputFile, UTCNameMangler nameMangler, bool buildMRT)
- : base(context, compilationModuleGroup, PickMetadataManager(context, compilationModuleGroup, inputModules, metadataFile), nameMangler, new AttributeDrivenLazyGenericsPolicy())
+ : base(context, compilationModuleGroup, PickMetadataManager(context, compilationModuleGroup, inputModules, metadataFile), nameMangler, new AttributeDrivenLazyGenericsPolicy(), null)
{
CreateHostedNodeCaches();
CompilationUnitPrefix = nameMangler.CompilationUnitPrefix;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs
index f01fbf406..59777bae9 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs
@@ -21,6 +21,7 @@ namespace ILCompiler.DependencyAnalysis
public VTableSliceNode(TypeDesc type)
{
+ Debug.Assert(!type.IsArray, "Wanted to call GetClosestDefType?");
_type = type;
}
@@ -29,6 +30,8 @@ namespace ILCompiler.DependencyAnalysis
get;
}
+ public TypeDesc Type => _type;
+
/// <summary>
/// Gets a value indicating whether the slots are assigned at the beginning of the compilation.
/// </summary>
@@ -41,6 +44,16 @@ namespace ILCompiler.DependencyAnalysis
public override bool StaticDependenciesAreComputed => true;
+ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
+ {
+ if (_type.HasBaseType)
+ {
+ return new[] { new DependencyListEntry(factory.VTable(_type.BaseType), "Base type VTable") };
+ }
+
+ return null;
+ }
+
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
@@ -48,9 +61,9 @@ namespace ILCompiler.DependencyAnalysis
public override bool HasDynamicDependencies => false;
public override bool HasConditionalStaticDependencies => false;
- protected IEnumerable<MethodDesc> GetAllVirtualMethods()
+ protected static IEnumerable<MethodDesc> GetAllVirtualMethods(TypeDesc type)
{
- foreach (MethodDesc method in _type.GetAllMethods())
+ foreach (MethodDesc method in type.GetAllMethods())
{
if (method.IsVirtual)
yield return method;
@@ -59,23 +72,55 @@ namespace ILCompiler.DependencyAnalysis
}
/// <summary>
+ /// Represents a VTable slice with fixed slots whose assignment was determined at the time the slice was allocated.
+ /// </summary>
+ internal class PrecomputedVTableSliceNode : VTableSliceNode
+ {
+ private readonly IReadOnlyList<MethodDesc> _slots;
+
+ public PrecomputedVTableSliceNode(TypeDesc type, IReadOnlyList<MethodDesc> slots)
+ : base(type)
+ {
+ _slots = slots;
+ }
+
+ public override IReadOnlyList<MethodDesc> Slots
+ {
+ get
+ {
+ return _slots;
+ }
+ }
+
+ public override bool HasFixedSlots
+ {
+ get
+ {
+ return true;
+ }
+ }
+ }
+
+ /// <summary>
/// Represents a VTable slice for a complete type - a type with all virtual method slots generated,
/// irrespective of whether they are used.
/// </summary>
- internal sealed class EagerlyBuiltVTableSliceNode : VTableSliceNode
+ internal sealed class EagerlyBuiltVTableSliceNode : PrecomputedVTableSliceNode
{
- private MethodDesc[] _slots;
-
public EagerlyBuiltVTableSliceNode(TypeDesc type)
- : base(type)
+ : base(type, ComputeSlots(type))
+ {
+ }
+
+ private static IReadOnlyList<MethodDesc> ComputeSlots(TypeDesc type)
{
var slots = new ArrayBuilder<MethodDesc>();
bool isObjectType = type.IsObject;
- DefType defType = _type.GetClosestDefType();
+ DefType defType = type.GetClosestDefType();
- IEnumerable<MethodDesc> allSlots = _type.IsInterface ?
- GetAllVirtualMethods() : defType.EnumAllVirtualSlots();
+ IEnumerable<MethodDesc> allSlots = type.IsInterface ?
+ GetAllVirtualMethods(type) : defType.EnumAllVirtualSlots();
foreach (var method in allSlots)
{
@@ -94,36 +139,7 @@ namespace ILCompiler.DependencyAnalysis
slots.Add(method);
}
- _slots = slots.ToArray();
- }
-
- public override IReadOnlyList<MethodDesc> Slots
- {
- get
- {
- return _slots;
- }
- }
-
- public override bool HasFixedSlots
- {
- get
- {
- return true;
- }
- }
-
- public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
- {
- if (_type.HasBaseType)
- {
- return new DependencyListEntry[]
- {
- new DependencyListEntry(factory.VTable(_type.BaseType), "Base type VTable")
- };
- }
-
- return null;
+ return slots.ToArray();
}
}
@@ -187,16 +203,6 @@ namespace ILCompiler.DependencyAnalysis
_usedMethods.Add(virtualMethod);
}
- public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
- {
- if (_type.HasBaseType)
- {
- return new[] { new DependencyListEntry(factory.VTable(_type.BaseType), "Base type VTable") };
- }
-
- return null;
- }
-
public override bool HasConditionalStaticDependencies
{
get
@@ -212,7 +218,7 @@ namespace ILCompiler.DependencyAnalysis
DefType defType = _type.GetClosestDefType();
IEnumerable<MethodDesc> allSlots = _type.IsInterface ?
- GetAllVirtualMethods() : defType.EnumAllVirtualSlots();
+ GetAllVirtualMethods(_type) : defType.EnumAllVirtualSlots();
foreach (var method in allSlots)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/ILScanner.cs b/src/ILCompiler.Compiler/src/Compiler/ILScanner.cs
index d93aba60c..67c0a8532 100644
--- a/src/ILCompiler.Compiler/src/Compiler/ILScanner.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/ILScanner.cs
@@ -74,8 +74,9 @@ namespace ILCompiler
}
}
- public ILScanResults Scan()
+ ILScanResults IILScanner.Scan()
{
+ _nodeFactory.NameMangler.CompilationUnitPrefix = "";
return new ILScanResults(_dependencyGraph.MarkedNodeList);
}
}
@@ -94,17 +95,31 @@ namespace ILCompiler
_markedNodes = markedNodes;
}
- public IEnumerable<MethodDesc> CompiledMethods
+ public VTableSliceProvider GetVTableLayoutInfo()
{
- get
+ return new ScannedVTableProvider(_markedNodes);
+ }
+
+ private class ScannedVTableProvider : VTableSliceProvider
+ {
+ private Dictionary<TypeDesc, IReadOnlyList<MethodDesc>> _vtableSlices = new Dictionary<TypeDesc, IReadOnlyList<MethodDesc>>();
+
+ public ScannedVTableProvider(ImmutableArray<DependencyNodeCore<NodeFactory>> markedNodes)
{
- foreach (var node in _markedNodes)
+ foreach (var node in markedNodes)
{
- var methodNode = node as ScannedMethodNode;
- if (methodNode != null)
- yield return methodNode.Method;
+ var vtableSliceNode = node as VTableSliceNode;
+ if (vtableSliceNode != null)
+ {
+ _vtableSlices.Add(vtableSliceNode.Type, vtableSliceNode.Slots);
+ }
}
}
+
+ internal override VTableSliceNode GetSlice(TypeDesc type)
+ {
+ return new PrecomputedVTableSliceNode(type, _vtableSlices[type]);
+ }
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/LibraryRootProvider.cs b/src/ILCompiler.Compiler/src/Compiler/LibraryRootProvider.cs
index c4a3805cb..80f6b0171 100644
--- a/src/ILCompiler.Compiler/src/Compiler/LibraryRootProvider.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/LibraryRootProvider.cs
@@ -84,6 +84,10 @@ namespace ILCompiler
{
MethodSignature signature = method.Signature;
+ // Vararg methods are not supported in .NET Core
+ if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) == MethodSignatureFlags.CallingConventionVarargs)
+ throw new TypeSystemException.BadImageFormatException();
+
CheckTypeCanBeUsedInSignature(signature.ReturnType);
for (int i = 0; i < signature.Length; i++)
diff --git a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs
index 3de4197dc..27240e366 100644
--- a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs
@@ -85,7 +85,7 @@ namespace ILCompiler
jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_FEATURE_SIMD);
}
- var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _nameMangler);
+ var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _nameMangler, _vtableSliceProvider);
var jitConfig = new JitConfigProvider(jitFlagBuilder.ToArray(), _ryujitOptions);
DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory);
diff --git a/src/ILCompiler.Compiler/src/Compiler/VTableSliceProvider.cs b/src/ILCompiler.Compiler/src/Compiler/VTableSliceProvider.cs
new file mode 100644
index 000000000..18455f2b4
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/VTableSliceProvider.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+using ILCompiler.DependencyAnalysis;
+
+namespace ILCompiler
+{
+ /// <summary>
+ /// Provides VTable information for a specific type.
+ /// </summary>
+ public abstract class VTableSliceProvider
+ {
+ internal abstract VTableSliceNode GetSlice(TypeDesc type);
+ }
+
+ /// <summary>
+ /// Provides VTable information that collects data during the compilation to build a VTable for a type.
+ /// </summary>
+ public sealed class LazyVTableSliceProvider : VTableSliceProvider
+ {
+ internal override VTableSliceNode GetSlice(TypeDesc type)
+ {
+ return new LazilyBuiltVTableSliceNode(type);
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
index eeaebf363..a44116f4f 100644
--- a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
+++ b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
@@ -592,32 +592,26 @@ namespace Internal.IL
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.GVMLookupForSlot), reason);
}
- else
+ else if (method.OwningType.IsInterface)
{
- ReadyToRunHelperId helper;
- if (opcode == ILOpcode.ldvirtftn)
+ if (exactContextNeedsRuntimeLookup)
{
- helper = ReadyToRunHelperId.ResolveVirtualFunction;
+ _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.VirtualDispatchCell, runtimeDeterminedMethod), reason);
}
else
{
- Debug.Assert(opcode == ILOpcode.callvirt);
- helper = ReadyToRunHelperId.VirtualCall;
+ _dependencies.Add(_factory.InterfaceDispatchCell(method), reason);
}
-
- if (exactContextNeedsRuntimeLookup && targetMethod.OwningType.IsInterface)
- {
- _dependencies.Add(GetGenericLookupHelper(helper, runtimeDeterminedMethod), reason);
- }
- else
- {
- // Get the slot defining method to make sure our virtual method use tracking gets this right.
- // For normal C# code the targetMethod will always be newslot.
- MethodDesc slotDefiningMethod = targetMethod.IsNewSlot ?
+ }
+ else if (_compilation.HasFixedSlotVTable(method.OwningType))
+ {
+ // No dependencies: virtual call through the vtable
+ }
+ else
+ {
+ MethodDesc slotDefiningMethod = targetMethod.IsNewSlot ?
targetMethod : MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(targetMethod);
-
- _dependencies.Add(_factory.ReadyToRunHelper(helper, slotDefiningMethod), reason);
- }
+ _dependencies.Add(_factory.VirtualMethodUse(slotDefiningMethod), reason);
}
}
diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
index 25de949da..068828832 100644
--- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
+++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
@@ -309,6 +309,7 @@
<Compile Include="Compiler\SimdHelper.cs" />
<Compile Include="Compiler\VectorOfTFieldLayoutAlgorithm.cs" />
<Compile Include="Compiler\VirtualMethodCallHelper.cs" />
+ <Compile Include="Compiler\VTableSliceProvider.cs" />
<Compile Include="Compiler\WindowsNodeMangler.cs" />
<Compile Include="IL\ILImporter.Scanner.cs" />
<Compile Include="IL\Stubs\PInvokeILProvider.cs" />
diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs
index 7ea68e212..3f56e757c 100644
--- a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs
+++ b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs
@@ -29,7 +29,7 @@ namespace ILCompiler
public override ICompilation ToCompilation()
{
- CppCodegenNodeFactory factory = new CppCodegenNodeFactory(_context, _compilationGroup, _metadataManager, _nameMangler);
+ CppCodegenNodeFactory factory = new CppCodegenNodeFactory(_context, _compilationGroup, _metadataManager, _nameMangler, _vtableSliceProvider);
DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory);
return new CppCodegenCompilation(graph, factory, _compilationRoots, _logger, _config);
diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs
index 3eaf2ae2a..2a0e66acb 100644
--- a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs
+++ b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs
@@ -10,8 +10,9 @@ namespace ILCompiler.DependencyAnalysis
{
public sealed class CppCodegenNodeFactory : NodeFactory
{
- public CppCodegenNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, MetadataManager metadataManager, NameMangler nameMangler)
- : base(context, compilationModuleGroup, metadataManager, nameMangler, new LazyGenericsDisabledPolicy())
+ public CppCodegenNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, MetadataManager metadataManager,
+ NameMangler nameMangler, VTableSliceProvider vtableSliceProvider)
+ : base(context, compilationModuleGroup, metadataManager, nameMangler, new LazyGenericsDisabledPolicy(), vtableSliceProvider)
{
}
diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs
index 53e9e892d..5e5069a63 100644
--- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs
+++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs
@@ -1109,7 +1109,7 @@ namespace ILCompiler.CppCodeGen
{
OutputTypeFields(typeDefinitions, nodeType);
- IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(nodeType).Slots;
+ IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(nodeType.GetClosestDefType()).Slots;
int baseSlots = 0;
var baseType = nodeType.BaseType;
diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
index cac63cb1e..dce48157a 100644
--- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
+++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
@@ -990,7 +990,6 @@ namespace Internal.IL
if (callViaInterfaceDispatch)
{
- _dependencies.Add(_nodeFactory.ReadyToRunHelper(ReadyToRunHelperId.VirtualCall, method));
ExpressionEntry v = (ExpressionEntry)_stack[_stack.Top - (methodSignature.Length + 1)];
string typeDefName = _writer.GetCppMethodName(method);
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs
index 9e8c802bf..9c8534db5 100644
--- a/src/JitInterface/src/CorInfoImpl.cs
+++ b/src/JitInterface/src/CorInfoImpl.cs
@@ -534,6 +534,11 @@ namespace Internal.JitInterface
private void Get_CORINFO_SIG_INFO(MethodSignature signature, out CORINFO_SIG_INFO sig)
{
sig.callConv = (CorInfoCallConv)(signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask);
+
+ // Varargs are not supported in .NET Core
+ if (sig.callConv == CorInfoCallConv.CORINFO_CALLCONV_VARARG)
+ throw new TypeSystemException.BadImageFormatException();
+
if (!signature.IsStatic) sig.callConv |= CorInfoCallConv.CORINFO_CALLCONV_HASTHIS;
TypeDesc returnType = signature.ReturnType;
@@ -792,10 +797,66 @@ namespace Internal.JitInterface
private CORINFO_MODULE_STRUCT_* getMethodModule(CORINFO_METHOD_STRUCT_* method)
{ throw new NotImplementedException("getMethodModule"); }
+
private void getMethodVTableOffset(CORINFO_METHOD_STRUCT_* method, ref uint offsetOfIndirection, ref uint offsetAfterIndirection)
- { throw new NotImplementedException("getMethodVTableOffset"); }
- private CORINFO_METHOD_STRUCT_* resolveVirtualMethod(CORINFO_METHOD_STRUCT_* virtualMethod, CORINFO_CLASS_STRUCT_* implementingClass, CORINFO_CONTEXT_STRUCT* ownerType)
- { throw new NotImplementedException("resolveVirtualMethod"); }
+ {
+ MethodDesc methodDesc = HandleToObject(method);
+ int pointerSize = _compilation.TypeSystemContext.Target.PointerSize;
+ offsetOfIndirection = (uint)CORINFO_VIRTUALCALL_NO_CHUNK.Value;
+
+ // Normalize to the slot defining method. We don't have slot information for the overrides.
+ methodDesc = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(methodDesc);
+
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(_compilation.NodeFactory, methodDesc);
+ Debug.Assert(slot != -1);
+
+ offsetAfterIndirection = (uint)(EETypeNode.GetVTableOffset(pointerSize) + slot * pointerSize);
+ }
+
+ private CORINFO_METHOD_STRUCT_* resolveVirtualMethod(CORINFO_METHOD_STRUCT_* baseMethod, CORINFO_CLASS_STRUCT_* derivedClass, CORINFO_CONTEXT_STRUCT* ownerType)
+ {
+ TypeDesc implType = HandleToObject(derivedClass);
+
+ // __Canon cannot be devirtualized
+ if (implType.IsCanonicalDefinitionType(CanonicalFormKind.Any))
+ {
+ return null;
+ }
+
+ implType = implType.GetClosestDefType();
+
+ MethodDesc decl = HandleToObject(baseMethod);
+ Debug.Assert(decl.IsVirtual);
+ Debug.Assert(!decl.HasInstantiation);
+
+ MethodDesc impl;
+
+ TypeDesc declOwningType = decl.OwningType;
+ if (declOwningType.IsInterface)
+ {
+ // Interface call devirtualization.
+
+ if (implType.IsValueType)
+ {
+ // TODO: this ends up asserting RyuJIT - why?
+ return null;
+ }
+
+ if (implType.IsCanonicalSubtype(CanonicalFormKind.Any))
+ {
+ // TODO: attempt to devirtualize methods on canonical interfaces
+ return null;
+ }
+
+ impl = implType.ResolveInterfaceMethodTarget(decl);
+ }
+ else
+ {
+ impl = implType.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(decl);
+ }
+
+ return impl != null ? ObjectToHandle(impl) : null;
+ }
private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult)
{
@@ -3014,6 +3075,39 @@ namespace Internal.JitInterface
// move that assert to some place later though.
targetIsFatFunctionPointer = true;
}
+ else if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_LDFTN) == 0
+ && targetMethod.OwningType.IsInterface)
+ {
+ pResult.kind = CORINFO_CALL_KIND.CORINFO_VIRTUALCALL_STUB;
+
+ if (pResult.exactContextNeedsRuntimeLookup)
+ {
+ pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = true;
+ pResult.codePointerOrStubLookup.runtimeLookup.indirections = CORINFO.USEHELPER;
+
+ // Do not bother computing the runtime lookup if we are inlining. The JIT is going
+ // to abort the inlining attempt anyway.
+ MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
+ if (contextMethod == MethodBeingCompiled)
+ {
+ pResult.codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
+ pResult.codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.VirtualDispatchCell;
+ pResult.codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
+ }
+ }
+ else
+ {
+ pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = false;
+ pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_PVALUE;
+ pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.InterfaceDispatchCell(targetMethod));
+ }
+ }
+ else if ((flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_LDFTN) == 0
+ && _compilation.HasFixedSlotVTable(targetMethod.OwningType))
+ {
+ pResult.kind = CORINFO_CALL_KIND.CORINFO_VIRTUALCALL_VTABLE;
+ pResult.nullInstanceCheck = true;
+ }
else
{
ReadyToRunHelperId helperId;
@@ -3036,18 +3130,12 @@ namespace Internal.JitInterface
// Foo<string>.GetHashCode is needed too.
if (pResult.exactContextNeedsRuntimeLookup && targetMethod.OwningType.IsInterface)
{
- pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = true;
- pResult.codePointerOrStubLookup.runtimeLookup.indirections = CORINFO.USEHELPER;
-
- // Do not bother computing the runtime lookup if we are inlining. The JIT is going
- // to abort the inlining attempt anyway.
- MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
- if (contextMethod == MethodBeingCompiled)
- {
- pResult.codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
- pResult.codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)helperId;
- pResult.codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
- }
+ // We need JitInterface changes to fully support this.
+ // If this is LDVIRTFTN of an interface method that is part of a verifiable delegate creation sequence,
+ // RyuJIT is not going to use this value.
+ Debug.Assert(helperId == ReadyToRunHelperId.ResolveVirtualFunction);
+ pResult.exactContextNeedsRuntimeLookup = false;
+ pResult.codePointerOrStubLookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ExternSymbol("NYI_LDVIRTFTN"));
}
else
{
diff --git a/src/JitInterface/src/CorInfoTypes.cs b/src/JitInterface/src/CorInfoTypes.cs
index 53bb1f721..513def773 100644
--- a/src/JitInterface/src/CorInfoTypes.cs
+++ b/src/JitInterface/src/CorInfoTypes.cs
@@ -1021,6 +1021,10 @@ namespace Internal.JitInterface
CORINFO_VIRTUALCALL_VTABLE
};
+ public enum CORINFO_VIRTUALCALL_NO_CHUNK : uint
+ {
+ Value = 0xFFFFFFFF,
+ }
public unsafe struct CORINFO_CALL_INFO
{
diff --git a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
index 52bc25701..212aa98b9 100644
--- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
+++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
@@ -97,6 +97,11 @@ namespace ILCompiler
return intrinsicMethod;
}
+ public bool HasFixedSlotVTable(TypeDesc type)
+ {
+ return true;
+ }
+
public DelegateCreationInfo GetDelegateCtor(TypeDesc delegateType, MethodDesc target, bool followVirtualDispatch)
{
return DelegateCreationInfo.Create(delegateType, target, NodeFactory, followVirtualDispatch);
diff --git a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
index 5491c32c6..fa220b956 100644
--- a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
+++ b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
@@ -52,6 +52,7 @@
<NativeFormatCommonPath>..\..\Common\src\Internal\NativeFormat</NativeFormatCommonPath>
</PropertyGroup>
<ItemGroup Condition="'$(JitSupport)' == 'true'">
+ <Compile Include="..\..\Common\src\TypeSystem\Common\CastingHelper.cs" />
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\ArrayType.RuntimeDetermined.cs" />
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\ByRefType.RuntimeDetermined.cs" />
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\DefType.RuntimeDetermined.cs" />
diff --git a/src/packaging/packages.targets b/src/packaging/packages.targets
index 3695f21a9..c76fd287e 100644
--- a/src/packaging/packages.targets
+++ b/src/packaging/packages.targets
@@ -26,7 +26,7 @@
<CoreFxNuPkgRid Condition="'$(OSGroup)'=='OSX'">osx-x64</CoreFxNuPkgRid>
<CoreFxNuPkgRid Condition="'$(CoreFxNuPkgRid)'==''">$(NuPkgRid)</CoreFxNuPkgRid>
- <JitPackageVersion>2.1.0-preview1-25406-04</JitPackageVersion>
+ <JitPackageVersion>2.1.0-preview1-25412-03</JitPackageVersion>
<JitNuPkgRid Condition="'$(OSGroup)'=='Windows_NT'">win-x64</JitNuPkgRid>
<JitNuPkgRid Condition="'$(OSGroup)'=='OSX'">osx-x64</JitNuPkgRid>
<JitNuPkgRid Condition="'$(OSGroup)'=='Linux'">linux-x64</JitNuPkgRid>
diff --git a/src/packaging/ryujit/project.json b/src/packaging/ryujit/project.json
index fc003705f..62e1aa26b 100644
--- a/src/packaging/ryujit/project.json
+++ b/src/packaging/ryujit/project.json
@@ -1,6 +1,6 @@
{
"dependencies": {
- "Microsoft.NETCore.Jit": "2.1.0-preview1-25406-04"
+ "Microsoft.NETCore.Jit": "2.1.0-preview1-25412-03"
},
"frameworks": {
"netcoreapp2.0": { }
diff --git a/tests/src/Simple/Generics/Generics.cs b/tests/src/Simple/Generics/Generics.cs
index 213400efe..6ad140ae8 100644
--- a/tests/src/Simple/Generics/Generics.cs
+++ b/tests/src/Simple/Generics/Generics.cs
@@ -820,7 +820,8 @@ class Program
new DerivedClass2<string>().GVMethod2<string>("string", "string2");
new DerivedClass2<string>().GVMethod3<string>("string", "string2");
new DerivedClass2<string>().GVMethod4<string>("string", "string2");
- ((IFace<string>)new BaseClass<string>()).IFaceMethod1("string");
+ Func<IFace<string>> f = () => new BaseClass<string>(); // Hack to prevent devirtualization
+ f().IFaceMethod1("string");
((IFace<string>)new BaseClass<string>()).IFaceGVMethod1<string>("string1", "string2");
MethodInfo m1 = typeof(BaseClass<string>).GetTypeInfo().GetDeclaredMethod("Method1");