protected override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { if (!ConstructedEETypeNode.CreationAllowed(type)) { // Both EETypeNode and ConstructedEETypeNode call into this logic. EETypeNode will only call for unconstructable // EETypes. We don't have templates for those. return; } DefType closestDefType = type.GetClosestDefType(); // TODO-SIZE: this is overly generous in the templates we create if (closestDefType.HasInstantiation) { TypeDesc canonType = type.ConvertToCanonForm(CanonicalFormKind.Specific); TypeDesc canonClosestDefType = closestDefType.ConvertToCanonForm(CanonicalFormKind.Specific); // Add a dependency on the template for this type, if the canonical type should be generated into this binary. // If the type is an array type, the check should be on its underlying Array<T> type. This is because a copy of // an array type gets placed into each module but the Array<T> type only exists in the defining module and only // one template is needed for the Array<T> type by the dynamic type loader. if (canonType.IsCanonicalSubtype(CanonicalFormKind.Any) && !factory.NecessaryTypeSymbol(canonClosestDefType).RepresentsIndirectionCell) { dependencies.Add(factory.NativeLayout.TemplateTypeLayout(canonType), "Template Type Layout"); } } }
public void AddCompilationRoot(TypeDesc type, string reason) { if (!ConstructedEETypeNode.CreationAllowed(type)) { _graph.AddRoot(_factory.NecessaryTypeSymbol(type), reason); } else { _graph.AddRoot(_factory.ConstructedTypeSymbol(type), reason); } }
private IEnumerable <TypeDesc> GetTypesWithRuntimeMapping() { // All constructed types that are not blocked get runtime mapping foreach (var constructedType in GetTypesWithConstructedEETypes()) { if (!IsReflectionBlocked(constructedType)) { yield return(constructedType); } } // All necessary types for which this is the highest load level that are not blocked // get runtime mapping. foreach (var necessaryType in GetTypesWithEETypes()) { if (!ConstructedEETypeNode.CreationAllowed(necessaryType) && !IsReflectionBlocked(necessaryType)) { yield return(necessaryType); } } }
public override bool ShouldProduceFullVTable(TypeDesc type) { return(ConstructedEETypeNode.CreationAllowed(type)); }
private void ImportLdToken(int token) { object obj = _methodIL.GetObject(token); if (obj is TypeDesc) { var type = (TypeDesc)obj; if (type.IsRuntimeDeterminedSubtype) { _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, type), "ldtoken"); } else { if (ConstructedEETypeNode.CreationAllowed(type)) { _dependencies.Add(_factory.ConstructedTypeSymbol(type), "ldtoken"); } else { _dependencies.Add(_factory.NecessaryTypeSymbol(type), "ldtoken"); } } // If this is a ldtoken Type / GetValueInternal sequence, we're done. BasicBlock nextBasicBlock = _basicBlocks[_currentOffset]; if (nextBasicBlock == null) { if ((ILOpcode)_ilBytes[_currentOffset] == ILOpcode.call) { int methodToken = ReadILTokenAt(_currentOffset + 1); var method = (MethodDesc)_methodIL.GetObject(methodToken); if (IsRuntimeTypeHandleGetValueInternal(method)) { // Codegen expands this and doesn't do the normal ldtoken. return; } } } _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.GetRuntimeTypeHandle), "ldtoken"); } else if (obj is MethodDesc) { var method = (MethodDesc)obj; if (method.IsRuntimeDeterminedExactMethod) { _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.MethodHandle, method), "ldtoken"); } else { _dependencies.Add(_factory.RuntimeMethodHandle(method), "ldtoken"); } _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.GetRuntimeMethodHandle), "ldtoken"); } else { Debug.Assert(obj is FieldDesc); // First check if this is a ldtoken Field / InitializeArray sequence. BasicBlock nextBasicBlock = _basicBlocks[_currentOffset]; if (nextBasicBlock == null) { if ((ILOpcode)_ilBytes[_currentOffset] == ILOpcode.call) { int methodToken = ReadILTokenAt(_currentOffset + 1); var method = (MethodDesc)_methodIL.GetObject(methodToken); if (IsRuntimeHelpersInitializeArray(method)) { // Codegen expands this and doesn't do the normal ldtoken. return; } } } var field = (FieldDesc)obj; if (field.OwningType.IsRuntimeDeterminedSubtype) { _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.FieldHandle, field), "ldtoken"); } else { _dependencies.Add(_factory.RuntimeFieldHandle(field), "ldtoken"); } _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.GetRuntimeFieldHandle), "ldtoken"); } }
public MetadataManager ToAnalysisBasedMetadataManager() { var reflectableTypes = ReflectableEntityBuilder <TypeDesc> .Create(); // Collect the list of types that are generating reflection metadata foreach (var typeWithMetadata in _typesWithMetadata) { reflectableTypes[typeWithMetadata] = MetadataCategory.Description; } // All the constructed types we generated that are not blocked are required to have runtime artifacts foreach (var constructedType in GetTypesWithConstructedEETypes()) { if (!IsReflectionBlocked(constructedType)) { reflectableTypes[constructedType] |= MetadataCategory.RuntimeMapping; // Also set the description bit if the definition is getting metadata. TypeDesc constructedTypeDefinition = constructedType.GetTypeDefinition(); if (constructedType != constructedTypeDefinition && (reflectableTypes[constructedTypeDefinition] & MetadataCategory.Description) != 0) { reflectableTypes[constructedType] |= MetadataCategory.Description; } } } // All the necessary types for which this is the higest load level are required to have runtime artifacts foreach (var necessaryType in GetTypesWithEETypes()) { if (!ConstructedEETypeNode.CreationAllowed(necessaryType) && !IsReflectionBlocked(necessaryType)) { reflectableTypes[necessaryType] |= MetadataCategory.RuntimeMapping; // Also set the description bit if the definition is getting metadata. TypeDesc necessaryTypeDefinition = necessaryType.GetTypeDefinition(); if (necessaryType != necessaryTypeDefinition && (reflectableTypes[necessaryTypeDefinition] & MetadataCategory.Description) != 0) { reflectableTypes[necessaryType] |= MetadataCategory.Description; } } } var reflectableMethods = ReflectableEntityBuilder <MethodDesc> .Create(); foreach (var methodWithMetadata in _methodsWithMetadata) { reflectableMethods[methodWithMetadata] = MetadataCategory.Description; } foreach (var method in GetCompiledMethods()) { if (!method.IsCanonicalMethod(CanonicalFormKind.Specific) && !IsReflectionBlocked(method)) { if ((reflectableTypes[method.OwningType] & MetadataCategory.RuntimeMapping) != 0) { reflectableMethods[method] |= MetadataCategory.RuntimeMapping; } // Also set the description bit if the definition is getting metadata. MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); if (method != typicalMethod && (reflectableMethods[typicalMethod] & MetadataCategory.Description) != 0) { reflectableMethods[method] |= MetadataCategory.Description; reflectableTypes[method.OwningType] |= MetadataCategory.Description; } } } var reflectableFields = ReflectableEntityBuilder <FieldDesc> .Create(); foreach (var fieldWithMetadata in _fieldsWithMetadata) { reflectableFields[fieldWithMetadata] = MetadataCategory.Description; } // TODO: this should be more precise foreach (var reflectableType in reflectableTypes.ToEnumerable()) { if (reflectableType.Entity.IsGenericDefinition) { continue; } if (reflectableType.Entity.IsCanonicalSubtype(CanonicalFormKind.Specific)) { continue; } foreach (var field in reflectableType.Entity.GetFields()) { if (CanGenerateMetadata(field.GetTypicalFieldDefinition())) { reflectableFields[field] |= reflectableType.Category; } } } return(new AnalysisBasedMetadataManager(_compilationModuleGroup.GeneratedAssembly, _typeSystemContext, _blockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy, _modulesWithMetadata, reflectableTypes.ToEnumerable(), reflectableMethods.ToEnumerable(), reflectableFields.ToEnumerable())); }