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:
-rw-r--r--src/Common/src/TypeSystem/Common/InstantiatedType.MethodImpls.cs (renamed from src/Common/src/TypeSystem/Common/TypeDesc.MethodImpls.cs)52
-rw-r--r--src/Common/src/TypeSystem/Common/MetadataType.MethodImpls.cs48
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs60
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs87
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs137
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapTableNode.cs74
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs27
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs8
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs9
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs8
-rw-r--r--src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj3
-rw-r--r--src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj3
-rw-r--r--src/ILCompiler/repro/Program.cs1
-rw-r--r--src/JitInterface/src/CorInfoImpl.cs35
-rw-r--r--src/Native/Bootstrap/main.cpp17
-rw-r--r--src/Native/Runtime/CMakeLists.txt5
-rw-r--r--src/Native/Runtime/CachedInterfaceDispatch.cpp27
-rw-r--r--src/Native/Runtime/inc/eetype.h2
-rw-r--r--src/Native/Runtime/inc/eetype.inl9
-rw-r--r--src/Native/Runtime/portable.cpp43
-rw-r--r--src/Native/Runtime/unix/PalRedhawkInline.h4
-rw-r--r--src/System.Private.CoreLib/src/System/Activator.cs9
23 files changed, 579 insertions, 100 deletions
diff --git a/src/Common/src/TypeSystem/Common/TypeDesc.MethodImpls.cs b/src/Common/src/TypeSystem/Common/InstantiatedType.MethodImpls.cs
index 6fbe17263..1b6edfb68 100644
--- a/src/Common/src/TypeSystem/Common/TypeDesc.MethodImpls.cs
+++ b/src/Common/src/TypeSystem/Common/InstantiatedType.MethodImpls.cs
@@ -5,47 +5,6 @@ using System;
namespace Internal.TypeSystem
{
- public struct MethodImplRecord
- {
- public MethodDesc Decl;
- public MethodDesc Body;
- }
-
- // MethodImpl api surface for types.
- public partial class MetadataType
- {
- /// <summary>
- /// Compute an array of all MethodImpls that pertain to overriding virtual (non-interface methods) on this type.
- /// May be expensive.
- /// </summary>
- protected abstract MethodImplRecord[] ComputeVirtualMethodImplsForType();
-
- private MethodImplRecord[] _allVirtualMethodImplsForType;
- /// <summary>
- /// Get an array of all MethodImpls that pertain to overriding virtual (non-interface methods) on this type.
- /// Expected to cache results so this api can be used repeatedly.
- /// </summary>
- public MethodImplRecord[] VirtualMethodImplsForType
- {
- get
- {
- if (_allVirtualMethodImplsForType == null)
- {
- _allVirtualMethodImplsForType = ComputeVirtualMethodImplsForType();
- }
-
- return _allVirtualMethodImplsForType;
- }
- }
-
- /// <summary>
- /// Get an array of MethodImpls where the Decl method matches by name with the specified name.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public abstract MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name);
- }
-
// Implementation of MethodImpl api surface implemented without metadata access.
public partial class InstantiatedType
{
@@ -63,7 +22,16 @@ namespace Internal.TypeSystem
for (int i = 0; i < uninstMethodImpls.Length; i++)
{
- instMethodImpls[i].Decl = _typeDef.Context.GetMethodForInstantiatedType(uninstMethodImpls[i].Decl, this);
+ var implTypeInstantiated = uninstMethodImpls[i].Decl.OwningType.InstantiateSignature(this.Instantiation, new Instantiation());
+ if (implTypeInstantiated is InstantiatedType)
+ {
+ instMethodImpls[i].Decl = _typeDef.Context.GetMethodForInstantiatedType(uninstMethodImpls[i].Decl.GetTypicalMethodDefinition(), (InstantiatedType)implTypeInstantiated);
+ }
+ else
+ {
+ instMethodImpls[i].Decl = uninstMethodImpls[i].Decl;
+ }
+
instMethodImpls[i].Body = _typeDef.Context.GetMethodForInstantiatedType(uninstMethodImpls[i].Body, this);
}
diff --git a/src/Common/src/TypeSystem/Common/MetadataType.MethodImpls.cs b/src/Common/src/TypeSystem/Common/MetadataType.MethodImpls.cs
new file mode 100644
index 000000000..a1ec05c83
--- /dev/null
+++ b/src/Common/src/TypeSystem/Common/MetadataType.MethodImpls.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Internal.TypeSystem
+{
+ public struct MethodImplRecord
+ {
+ public MethodDesc Decl;
+ public MethodDesc Body;
+ }
+
+ // MethodImpl api surface for types.
+ public partial class MetadataType
+ {
+ /// <summary>
+ /// Compute an array of all MethodImpls that pertain to overriding virtual (non-interface methods) on this type.
+ /// May be expensive.
+ /// </summary>
+ protected abstract MethodImplRecord[] ComputeVirtualMethodImplsForType();
+
+ private MethodImplRecord[] _allVirtualMethodImplsForType;
+ /// <summary>
+ /// Get an array of all MethodImpls that pertain to overriding virtual (non-interface methods) on this type.
+ /// Expected to cache results so this api can be used repeatedly.
+ /// </summary>
+ public MethodImplRecord[] VirtualMethodImplsForType
+ {
+ get
+ {
+ if (_allVirtualMethodImplsForType == null)
+ {
+ _allVirtualMethodImplsForType = ComputeVirtualMethodImplsForType();
+ }
+
+ return _allVirtualMethodImplsForType;
+ }
+ }
+
+ /// <summary>
+ /// Get an array of MethodImpls where the Decl method matches by name with the specified name.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public abstract MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name);
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
index 767f00aaa..4ad4beea3 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
@@ -108,6 +108,11 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ public void SetDispatchMapIndex(uint index)
+ {
+ _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldsElement.DispatchMap, index);
+ }
+
int ISymbolNode.Offset
{
get
@@ -137,8 +142,9 @@ namespace ILCompiler.DependencyAnalysis
objData.EmitZeroPointer();
return objData.ToObjectData();
}
-
+
ComputeOptionalEETypeFields(factory);
+
if (null == _optionalFieldsNode)
{
_optionalFieldsNode = factory.EETypeOptionalFields(_optionalFieldsBuilder);
@@ -155,6 +161,7 @@ namespace ILCompiler.DependencyAnalysis
if (_constructed)
{
OutputVirtualSlots(factory, ref objData, _type, _type);
+ OutputInterfaceMap(factory, ref objData);
OutputFinalizerMethod(factory, ref objData);
OutputOptionalFields(factory, ref objData);
OutputNullableTypeParameter(factory, ref objData);
@@ -163,6 +170,18 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
+ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
+ {
+ DependencyList dependencyList = new DependencyNodeCore<NodeFactory>.DependencyList();
+ if (_type is MetadataType && _constructed)
+ {
+ dependencyList.Add(factory.InterfaceDispatchMap(_type), "Interface dispatch map");
+ }
+
+ dependencyList.Add(factory.EETypeOptionalFields(_optionalFieldsBuilder), "EEType optional fields");
+ return dependencyList;
+ }
+
public override bool HasConditionalStaticDependencies
{
get
@@ -179,6 +198,11 @@ namespace ILCompiler.DependencyAnalysis
return true;
}
+ // If the type implements at least one interface, calls against that interface could result in this type's
+ // implementation being used.
+ if (_type.RuntimeInterfaces.Length > 0)
+ return true;
+
return false;
}
}
@@ -195,6 +219,24 @@ namespace ILCompiler.DependencyAnalysis
yield return new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(factory.MethodEntrypoint(impl), factory.VirtualMethodUse(decl), "Virtual method");
}
}
+
+ // Add conditional dependencies for interface methods the type implements. For example, if the type T implements
+ // interface IFoo which has a method M1, add a dependency on T.M1 dependent on IFoo.M1 being called, since it's
+ // possible for any IFoo object to actually be an instance of T.
+ foreach (DefType interfaceType in _type.RuntimeInterfaces)
+ {
+ Debug.Assert(interfaceType.IsInterface);
+
+ foreach (MethodDesc interfaceMethod in interfaceType.GetMethods())
+ {
+ Debug.Assert(interfaceMethod.IsVirtual);
+ MethodDesc implMethod = VirtualFunctionResolution.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, _type.GetClosestMetadataType());
+ if (implMethod != null)
+ {
+ yield return new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(factory.VirtualMethodUse(implMethod), factory.ReadyToRunHelper(ReadyToRunHelperId.InterfaceDispatch, interfaceMethod), "Interface method");
+ }
+ }
+ }
}
}
@@ -335,9 +377,7 @@ namespace ILCompiler.DependencyAnalysis
}
objData.EmitShort(checked((short)virtualSlotCount));
-
- // Todo: Number of slots of EEInterfaceInfo when we add interface support
- objData.EmitShort(0);
+ objData.EmitShort(checked((short)_type.RuntimeInterfaces.Length));
}
private void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType)
@@ -364,6 +404,14 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ private void OutputInterfaceMap(NodeFactory factory, ref ObjectDataBuilder objData)
+ {
+ foreach (var itf in _type.RuntimeInterfaces)
+ {
+ objData.EmitPointerReloc(factory.NecessaryTypeSymbol(itf));
+ }
+ }
+
private void OutputFinalizerMethod(NodeFactory factory, ref ObjectDataBuilder objData)
{
MethodDesc finalizerMethod = _type.GetFinalizer();
@@ -391,12 +439,10 @@ namespace ILCompiler.DependencyAnalysis
}
/// <summary>
- /// Populate the OptionalFieldsRuntimeBuilder if any optional fields are required. Returns true iff
- /// at least one optional field was set.
+ /// Populate the OptionalFieldsRuntimeBuilder if any optional fields are required.
/// </summary>
private void ComputeOptionalEETypeFields(NodeFactory factory)
{
- // Todo: DispatchMap table index when we support interface dispatch maps
ComputeRareFlags();
ComputeNullableValueOffset();
ComputeICastableVirtualMethodSlots(factory);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs
index 357de99c4..a2bab8b82 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs
@@ -56,12 +56,21 @@ namespace ILCompiler.DependencyAnalysis
return ((ISymbolNode)this).MangledName;
}
+ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory)
+ {
+ return !_fieldBuilder.IsAtLeastOneFieldUsed();
+ }
+
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
ObjectDataBuilder objData = new ObjectDataBuilder(factory);
objData.RequirePointerAlignment();
objData.DefinedSymbols.Add(this);
- objData.EmitBytes(_fieldBuilder.GetBytes());
+
+ if (!relocsOnly)
+ {
+ objData.EmitBytes(_fieldBuilder.GetBytes());
+ }
return objData.ToObjectData();
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
new file mode 100644
index 000000000..cbf3ad015
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
@@ -0,0 +1,87 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Internal.TypeSystem;
+using System;
+using System.Diagnostics;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ class InterfaceDispatchCellNode : ObjectNode, ISymbolNode
+ {
+ MethodDesc _targetMethod;
+
+ public InterfaceDispatchCellNode(MethodDesc targetMethod)
+ {
+ Debug.Assert(targetMethod.OwningType.IsInterface);
+ _targetMethod = targetMethod;
+ }
+
+ public string MangledName
+ {
+ get
+ {
+ return "__InterfaceDispatchCell_" + NodeFactory.NameMangler.GetMangledMethodName(_targetMethod);
+ }
+ }
+
+ public override string GetName()
+ {
+ return ((ISymbolNode)this).MangledName;
+ }
+
+ public int Offset
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override string Section
+ {
+ get
+ {
+ return "data";
+ }
+ }
+
+ public override bool StaticDependenciesAreComputed
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ ObjectDataBuilder objData = new ObjectDataBuilder(factory);
+ // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the
+ // synchronization mechanism of the two values in the runtime.
+ objData.Alignment = _targetMethod.Context.Target.PointerSize * 2;
+ objData.DefinedSymbols.Add(this);
+
+ objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch"));
+
+ // The second cell field uses the two lower-order bits to communicate the contents.
+ // We add 1 to signal IDC_CachePointerIsInterfacePointer. See src\Native\Runtime\inc\rhbinder.h.
+ objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), 1);
+
+ // End the run of dispatch cells
+ objData.EmitZeroPointer();
+
+ int interfaceMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod);
+ if (factory.Target.PointerSize == 8)
+ {
+ objData.EmitLong(interfaceMethodSlot);
+ }
+ else
+ {
+ throw new NotImplementedException();
+ }
+
+ return objData.ToObjectData();
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
new file mode 100644
index 000000000..09d5021aa
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
@@ -0,0 +1,137 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Internal.TypeSystem;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ internal struct DispatchMapEntry
+ {
+ public short InterfaceIndex;
+ public short InterfaceMethodSlot;
+ public short ImplementationMethodSlot;
+ }
+
+ internal class InterfaceDispatchMapNode : ObjectNode, ISymbolNode
+ {
+ uint _dispatchMapTableIndex;
+ TypeDesc _type;
+
+ public InterfaceDispatchMapNode(TypeDesc type)
+ {
+ _type = type;
+ _dispatchMapTableIndex = uint.MaxValue;
+ }
+
+ public override string GetName()
+ {
+ return ((ISymbolNode)this).MangledName;
+ }
+
+ string ISymbolNode.MangledName
+ {
+ get
+ {
+ if (_dispatchMapTableIndex == uint.MaxValue)
+ return "__InterfaceDispatchMap_";
+ else
+ return "__InterfaceDispatchMap_" + _dispatchMapTableIndex;
+ }
+ }
+
+ int ISymbolNode.Offset
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override bool StaticDependenciesAreComputed
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override string Section
+ {
+ get
+ {
+ return "data";
+ }
+ }
+
+ internal void SetDispatchMapTableIndex(uint index)
+ {
+ Debug.Assert(_dispatchMapTableIndex == uint.MaxValue);
+ _dispatchMapTableIndex = index;
+ }
+
+ protected override void OnMarked(NodeFactory context)
+ {
+ _dispatchMapTableIndex = context.DispatchMapTable.AddDispatchMap(this);
+ ((EETypeNode)context.ConstructedTypeSymbol(_type)).SetDispatchMapIndex(_dispatchMapTableIndex);
+ }
+
+ DispatchMapEntry[] BuildDispatchMap(NodeFactory factory)
+ {
+ ArrayBuilder<DispatchMapEntry> dispatchMapEntries = new ArrayBuilder<DispatchMapEntry>();
+
+ for (int i = 0; i < _type.RuntimeInterfaces.Length; i++)
+ {
+ var interfaceType = _type.RuntimeInterfaces[i];
+ Debug.Assert(interfaceType.IsInterface);
+
+ List<MethodDesc> virtualSlots;
+ factory.VirtualSlots.TryGetValue(interfaceType, out virtualSlots);
+
+ if (virtualSlots != null)
+ {
+ for (int j = 0; j < virtualSlots.Count; j++)
+ {
+ MethodDesc declMethod = virtualSlots[j];
+ var implMethod = VirtualFunctionResolution.ResolveInterfaceMethodToVirtualMethodOnType(declMethod, _type.GetClosestMetadataType());
+
+ // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
+ // dispatch will walk the inheritance chain).
+ if (implMethod != null)
+ {
+ var entry = new DispatchMapEntry();
+ entry.InterfaceIndex = checked((short)i);
+ entry.InterfaceMethodSlot = checked((short)j);
+ entry.ImplementationMethodSlot = checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod));
+ dispatchMapEntries.Add(entry);
+ }
+ }
+ }
+ }
+
+ return dispatchMapEntries.ToArray();
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ ObjectDataBuilder objData = new ObjectDataBuilder(factory);
+ objData.Alignment = 16;
+ objData.DefinedSymbols.Add(this);
+
+ if (!relocsOnly)
+ {
+ var entries = BuildDispatchMap(factory);
+ objData.EmitInt(entries.Length);
+ foreach (var entry in entries)
+ {
+ objData.EmitShort(entry.InterfaceIndex);
+ objData.EmitShort(entry.InterfaceMethodSlot);
+ objData.EmitShort(entry.ImplementationMethodSlot);
+ }
+ }
+
+ return objData.ToObjectData();
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapTableNode.cs
new file mode 100644
index 000000000..11e0f8056
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapTableNode.cs
@@ -0,0 +1,74 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ public class InterfaceDispatchMapTableNode : ObjectNode, ISymbolNode
+ {
+ List<InterfaceDispatchMapNode> _dispatchMaps = new List<InterfaceDispatchMapNode>();
+
+ public InterfaceDispatchMapTableNode()
+ {
+ }
+
+ public string MangledName
+ {
+ get
+ {
+ return "__InterfaceDispatchMapTable";
+ }
+ }
+
+ public override string GetName()
+ {
+ return ((ISymbolNode)this).MangledName;
+ }
+
+ public int Offset
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override string Section
+ {
+ get
+ {
+ return "rdata";
+ }
+ }
+
+ public override bool StaticDependenciesAreComputed
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ internal uint AddDispatchMap(InterfaceDispatchMapNode node)
+ {
+ _dispatchMaps.Add(node);
+
+ return (uint)_dispatchMaps.Count - 1;
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ ObjectDataBuilder objData = new ObjectDataBuilder(factory);
+ objData.Alignment = factory.Target.PointerSize;
+ objData.DefinedSymbols.Add(this);
+
+ foreach (var map in _dispatchMaps)
+ {
+ objData.EmitPointerReloc(map);
+ }
+
+ return objData.ToObjectData();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
index 8822b099c..e450dcc93 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
@@ -148,6 +148,16 @@ namespace ILCompiler.DependencyAnalysis
{
return new EETypeOptionalFieldsNode(fieldBuilder);
});
+
+ _interfaceDispatchCells = new NodeCache<MethodDesc, InterfaceDispatchCellNode>((MethodDesc method) =>
+ {
+ return new InterfaceDispatchCellNode(method);
+ });
+
+ _interfaceDispatchMaps = new NodeCache<TypeDesc, InterfaceDispatchMapNode>((TypeDesc type) =>
+ {
+ return new InterfaceDispatchMapNode(type);
+ });
}
private NodeCache<TypeDesc, EETypeNode> _typeSymbols;
@@ -190,6 +200,13 @@ namespace ILCompiler.DependencyAnalysis
return _threadStatics.GetOrAdd(type);
}
+ private NodeCache<MethodDesc, InterfaceDispatchCellNode> _interfaceDispatchCells;
+
+ internal InterfaceDispatchCellNode InterfaceDispatchCell(MethodDesc method)
+ {
+ return _interfaceDispatchCells.GetOrAdd(method);
+ }
+
private class BoolArrayEqualityComparer : IEqualityComparer<bool[]>
{
bool IEqualityComparer<bool[]>.Equals(bool[] x, bool[] y)
@@ -241,6 +258,13 @@ namespace ILCompiler.DependencyAnalysis
return _typeOptionalFields.GetOrAdd(fieldBuilder);
}
+ private NodeCache<TypeDesc, InterfaceDispatchMapNode> _interfaceDispatchMaps;
+
+ internal InterfaceDispatchMapNode InterfaceDispatchMap(TypeDesc type)
+ {
+ return _interfaceDispatchMaps.GetOrAdd(type);
+ }
+
private NodeCache<string, ExternSymbolNode> _externSymbols;
public ISymbolNode ExternSymbol(string name)
@@ -373,6 +397,8 @@ namespace ILCompiler.DependencyAnalysis
NameMangler.CompilationUnitPrefix + "__str_fixup_end",
null);
+ public InterfaceDispatchMapTableNode DispatchMapTable = new InterfaceDispatchMapTableNode();
+
public Dictionary<TypeDesc, List<MethodDesc>> VirtualSlots = new Dictionary<TypeDesc, List<MethodDesc>>();
public Dictionary<ISymbolNode, string> NodeAliases = new Dictionary<ISymbolNode, string>();
@@ -384,6 +410,7 @@ namespace ILCompiler.DependencyAnalysis
graph.AddRoot(GCStaticsRegion, "GC StaticsRegion is always generated");
graph.AddRoot(ThreadStaticsRegion, "ThreadStaticsRegion is always generated");
graph.AddRoot(StringTable, "StringTable is always generated");
+ graph.AddRoot(DispatchMapTable, "DispatchMapTable is always generated");
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs
index db925dd58..4ddfcf2fd 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs
@@ -101,9 +101,9 @@ namespace ILCompiler.DependencyAnalysis
_relocs.Add(symbolReloc);
}
- public void EmitReloc(ISymbolNode symbol, RelocType relocType)
+ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
{
- AddRelocAtOffset(symbol, relocType, _data.Count);
+ AddRelocAtOffset(symbol, relocType, _data.Count, delta);
// And add space for the reloc
switch (relocType)
@@ -119,11 +119,11 @@ namespace ILCompiler.DependencyAnalysis
}
}
- public void EmitPointerReloc(ISymbolNode symbol)
+ public void EmitPointerReloc(ISymbolNode symbol, int delta = 0)
{
if (_target.PointerSize == 8)
{
- EmitReloc(symbol, RelocType.IMAGE_REL_BASED_DIR64);
+ EmitReloc(symbol, RelocType.IMAGE_REL_BASED_DIR64, delta);
}
else
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
index 28af227e3..39cf7269c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
@@ -23,6 +23,7 @@ namespace ILCompiler.DependencyAnalysis
GetGCStaticBase,
GetThreadStaticBase,
DelegateCtor,
+ InterfaceDispatch,
}
public partial class ReadyToRunHelperNode : AssemblyStubNode
@@ -81,6 +82,8 @@ namespace ILCompiler.DependencyAnalysis
return "__GetThreadStaticBase_" + NodeFactory.NameMangler.GetMangledTypeName((TypeDesc)_target);
case ReadyToRunHelperId.DelegateCtor:
return "__DelegateCtor_" + NodeFactory.NameMangler.GetMangledMethodName(((DelegateInfo)_target).Target);
+ case ReadyToRunHelperId.InterfaceDispatch:
+ return "__InterfaceDispatch_" + NodeFactory.NameMangler.GetMangledMethodName((MethodDesc)_target);
default:
throw new NotImplementedException();
}
@@ -95,6 +98,12 @@ namespace ILCompiler.DependencyAnalysis
dependencyList.Add(context.VirtualMethodUse((MethodDesc)_target), "ReadyToRun Virtual Method Call");
return dependencyList;
}
+ else if (_id == ReadyToRunHelperId.InterfaceDispatch)
+ {
+ DependencyList dependencyList = new DependencyList();
+ dependencyList.Add(context.VirtualMethodUse((MethodDesc)_target), "ReadyToRun Interface Method Call");
+ return dependencyList;
+ }
else
{
return null;
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 7149a9097..0aa9678d2 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
@@ -132,6 +132,14 @@ namespace ILCompiler.DependencyAnalysis
}
break;
+ case ReadyToRunHelperId.InterfaceDispatch:
+ {
+ encoder.EmitLEAQ(Register.R10, factory.InterfaceDispatchCell((MethodDesc)Target));
+ AddrMode jmpAddrMode = new AddrMode(Register.R10, null, 0, 0, AddrModeSize.Int64);
+ encoder.EmitJmpToAddrMode(ref jmpAddrMode);
+ }
+ break;
+
default:
throw new NotImplementedException();
}
diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
index 90c2c6e0e..02b717fae 100644
--- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
+++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
@@ -38,6 +38,8 @@
<Compile Include="Compiler\DependencyAnalysis\CppMethodCodeNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\EETypeOptionalFieldsNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\EmbeddedObjectNode.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\InterfaceDispatchCellNode.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\InterfaceDispatchMapTableNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\JumpStubNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\MethodCodeNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\StringDataNode.cs" />
@@ -67,6 +69,7 @@
<Compile Include="Compiler\DependencyAnalysis\Target_X64\Register.cs" />
<Compile Include="Compiler\DependencyAnalysis\Target_X64\X64Emitter.cs" />
<Compile Include="Compiler\DependencyAnalysis\Target_X64\X64ReadyToRunHelperNode.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\InterfaceDispatchMapNode.cs" />
<Compile Include="Compiler\JitHelper.cs" />
<Compile Include="Compiler\MemoryHelper.cs" />
<Compile Include="Compiler\MethodExtensions.cs" />
diff --git a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
index 887989b3d..6df1eeab2 100644
--- a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
+++ b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
@@ -44,8 +44,10 @@
<Compile Include="..\..\Common\src\TypeSystem\Common\InstantiatedMethod.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\InstantiatedType.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\InstantiatedType.Interfaces.cs" />
+ <Compile Include="..\..\Common\src\TypeSystem\Common\InstantiatedType.MethodImpls.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\MetadataType.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\MetadataType.Interfaces.cs" />
+ <Compile Include="..\..\Common\src\TypeSystem\Common\MetadataType.MethodImpls.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\MetadataFieldLayoutAlgorithm.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\MetadataRuntimeInterfacesAlgorithm.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\MethodForInstantiatedType.cs" />
@@ -64,7 +66,6 @@
<Compile Include="..\..\Common\src\TypeSystem\Common\MethodDesc.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\VirtualFunctionResolution.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\TypeDesc.cs" />
- <Compile Include="..\..\Common\src\TypeSystem\Common\TypeDesc.MethodImpls.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\TypeDesc.Interfaces.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\DefType.cs" />
<Compile Include="..\..\Common\src\TypeSystem\Common\DefType.FieldLayout.cs" />
diff --git a/src/ILCompiler/repro/Program.cs b/src/ILCompiler/repro/Program.cs
index 328ce8871..f01202ea1 100644
--- a/src/ILCompiler/repro/Program.cs
+++ b/src/ILCompiler/repro/Program.cs
@@ -10,4 +10,3 @@ internal class Program
Console.WriteLine("Hello world");
}
}
-
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs
index 3c2efd7f5..2a3895fdb 100644
--- a/src/JitInterface/src/CorInfoImpl.cs
+++ b/src/JitInterface/src/CorInfoImpl.cs
@@ -1826,11 +1826,7 @@ namespace Internal.JitInterface
directCall = true;
}
}
-
- // TODO: Interface methods
- if (targetMethod.IsVirtual && targetMethod.OwningType.IsInterface)
- throw new NotImplementedException("Interface method");
-
+
pResult.hMethod = ObjectToHandle(targetMethod);
pResult.methodFlags = getMethodAttribsInternal(targetMethod);
@@ -1867,8 +1863,21 @@ namespace Internal.JitInterface
pResult._exactContextNeedsRuntimeLookup = 0;
pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = false;
+
+ if (directCall)
+ {
+ if (targetMethod.IsConstructor && targetMethod.OwningType.IsString)
+ {
+ // Calling a string constructor doesn't call the actual constructor.
+ targetMethod = targetMethod.GetStringInitializer();
+ }
- if (!directCall)
+ pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL;
+ pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE;
+ pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.MethodEntrypoint(targetMethod));
+ pResult.nullInstanceCheck = resolvedCallVirt;
+ }
+ else if (!targetMethod.OwningType.IsInterface)
{
// CORINFO_CALL_CODE_POINTER tells the JIT that this is indirect
// call that should not be inlined.
@@ -1885,17 +1894,13 @@ namespace Internal.JitInterface
}
else
{
- if (targetMethod.IsConstructor && targetMethod.OwningType.IsString)
- {
- // Calling a string constructor doesn't call the actual constructor.
- targetMethod = targetMethod.GetStringInitializer();
- }
-
- pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL;
+ pResult.nullInstanceCheck = true;
+ pResult.kind = CORINFO_CALL_KIND.CORINFO_CALL_CODE_POINTER;
+ pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup = false;
pResult.codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE;
- pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle(_compilation.NodeFactory.MethodEntrypoint(targetMethod));
- pResult.nullInstanceCheck = resolvedCallVirt;
+ pResult.codePointerOrStubLookup.constLookup.addr =
+ (void*)ObjectToHandle(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.InterfaceDispatch, targetMethod));
}
// TODO: Generics
diff --git a/src/Native/Bootstrap/main.cpp b/src/Native/Bootstrap/main.cpp
index a3aeb341a..67b53c6af 100644
--- a/src/Native/Bootstrap/main.cpp
+++ b/src/Native/Bootstrap/main.cpp
@@ -232,18 +232,6 @@ extern "C" void RhGetCurrentThreadStackTrace()
throw "RhGetCurrentThreadStackTrace";
}
-extern "C" void RhpGetDispatchCellInfo()
-{
- throw "RhpGetDispatchCellInfo";
-}
-extern "C" void RhpUpdateDispatchCellCache()
-{
- throw "RhpUpdateDispatchCellCache";
-}
-extern "C" void RhpSearchDispatchCellCache()
-{
- throw "RhpSearchDispatchCellCache";
-}
extern "C" void RhCollect()
{
throw "RhCollect";
@@ -285,6 +273,9 @@ extern "C" void RhReRegisterForFinalize()
throw "RhReRegisterForFinalize";
}
+extern "C" void * g_pDispatchMapTemporaryWorkaround;
+void * g_pDispatchMapTemporaryWorkaround;
+
#ifndef CPPCODEGEN
SimpleModuleHeader __module = { NULL, NULL /* &__gcStatics, &__gcStaticsDescs */ };
@@ -388,6 +379,7 @@ int __strings_fixup()
return 0;
}
+extern "C" void* __InterfaceDispatchMapTable;
extern "C" void* __GCStaticRegionStart;
extern "C" void* __GCStaticRegionEnd;
int __statics_fixup()
@@ -405,6 +397,7 @@ int __statics_fixup()
int main(int argc, char * argv[]) {
if (__initialize_runtime() != 0) return -1;
__register_module(&__module);
+ g_pDispatchMapTemporaryWorkaround = (void*)&__InterfaceDispatchMapTable;
ReversePInvokeFrame frame; __reverse_pinvoke(&frame);
if (__strings_fixup() != 0) return -1;
diff --git a/src/Native/Runtime/CMakeLists.txt b/src/Native/Runtime/CMakeLists.txt
index afafa46d8..af604f64c 100644
--- a/src/Native/Runtime/CMakeLists.txt
+++ b/src/Native/Runtime/CMakeLists.txt
@@ -1,6 +1,7 @@
set(COMMON_RUNTIME_SOURCES
allocheap.cpp
assert.cpp
+ CachedInterfaceDispatch.cpp
Crst.cpp
DebugEventSource.cpp
dllmain.cpp
@@ -77,6 +78,8 @@ if(WIN32)
list(APPEND RUNTIME_SOURCES_ARCH_ASM
${ARCH_SOURCES_DIR}/GC.${ASM_SUFFIX}
+ ${ARCH_SOURCES_DIR}/StubDispatch.${ASM_SUFFIX}
+ ${ARCH_SOURCES_DIR}/ManagedCalloutThunk.${ASM_SUFFIX}
)
else()
@@ -120,7 +123,7 @@ add_definitions(-DFEATURE_PROFILING)
add_definitions(-DFEATURE_REDHAWK)
add_definitions(-DVERIFY_HEAP)
add_definitions(-DCORERT)
-
+add_definitions(-DFEATURE_CACHED_INTERFACE_DISPATCH)
add_definitions(-D_LIB)
if(WIN32)
diff --git a/src/Native/Runtime/CachedInterfaceDispatch.cpp b/src/Native/Runtime/CachedInterfaceDispatch.cpp
index 5735336eb..4a1582044 100644
--- a/src/Native/Runtime/CachedInterfaceDispatch.cpp
+++ b/src/Native/Runtime/CachedInterfaceDispatch.cpp
@@ -11,31 +11,30 @@
#include "common.h"
#ifdef FEATURE_CACHED_INTERFACE_DISPATCH
-#include "commontypes.h"
-#include "commonmacros.h"
+#include "CommonTypes.h"
+#include "CommonMacros.h"
#include "daccess.h"
-#include "debugmacrosext.h"
-#include "palredhawkcommon.h"
-#include "palredhawk.h"
+#include "DebugMacrosExt.h"
+#include "PalRedhawkCommon.h"
+#include "PalRedhawk.h"
#include "assert.h"
#include "slist.h"
#include "holder.h"
-#include "crst.h"
-#include "redhawkwarnings.h"
-#include "targetptrs.h"
+#include "Crst.h"
+#include "RedhawkWarnings.h"
+#include "TargetPtrs.h"
#include "eetype.h"
-#include "range.h"
-#include "memaccessmgr.h"
+#include "Range.h"
#include "allocheap.h"
#include "rhbinder.h"
-#include "objectlayout.h"
+#include "ObjectLayout.h"
#include "gcrhinterface.h"
#include "module.h"
-#include "rwlock.h"
-#include "runtimeinstance.h"
+#include "RWLock.h"
+#include "RuntimeInstance.h"
#include "eetype.inl"
-#include "cachedinterfacedispatch.h"
+#include "CachedInterfaceDispatch.h"
extern "C" UIntTarget __fastcall ManagedCallout2(UIntTarget argument1, UIntTarget argument2, void *pTargetMethod, void *pPreviousManagedFrame);
diff --git a/src/Native/Runtime/inc/eetype.h b/src/Native/Runtime/inc/eetype.h
index 4d9e6b3ca..624411b29 100644
--- a/src/Native/Runtime/inc/eetype.h
+++ b/src/Native/Runtime/inc/eetype.h
@@ -14,6 +14,8 @@ class MdilModule;
class EEType;
class OptionalFields;
+
+
//-------------------------------------------------------------------------------------------------
// Array of these represents the interfaces implemented by a type
diff --git a/src/Native/Runtime/inc/eetype.inl b/src/Native/Runtime/inc/eetype.inl
index 9a1c774a0..4d5c3ae16 100644
--- a/src/Native/Runtime/inc/eetype.inl
+++ b/src/Native/Runtime/inc/eetype.inl
@@ -152,6 +152,10 @@ inline bool EEType::HasDispatchMap()
return true;
}
+#ifdef CORERT
+extern "C" void * g_pDispatchMapTemporaryWorkaround;
+#endif
+
inline DispatchMap * EEType::GetDispatchMap()
{
if (!HasInterfaces())
@@ -172,6 +176,11 @@ inline DispatchMap * EEType::GetDispatchMap()
// Determine this EEType's module.
RuntimeInstance * pRuntimeInstance = GetRuntimeInstance();
+
+#ifdef CORERT
+ return (DispatchMap*)((void**)g_pDispatchMapTemporaryWorkaround)[idxDispatchMap];
+#endif
+
Module * pModule = pRuntimeInstance->FindModuleByReadOnlyDataAddress(this);
if (pModule == NULL)
pModule = pRuntimeInstance->FindModuleByDataAddress(this);
diff --git a/src/Native/Runtime/portable.cpp b/src/Native/Runtime/portable.cpp
index c80f89fbb..fa5f47b31 100644
--- a/src/Native/Runtime/portable.cpp
+++ b/src/Native/Runtime/portable.cpp
@@ -230,11 +230,54 @@ COOP_PINVOKE_HELPER(MDArray *, RhNewMDArray, (EEType * pArrayEEType, UInt32 rank
return pObject;
}
+#if defined(USE_PORTABLE_HELPERS) || !defined(WIN32)
COOP_PINVOKE_HELPER(void, RhpInitialDynamicInterfaceDispatch, ())
{
ASSERT_UNCONDITIONALLY("NYI");
}
+COOP_PINVOKE_HELPER(void, RhpInterfaceDispatch1, ())
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+}
+
+COOP_PINVOKE_HELPER(void, RhpInterfaceDispatch2, ())
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+}
+
+COOP_PINVOKE_HELPER(void, RhpInterfaceDispatch4, ())
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+}
+
+COOP_PINVOKE_HELPER(void, RhpInterfaceDispatch8, ())
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+}
+
+COOP_PINVOKE_HELPER(void, RhpInterfaceDispatch16, ())
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+}
+
+COOP_PINVOKE_HELPER(void, RhpInterfaceDispatch32, ())
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+}
+
+COOP_PINVOKE_HELPER(void, RhpInterfaceDispatch64, ())
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+}
+
+COOP_PINVOKE_HELPER(UIntTarget, ManagedCallout2, (UIntTarget argument1, UIntTarget argument2, void *pTargetMethod, void *pPreviousManagedFrame))
+{
+ ASSERT_UNCONDITIONALLY("NYI");
+ return 0;
+}
+#endif
+
// finalizer.cs
COOP_PINVOKE_HELPER(void, ProcessFinalizers, ())
{
diff --git a/src/Native/Runtime/unix/PalRedhawkInline.h b/src/Native/Runtime/unix/PalRedhawkInline.h
index a09fac876..820e262d2 100644
--- a/src/Native/Runtime/unix/PalRedhawkInline.h
+++ b/src/Native/Runtime/unix/PalRedhawkInline.h
@@ -46,10 +46,10 @@ FORCEINLINE Int64 PalInterlockedCompareExchange64(_Inout_ _Interlocked_operand_
}
#if defined(_AMD64_)
-EXTERN_C UInt8 _InterlockedCompareExchange128(Int64 volatile *, Int64, Int64, Int64 *);
FORCEINLINE UInt8 PalInterlockedCompareExchange128(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValueHigh, Int64 iValueLow, Int64 *pComperand)
{
- return _InterlockedCompareExchange128(pDst, iValueHigh, iValueLow, pComperand);
+ ASSERT_UNCONDITIONALLY("NYI");
+ return 0;
}
#endif // _AMD64_
diff --git a/src/System.Private.CoreLib/src/System/Activator.cs b/src/System.Private.CoreLib/src/System/Activator.cs
index b5c00e098..6c7065b86 100644
--- a/src/System.Private.CoreLib/src/System/Activator.cs
+++ b/src/System.Private.CoreLib/src/System/Activator.cs
@@ -67,7 +67,16 @@ namespace System
}
[Intrinsic]
+#if CORERT
+ // CORERT-TODO: Add CreateInstanceIntrinsic intrinsic support.
+ // https://github.com/dotnet/corert/issues/368
+ private static T CreateInstanceIntrinsic<T>()
+ {
+ throw new NotSupportedException("CreateInstance");
+ }
+#else
private extern static T CreateInstanceIntrinsic<T>();
+#endif
[ThreadStatic]
internal static bool s_createInstanceMissingDefaultConstructor;