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)); }
public GenericDictionaryLookup ComputeGenericLookup(MethodDesc contextMethod, ReadyToRunHelperId lookupKind, object targetOfLookup) { if (targetOfLookup is TypeSystemEntity typeSystemEntity) { _nodeFactory.TypeSystemContext.DetectGenericCycles(contextMethod, typeSystemEntity); } GenericContextSource contextSource; if (contextMethod.RequiresInstMethodDescArg()) { contextSource = GenericContextSource.MethodParameter; } else if (contextMethod.RequiresInstMethodTableArg()) { contextSource = GenericContextSource.TypeParameter; } else { Debug.Assert(contextMethod.AcquiresInstMethodTableFromThis()); contextSource = GenericContextSource.ThisObject; } // // Some helpers represent logical concepts that might not be something that can be looked up in a dictionary // // Downgrade type handle for casting to a normal type handle if possible if (lookupKind == ReadyToRunHelperId.TypeHandleForCasting) { var type = (TypeDesc)targetOfLookup; if (!type.IsRuntimeDeterminedType || (!((RuntimeDeterminedType)type).CanonicalType.IsCanonicalDefinitionType(CanonicalFormKind.Universal) && !((RuntimeDeterminedType)type).CanonicalType.IsNullable)) { if (type.IsNullable) { targetOfLookup = type.Instantiation[0]; } lookupKind = ReadyToRunHelperId.NecessaryTypeHandle; } } // We don't have separate entries for necessary type handles to avoid possible duplication if (lookupKind == ReadyToRunHelperId.NecessaryTypeHandle) { lookupKind = ReadyToRunHelperId.TypeHandle; } // 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.GetSlotForFixedEntry(lookup); if (dictionarySlot != -1) { int dictionaryOffset = dictionarySlot * pointerSize; bool indirectLastOffset = lookup.LookupResultReferenceType(_nodeFactory) == GenericLookupResultReferenceType.Indirect; if (contextSource == GenericContextSource.MethodParameter) { return(GenericDictionaryLookup.CreateFixedLookup(contextSource, dictionaryOffset, indirectLastOffset: indirectLastOffset)); } else { int vtableSlot = VirtualMethodSlotHelper.GetGenericDictionarySlot(_nodeFactory, contextMethod.OwningType); int vtableOffset = EETypeNode.GetVTableOffset(pointerSize) + vtableSlot * pointerSize; return(GenericDictionaryLookup.CreateFixedLookup(contextSource, vtableOffset, dictionaryOffset, indirectLastOffset: indirectLastOffset)); } } } } // Fixed lookup not possible - use helper. return(GenericDictionaryLookup.CreateHelperLookup(contextSource, lookupKind, targetOfLookup)); }