diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
index 6b5c0e14764..f33185e4fc3 100644
--- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
@@ -182,6 +182,118 @@ public bool HasFixedSlotVTable(TypeDesc type)
return NodeFactory.VTable(type).HasFixedSlots;
}
+ public bool NeedsRuntimeLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
+ {
+ switch (lookupKind)
+ {
+ case ReadyToRunHelperId.TypeHandle:
+ case ReadyToRunHelperId.NecessaryTypeHandle:
+ case ReadyToRunHelperId.DefaultConstructor:
+ return ((TypeDesc)targetOfLookup).IsRuntimeDeterminedSubtype;
+
+ case ReadyToRunHelperId.MethodDictionary:
+ case ReadyToRunHelperId.MethodEntry:
+ case ReadyToRunHelperId.VirtualDispatchCell:
+ case ReadyToRunHelperId.MethodHandle:
+ return ((MethodDesc)targetOfLookup).IsRuntimeDeterminedExactMethod;
+
+ case ReadyToRunHelperId.FieldHandle:
+ return ((FieldDesc)targetOfLookup).OwningType.IsRuntimeDeterminedSubtype;
+
+ default:
+ throw new NotImplementedException();
+ }
+ }
+
+ public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
+ {
+ switch (lookupKind)
+ {
+ case ReadyToRunHelperId.TypeHandle:
+ return NodeFactory.ConstructedTypeSymbol((TypeDesc)targetOfLookup);
+ case ReadyToRunHelperId.NecessaryTypeHandle:
+ return NodeFactory.NecessaryTypeSymbol((TypeDesc)targetOfLookup);
+ case ReadyToRunHelperId.MethodDictionary:
+ return NodeFactory.MethodGenericDictionary((MethodDesc)targetOfLookup);
+ case ReadyToRunHelperId.MethodEntry:
+ return NodeFactory.FatFunctionPointer((MethodDesc)targetOfLookup);
+ case ReadyToRunHelperId.MethodHandle:
+ return NodeFactory.RuntimeMethodHandle((MethodDesc)targetOfLookup);
+ case ReadyToRunHelperId.FieldHandle:
+ return NodeFactory.RuntimeFieldHandle((FieldDesc)targetOfLookup);
+ case ReadyToRunHelperId.DefaultConstructor:
+ {
+ var type = (TypeDesc)targetOfLookup;
+ MethodDesc ctor = type.GetDefaultConstructor();
+ if (ctor == null)
+ {
+ MetadataType activatorType = TypeSystemContext.SystemModule.GetKnownType("System", "Activator");
+ MetadataType classWithMissingCtor = activatorType.GetKnownNestedType("ClassWithMissingConstructor");
+ ctor = classWithMissingCtor.GetParameterlessConstructor();
+ }
+ return NodeFactory.CanonicalEntrypoint(ctor);
+ }
+
+ default:
+ throw new NotImplementedException();
+ }
+ }
+
+ public GenericDictionaryLookup ComputeGenericLookup(MethodDesc contextMethod, ReadyToRunHelperId lookupKind, object targetOfLookup)
+ {
+ GenericContextSource contextSource;
+
+ if (contextMethod.RequiresInstMethodDescArg())
+ {
+ contextSource = GenericContextSource.MethodParameter;
+ }
+ else if (contextMethod.RequiresInstMethodTableArg())
+ {
+ contextSource = GenericContextSource.TypeParameter;
+ }
+ else
+ {
+ Debug.Assert(contextMethod.AcquiresInstMethodTableFromThis());
+ contextSource = GenericContextSource.ThisObject;
+ }
+
+ // Can we do a fixed lookup? Start by checking if we can get to the dictionary.
+ // Context source having a vtable with fixed slots is a prerequisite.
+ if (contextSource == GenericContextSource.MethodParameter
+ || HasFixedSlotVTable(contextMethod.OwningType))
+ {
+ DictionaryLayoutNode dictionaryLayout;
+ if (contextSource == GenericContextSource.MethodParameter)
+ dictionaryLayout = _nodeFactory.GenericDictionaryLayout(contextMethod);
+ else
+ dictionaryLayout = _nodeFactory.GenericDictionaryLayout(contextMethod.OwningType);
+
+ // If the dictionary layout has fixed slots, we can compute the lookup now. Otherwise defer to helper.
+ if (dictionaryLayout.HasFixedSlots)
+ {
+ int pointerSize = _nodeFactory.Target.PointerSize;
+
+ GenericLookupResult lookup = ReadyToRunGenericHelperNode.GetLookupSignature(_nodeFactory, lookupKind, targetOfLookup);
+ int dictionarySlot = dictionaryLayout.GetSlotForEntry(lookup);
+ int dictionaryOffset = dictionarySlot * pointerSize;
+
+ if (contextSource == GenericContextSource.MethodParameter)
+ {
+ return GenericDictionaryLookup.CreateFixedLookup(contextSource, dictionaryOffset);
+ }
+ else
+ {
+ int vtableSlot = VirtualMethodSlotHelper.GetGenericDictionarySlot(_nodeFactory, contextMethod.OwningType);
+ int vtableOffset = EETypeNode.GetVTableOffset(pointerSize) + vtableSlot * pointerSize;
+ return GenericDictionaryLookup.CreateFixedLookup(contextSource, vtableOffset, dictionaryOffset);
+ }
+ }
+ }
+
+ // Fixed lookup not possible - use helper.
+ return GenericDictionaryLookup.CreateHelperLookup(contextSource);
+ }
+
CompilationResults ICompilation.Compile(string outputFile, ObjectDumper dumper)
{
if (dumper != null)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
index d455326eab2..b85027a02ef 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
@@ -29,8 +29,11 @@ public ReadyToRunGenericHelperNode(NodeFactory factory, ReadyToRunHelperId helpe
_lookupSignature = GetLookupSignature(factory, helperId, target);
}
- private static GenericLookupResult GetLookupSignature(NodeFactory factory, ReadyToRunHelperId id, object target)
+ public static GenericLookupResult GetLookupSignature(NodeFactory factory, ReadyToRunHelperId id, object target)
{
+ // Necessary type handle is not something you can put in a dictionary - someone should have normalized to TypeHandle
+ Debug.Assert(id != ReadyToRunHelperId.NecessaryTypeHandle);
+
switch (id)
{
case ReadyToRunHelperId.TypeHandle:
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
index d3795b96d39..94671a88f45 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
@@ -27,6 +27,7 @@ public enum ReadyToRunHelperId
// The following helpers are used for generic lookups only
TypeHandle,
+ NecessaryTypeHandle,
MethodHandle,
FieldHandle,
MethodDictionary,
diff --git a/src/ILCompiler.Compiler/src/Compiler/GenericDictionaryLookup.cs b/src/ILCompiler.Compiler/src/Compiler/GenericDictionaryLookup.cs
new file mode 100644
index 00000000000..42c7deee73c
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/GenericDictionaryLookup.cs
@@ -0,0 +1,98 @@
+// 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 System;
+
+using Debug = System.Diagnostics.Debug;
+
+namespace ILCompiler
+{
+ ///
+ /// Structure that specifies how a generic dictionary lookup should be performed.
+ ///
+ public struct GenericDictionaryLookup
+ {
+ private const short UseHelperOffset = -1;
+
+ private short _offset1;
+ private short _offset2;
+
+ public readonly GenericContextSource ContextSource;
+
+ public bool UseHelper
+ {
+ get
+ {
+ return _offset1 == UseHelperOffset;
+ }
+ }
+
+ public int NumberOfIndirections
+ {
+ get
+ {
+ Debug.Assert(!UseHelper);
+ return ContextSource == GenericContextSource.MethodParameter ? 1 : 2;
+ }
+ }
+
+ public int this[int index]
+ {
+ get
+ {
+ Debug.Assert(!UseHelper);
+ Debug.Assert(index < NumberOfIndirections);
+ switch (index)
+ {
+ case 0:
+ return _offset1;
+ case 1:
+ return _offset2;
+ }
+
+ // Should be unreachable.
+ throw new NotSupportedException();
+ }
+ }
+
+ private GenericDictionaryLookup(GenericContextSource contextSource, int offset1, int offset2)
+ {
+ ContextSource = contextSource;
+ _offset1 = checked((short)offset1);
+ _offset2 = checked((short)offset2);
+ }
+
+ public static GenericDictionaryLookup CreateFixedLookup(GenericContextSource contextSource, int offset1, int offset2 = UseHelperOffset)
+ {
+ Debug.Assert(offset1 != UseHelperOffset);
+ return new GenericDictionaryLookup(contextSource, offset1, offset2);
+ }
+
+ public static GenericDictionaryLookup CreateHelperLookup(GenericContextSource contextSource)
+ {
+ return new GenericDictionaryLookup(contextSource, UseHelperOffset, UseHelperOffset);
+ }
+ }
+
+ ///
+ /// Specifies to source of the generic context.
+ ///
+ public enum GenericContextSource
+ {
+ ///
+ /// Generic context is specified by a hidden parameter that has a method dictionary.
+ ///
+ MethodParameter,
+
+ ///
+ /// Generic context is specified by a hidden parameter that has a type.
+ ///
+ TypeParameter,
+
+ ///
+ /// Generic context is specified implicitly by the `this` object.
+ ///
+ ThisObject,
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
index 47fdf19c403..b5352997c71 100644
--- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
+++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
@@ -262,6 +262,7 @@
+
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs
index ebfb2ecce1e..70585ca1742 100644
--- a/src/JitInterface/src/CorInfoImpl.cs
+++ b/src/JitInterface/src/CorInfoImpl.cs
@@ -867,64 +867,78 @@ private void getMethodVTableOffset(CORINFO_METHOD_STRUCT_* method, ref uint offs
return impl != null ? ObjectToHandle(impl) : null;
}
- private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult)
+ private void ComputeLookup(CORINFO_CONTEXT_STRUCT* pContextMethod, object entity, ReadyToRunHelperId helperId, ref CORINFO_LOOKUP lookup)
{
- // Resolved token as a potentially RuntimeDetermined object.
- MethodDesc method = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
-
- if (method.IsRuntimeDeterminedExactMethod)
+ if (_compilation.NeedsRuntimeLookup(helperId, entity))
{
- pResult.lookup.lookupKind.needsRuntimeLookup = true;
- pResult.lookup.runtimeLookup.signature = null;
- pResult.lookup.runtimeLookup.indirections = CORINFO.USEHELPER;
+ lookup.lookupKind.needsRuntimeLookup = true;
+ lookup.runtimeLookup.signature = null;
- MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
+ MethodDesc contextMethod = methodFromContext(pContextMethod);
// Do not bother computing the runtime lookup if we are inlining. The JIT is going
// to abort the inlining attempt anyway.
- if (contextMethod == MethodBeingCompiled)
+ if (contextMethod != MethodBeingCompiled)
+ return;
+
+ // Necessary type handle is not something that can be in a dictionary (only a constructed type).
+ // We only use necessary type handles if we can do a constant lookup.
+ if (helperId == ReadyToRunHelperId.NecessaryTypeHandle)
+ helperId = ReadyToRunHelperId.TypeHandle;
+
+ GenericDictionaryLookup genericLookup = _compilation.ComputeGenericLookup(contextMethod, helperId, entity);
+
+ if (genericLookup.UseHelper)
{
- switch (method.Name)
+ lookup.runtimeLookup.indirections = CORINFO.USEHELPER;
+ lookup.lookupKind.runtimeLookupFlags = (ushort)helperId;
+ lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(entity);
+ }
+ else
+ {
+ if (genericLookup.ContextSource == GenericContextSource.MethodParameter)
+ {
+ lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_METHOD;
+ }
+ else
{
- case "EETypePtrOf":
- pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.TypeHandle;
- pResult.lookup.lookupKind.runtimeLookupArgs = ObjectToHandle(method.Instantiation[0]);
- break;
- case "DefaultConstructorOf":
- pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.DefaultConstructor;
- pResult.lookup.lookupKind.runtimeLookupArgs = ObjectToHandle(method.Instantiation[0]);
- break;
- default:
- Debug.Assert(false);
- break;
+ lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_CLASS;
}
- pResult.lookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
+ lookup.runtimeLookup.indirections = (ushort)genericLookup.NumberOfIndirections;
+ lookup.runtimeLookup.offset0 = (IntPtr)genericLookup[0];
+ if (genericLookup.NumberOfIndirections > 1)
+ lookup.runtimeLookup.offset1 = (IntPtr)genericLookup[1];
+ lookup.runtimeLookup.testForFixup = false; // TODO: this will be needed in true multifile
+ lookup.runtimeLookup.testForNull = false;
+ lookup.runtimeLookup.indirectFirstOffset = false;
+ lookup.lookupKind.runtimeLookupFlags = 0;
+ lookup.lookupKind.runtimeLookupArgs = null;
}
+
+ lookup.lookupKind.runtimeLookupKind = GetLookupKindFromContextSource(genericLookup.ContextSource);
}
else
{
- pResult.lookup.lookupKind.needsRuntimeLookup = false;
-
- switch (method.Name)
- {
- case "EETypePtrOf":
- pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ConstructedTypeSymbol(method.Instantiation[0]));
- break;
- case "DefaultConstructorOf":
- MethodDesc ctor = method.Instantiation[0].GetDefaultConstructor();
- if (ctor == null)
- {
- MetadataType activatorType = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "Activator");
- MetadataType classWithMissingCtor = activatorType.GetKnownNestedType("ClassWithMissingConstructor");
- ctor = classWithMissingCtor.GetParameterlessConstructor();
- }
- pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.CanonicalEntrypoint(ctor));
- break;
- default:
- Debug.Assert(false);
- break;
- }
+ lookup.lookupKind.needsRuntimeLookup = false;
+ ISymbolNode constLookup = _compilation.ComputeConstantLookup(helperId, entity);
+ lookup.constLookup = CreateConstLookupToSymbol(constLookup);
+ }
+ }
+
+ private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult)
+ {
+ // Resolved token as a potentially RuntimeDetermined object.
+ MethodDesc method = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
+
+ switch (method.Name)
+ {
+ case "EETypePtrOf":
+ ComputeLookup(pResolvedToken.tokenContext, method.Instantiation[0], ReadyToRunHelperId.TypeHandle, ref pResult.lookup);
+ break;
+ case "DefaultConstructorOf":
+ ComputeLookup(pResolvedToken.tokenContext, method.Instantiation[0], ReadyToRunHelperId.DefaultConstructor, ref pResult.lookup);
+ break;
}
}
@@ -1497,6 +1511,11 @@ private CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_STRUCT_* cls)
private ISymbolNode GetGenericLookupHelper(CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind, ReadyToRunHelperId helperId, object helperArgument)
{
+ // Necessary type handle is not something that can be in a dictionary (only a constructed type).
+ // We only use necessary type handles if we can do a constant lookup.
+ if (helperId == ReadyToRunHelperId.NecessaryTypeHandle)
+ helperId = ReadyToRunHelperId.TypeHandle;
+
if (runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ
|| runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM)
{
@@ -2605,7 +2624,8 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
fixed (CORINFO_GENERICHANDLE_RESULT* tmp = &pResult)
MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf());
#endif
- bool runtimeLookup;
+ ReadyToRunHelperId helperId = ReadyToRunHelperId.Invalid;
+ object target = null;
if (!fEmbedParent && pResolvedToken.hMethod != null)
{
@@ -2616,28 +2636,17 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
Debug.Assert(md.OwningType == td);
- runtimeLookup = md.IsSharedByGenericInstantiations;
-
pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)ObjectToHandle(md);
- if (!runtimeLookup)
- {
- if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken)
- pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.RuntimeMethodHandle(md));
- else
- throw new NotImplementedException();
- }
+ if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken)
+ helperId = ReadyToRunHelperId.MethodHandle;
else
{
- if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken)
- pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.MethodHandle;
- else if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Method)
- pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.MethodDictionary;
- else
- throw new NotImplementedException();
-
- pResult.lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
+ Debug.Assert(pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Method);
+ helperId = ReadyToRunHelperId.MethodDictionary;
}
+
+ target = GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
}
else if (!fEmbedParent && pResolvedToken.hField != null)
{
@@ -2647,19 +2656,9 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_FIELD;
pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)pResolvedToken.hField;
- runtimeLookup = fd.IsStatic && td.IsCanonicalSubtype(CanonicalFormKind.Any);
-
- if (!runtimeLookup)
- {
- Debug.Assert(pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken);
- pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.RuntimeFieldHandle(fd));
- }
- else
- {
- Debug.Assert(pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken);
- pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.FieldHandle;
- pResult.lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
- }
+ Debug.Assert(pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken);
+ helperId = ReadyToRunHelperId.FieldHandle;
+ target = GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
}
else
{
@@ -2668,69 +2667,38 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_CLASS;
pResult.compileTimeHandle = (CORINFO_GENERIC_STRUCT_*)pResolvedToken.hClass;
- runtimeLookup = td.IsCanonicalSubtype(CanonicalFormKind.Any);
-
- if (!runtimeLookup)
+ object obj = GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
+ target = obj as TypeDesc;
+ if (target == null)
{
- if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_NewObj
- || pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Box
- || (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken && ConstructedEETypeNode.CreationAllowed(td)))
+ Debug.Assert(fEmbedParent);
+
+ if (obj is MethodDesc)
{
- pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ConstructedTypeSymbol(td));
+ target = ((MethodDesc)obj).OwningType;
}
else
{
- pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.NecessaryTypeSymbol(td));
+ Debug.Assert(obj is FieldDesc);
+ target = ((FieldDesc)obj).OwningType;
}
}
+
+ if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_NewObj
+ || pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Box
+ || (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken && ConstructedEETypeNode.CreationAllowed(td)))
+ {
+ helperId = ReadyToRunHelperId.TypeHandle;
+ }
else
{
- pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.TypeHandle;
-
- object obj = GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
- TypeDesc type = obj as TypeDesc;
- if (type == null)
- {
- Debug.Assert(fEmbedParent);
-
- if (obj is MethodDesc)
- {
- type = ((MethodDesc)obj).OwningType;
- }
- else
- {
- Debug.Assert(obj is FieldDesc);
- type = ((FieldDesc)obj).OwningType;
- }
- }
-
- pResult.lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(type);
+ helperId = ReadyToRunHelperId.NecessaryTypeHandle;
}
}
Debug.Assert(pResult.compileTimeHandle != null);
-
- if (runtimeLookup)
- {
- pResult.lookup.lookupKind.needsRuntimeLookup = true;
- pResult.lookup.runtimeLookup.signature = null;
- pResult.lookup.runtimeLookup.indirections = CORINFO.USEHELPER;
-
- MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
-
- // Do not bother computing the runtime lookup if we are inlining. The JIT is going
- // to abort the inlining attempt anyway.
- if (contextMethod != MethodBeingCompiled)
- return;
-
- pResult.lookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
- }
- else
- {
- // If the target is not shared then we've already got our result and
- // can simply do a static look up
- pResult.lookup.lookupKind.needsRuntimeLookup = false;
- }
+
+ ComputeLookup(pResolvedToken.tokenContext, target, helperId, ref pResult.lookup);
}
private CORINFO_RUNTIME_LOOKUP_KIND GetGenericRuntimeLookupKind(MethodDesc method)
@@ -2746,6 +2714,20 @@ private CORINFO_RUNTIME_LOOKUP_KIND GetGenericRuntimeLookupKind(MethodDesc metho
}
}
+ private CORINFO_RUNTIME_LOOKUP_KIND GetLookupKindFromContextSource(GenericContextSource contextSource)
+ {
+ switch (contextSource)
+ {
+ case GenericContextSource.MethodParameter:
+ return CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_METHODPARAM;
+ case GenericContextSource.TypeParameter:
+ return CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM;
+ default:
+ Debug.Assert(contextSource == GenericContextSource.ThisObject);
+ return CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ;
+ }
+ }
+
private void getLocationOfThisType(out CORINFO_LOOKUP_KIND result, CORINFO_METHOD_STRUCT_* context)
{
result = new CORINFO_LOOKUP_KIND();
@@ -3078,18 +3060,11 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
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.MethodHandle;
- pResult.codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
- }
+ ComputeLookup(pResolvedToken.tokenContext,
+ GetRuntimeDeterminedObjectForToken(ref pResolvedToken),
+ ReadyToRunHelperId.MethodHandle,
+ ref pResult.codePointerOrStubLookup);
+ Debug.Assert(pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup);
}
// RyuJIT will assert if we report CORINFO_CALLCONV_PARAMTYPE for a result of a ldvirtftn
@@ -3104,18 +3079,11 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
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));
- }
+ ComputeLookup(pResolvedToken.tokenContext,
+ GetRuntimeDeterminedObjectForToken(ref pResolvedToken),
+ ReadyToRunHelperId.VirtualDispatchCell,
+ ref pResult.codePointerOrStubLookup);
+ Debug.Assert(pResult.codePointerOrStubLookup.lookupKind.needsRuntimeLookup);
}
else
{
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 212aa98b9e3..85eb8a03cd2 100644
--- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
+++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
@@ -102,6 +102,24 @@ public bool HasFixedSlotVTable(TypeDesc type)
return true;
}
+ public bool NeedsRuntimeLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
+ {
+ // The current plan seem to be to copy paste from ILCompiler.Compilation, but that's not a sustainable plan
+ throw new NotImplementedException();
+ }
+
+ public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
+ {
+ // The current plan seem to be to copy paste from ILCompiler.Compilation, but that's not a sustainable plan
+ throw new NotImplementedException();
+ }
+
+ public GenericDictionaryLookup ComputeGenericLookup(MethodDesc contextMethod, ReadyToRunHelperId lookupKind, object targetOfLookup)
+ {
+ // The current plan seem to be to copy paste from ILCompiler.Compilation, but that's not a sustainable plan
+ throw new NotImplementedException();
+ }
+
public DelegateCreationInfo GetDelegateCtor(TypeDesc delegateType, MethodDesc target, bool followVirtualDispatch)
{
return DelegateCreationInfo.Create(delegateType, target, NodeFactory, followVirtualDispatch);
diff --git a/src/System.Private.Jit/src/System.Private.Jit.csproj b/src/System.Private.Jit/src/System.Private.Jit.csproj
index e8a31aaf119..8d303aa3e60 100644
--- a/src/System.Private.Jit/src/System.Private.Jit.csproj
+++ b/src/System.Private.Jit/src/System.Private.Jit.csproj
@@ -116,6 +116,7 @@
+