private void NoteGenericParameterFlow(ITypeDefinition actual, IGenericParameter formal) { if (createInstanceStrategy == TypeVariableCreateInstanceStrategy.ConstructAllConcreteParameters) { if (!(actual is IGenericParameter)) { // actual is concrete ITypeDefinition unspecializedConcreteType = GarbageCollectHelper.UnspecializeAndResolveTypeReference(actual); unspecializedTypesPassedAsTypeVariables.Add(unspecializedConcreteType); if (GarbageCollectHelper.TypeIsConstructable(unspecializedConcreteType)) { // t-devinc: We should associate a reason with this construction found ConstructionFound(unspecializedConcreteType); IMethodDefinition defaultConstructor = TypeHelper.GetMethod(unspecializedConcreteType, wholeProgram.Host().NameTable.GetNameFor(".ctor")); if (!(defaultConstructor is Dummy)) { // t-devinc: Add reason for this NotePotentialNonVirtualMethodReachedForReason(defaultConstructor, null); } } } } }
// Called when the first new T() is detected. // This method is where we add worst-case-scenario // constructed types for those stategies. // t-devinc: Now that we don't do construct reachable types // this maybe doesn't make sense. private void NoteFirstTypeVariableConstructed() { IEnumerable <ITypeDefinition> potentialUniverse; switch (createInstanceStrategy) { case TypeVariableCreateInstanceStrategy.ConstructAll: potentialUniverse = wholeProgram.AllDefinedTypes(); break; default: // do nothing potentialUniverse = new HashSet <ITypeDefinition>(); break; } foreach (ITypeDefinition t in potentialUniverse) { if (GarbageCollectHelper.TypeIsConstructable(t)) { ConstructionFound(t); // t-devinc: We should associate a reason with this! } } }
private void ConstructionFound(ITypeDefinition t) { Contract.Requires(t != null); Contract.Requires(!(t is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(t)); Contract.Requires(GarbageCollectHelper.TypeIsConstructable(t)); Contract.Ensures(this.constructed.Contains(t)); //Console.WriteLine("Found construction of {0}", t); if (this.constructed.Contains(t)) { return; } this.constructed.Add(t); // t-devinc: should change AllSuperTypes, etc. to include t foreach (var baseclass in new ITypeDefinition[] { t }.Concat(GarbageCollectHelper.AllSuperTypes(t))) { ITypeDefinition unspecializedBaseClass = GarbageCollectHelper.UnspecializeAndResolveTypeReference(baseclass); foreach (var m in unspecializedBaseClass.Methods) { if (m.IsVirtual && VirtualMethodIsInDemand(m)) { ICollection <IMethodDefinition> implementationsOfMForT = GarbageCollectHelper.Implements(t, unspecializedBaseClass, m); Contract.Assert(implementationsOfMForT.Count() > 0); foreach (IMethodDefinition mprime in implementationsOfMForT) { NoteDispatch(m, GarbageCollectHelper.UnspecializeAndResolveMethodReference(mprime), t); } } } } // If a type is constructed then its Finalize method may be called ICollection <IMethodDefinition> implementationsOfFinalizeForT = GarbageCollectHelper.Implements(t, systemObjectType, systemObjectFinalizeMethod); Contract.Assert(implementationsOfFinalizeForT.Count() == 1); // t-devinc: Need to to add reason for this this.AddToWorklist(GarbageCollectHelper.UnspecializeAndResolveMethodReference(implementationsOfFinalizeForT.First())); }
private void NoteVirtualDispatch(IMethodDefinition methodDispatchedUpon) { Contract.Requires(methodDispatchedUpon != null); Contract.Requires(!(methodDispatchedUpon is Dummy)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(methodDispatchedUpon)); Contract.Requires(methodDispatchedUpon.IsVirtual); Contract.Ensures(VirtualMethodIsInDemand(methodDispatchedUpon)); //Console.WriteLine("VirtCallFound on {0} of type {1}", methodDefinition, methodDefinition.GetType()); bool virtualMethodIsAlreadyKnown = VirtualMethodIsInDemand(methodDispatchedUpon); MarkVirtualMethodAsInDemand(methodDispatchedUpon); if (virtualMethodIsAlreadyKnown) { return; } // The code below this point is called only the first time we learn that // someone has dispatched against this method. //Console.WriteLine("{0} has {1} derived methods", methodDefinition, this.callgraph.GetAllDerivedMethods(methodDefinition).ToArray().Length); ITypeDefinition typeDefiningM = methodDispatchedUpon.ContainingTypeDefinition; this.TypeUseFound(typeDefiningM); // t-devinc: clean this up foreach (ITypeDefinition subType in new ITypeDefinition[] { typeDefiningM }.Concat(wholeProgram.ClassHierarchy().AllSubClassesOfClass(typeDefiningM))) { if (GarbageCollectHelper.TypeIsConstructable(subType) && ((subType.IsStruct || constructed.Contains(subType)))) { ICollection <IMethodDefinition> implementationsOfMethodDefinitionForSubType = GarbageCollectHelper.Implements(subType, typeDefiningM, methodDispatchedUpon); Contract.Assert(implementationsOfMethodDefinitionForSubType.Count() > 0); foreach (IMethodDefinition implementationOfM in implementationsOfMethodDefinitionForSubType) { NoteDispatch(methodDispatchedUpon, GarbageCollectHelper.UnspecializeAndResolveMethodReference(implementationOfM), subType); } } } }