public override bool ShouldProduceFullType(TypeDesc type) { // TODO: Remove this once we have delgate constructor transform added and GetMethods() tells us about // the virtuals we add on to delegate types. if (type.IsDelegate) { return(false); } // Fully build all types when building a library if (BuildingLibrary) { return(true); } // Fully build all shareable types so they will be identical in each module if (EETypeNode.IsTypeNodeShareable(type)) { return(true); } // If referring to a type from another module, VTables, interface maps, etc should assume the // type is fully build. if (!ContainsType(type)) { return(true); } return(false); }
private void AddTypeNode(EETypeNode node) { if (node != null && !_nodes.Contains(node) && !_visited.Contains(node)) { _visited.Add(node); EETypeNode baseTypeNode; if (node.Type.BaseType != null) { TypeDesc baseType = node.Type.BaseType; if (!node.Type.IsGenericDefinition && baseType.IsCanonicalSubtype(CanonicalFormKind.Any)) { baseType = baseType.ConvertToCanonForm(CanonicalFormKind.Specific); } _typeToNodeMap.TryGetValue(baseType, out baseTypeNode); if (!node.Type.IsPrimitive) { AddTypeNode(baseTypeNode); } else if (!_nodes.Contains(baseTypeNode)) { _nodes.Add(baseTypeNode); } } if (!node.Type.IsGenericDefinition) { foreach (var field in node.Type.GetFields()) { EETypeNode fieldNode; _typeToNodeMap.TryGetValue(field.FieldType, out fieldNode); if (fieldNode == null) { if (field.FieldType.IsValueType) { AddTypeNode((EETypeNode)_factory.NecessaryTypeSymbol(field.FieldType)); } } else { if (fieldNode.Type.IsValueType) { if (!fieldNode.Type.IsPrimitive) { AddTypeNode(fieldNode); } else if (!_nodes.Contains(fieldNode)) { _nodes.Add(fieldNode); } } } } } if (!_nodes.Contains(node)) { _nodes.Add(node); } } }
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 ExternalTypeNode(NodeFactory factory, TypeDesc type) { _type = type; // // This check encodes rules specific to CoreRT. Ie, no function pointer classes allowed. // Eventually we will hit situations where this check fails when it shouldn't and we'll need to // split the logic. It's a good sanity check for the time being though. // EETypeNode.CheckCanGenerateEEType(factory, type); }
private void AddTypeNode(EETypeNode node) { if (node != null && !_nodes.Contains(node) && !_visited.Contains(node)) { _visited.Add(node); EETypeNode baseTypeNode; if (node.Type.BaseType != null) { _typeToNodeMap.TryGetValue(node.Type.BaseType, out baseTypeNode); if (!node.Type.IsPrimitive) { AddTypeNode(baseTypeNode); } else if (!_nodes.Contains(baseTypeNode)) { _nodes.Add(baseTypeNode); } } if (!node.Type.IsGenericDefinition) { foreach (var field in node.Type.GetFields()) { EETypeNode fieldNode; _typeToNodeMap.TryGetValue(field.FieldType, out fieldNode); if (fieldNode == null) { if (field.FieldType.IsValueType) { AddTypeNode((EETypeNode)_factory.NecessaryTypeSymbol(field.FieldType)); } } else { if (fieldNode.Type.IsValueType) { if (!fieldNode.Type.IsPrimitive) { AddTypeNode(fieldNode); } else if (!_nodes.Contains(fieldNode)) { _nodes.Add(fieldNode); } } } } } if (!_nodes.Contains(node)) { _nodes.Add(node); } } }
public override bool ShouldProduceFullType(TypeDesc type) { // Fully build all shareable types so they will be identical in each module if (EETypeNode.IsTypeNodeShareable(type)) { return(true); } // If referring to a type from another module, VTables, interface maps, etc should assume the // type is fully build. if (!ContainsType(type)) { return(true); } return(false); }
private void AddTypeNode(EETypeNode node) { if (node != null && !_nodes.Contains(node) && !_visited.Contains(node)) { _visited.Add(node); EETypeNode baseTypeNode; if (node.Type.BaseType != null) { _typeToNodeMap.TryGetValue(node.Type.BaseType, out baseTypeNode); if (!node.Type.IsPrimitive) { AddTypeNode(baseTypeNode); } else if (!_nodes.Contains(baseTypeNode)) { _nodes.Add(baseTypeNode); } } foreach (var field in node.Type.GetFields()) { EETypeNode fieldNode; _typeToNodeMap.TryGetValue(field.FieldType, out fieldNode); if (fieldNode != null) { if (fieldNode.Type.IsValueType) { if (!fieldNode.Type.IsPrimitive) { AddTypeNode(fieldNode); } else if (!_nodes.Contains(fieldNode)) { _nodes.Add(fieldNode); } } } } if (!_nodes.Contains(node)) { _nodes.Add(node); } } }
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)); }