/// <summary> /// Function that retrieves associated method store /// </summary> /// <param name="pms"></param> /// <param name="ms"></param> /// <returns></returns> public static bool TryGetFieldStore(IPexComponent host, PersistentFieldStore pfs, out FieldStore fs) { fs = new FieldStore(); bool bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, pfs.FieldName, out fs.FieldName); SafeDebug.Assume(bresult, "Failed to get field from the persistent store"); fs.FieldValues.AddRange(pfs.FieldValues); //TODO: Performance can be improved via caching over here foreach (var mname in pfs.ReadMethods) { Method m; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, mname, out m); SafeDebug.Assume(bresult, "Failed to get method from persistent string form "); fs.ReadMethods.Add(m); } foreach (var typeex in pfs.WriteMethods.Keys) { SafeSet<Method> wmethods = new SafeSet<Method>(); TypeEx typeEx; bresult = MethodOrFieldAnalyzer.TryGetTypeExFromPersistentStringForm(host, typeex, out typeEx); SafeDebug.Assume(bresult, "Failed to get type from persistent string form " + typeex); fs.WriteMethods.Add(typeEx, wmethods); HashSet<string> methods; bresult = pfs.WriteMethods.TryGetValue(typeex, out methods); SafeDebug.Assume(bresult, "Failed to get associated set of methods for a type " + typeex); foreach (var m in methods) { Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method); SafeDebug.Assume(bresult, "Failed to get method from string form " + m); wmethods.Add(method); } } foreach (var m in pfs.ModificationTypeDictionary.Keys) { var value = pfs.ModificationTypeDictionary[m]; Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method); SafeDebug.Assume(bresult, "Failed to get method from string form " + m); fs.ModificationTypeDictionary.Add(method, value); } foreach (var m in pfs.PreciseModificationTypeDictionary.Keys) { var value = pfs.PreciseModificationTypeDictionary[m]; Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method); SafeDebug.Assume(bresult, "Failed to get method from string form " + m); fs.PreciseModificationTypeDictionary.Add(method, value); } return true; }
/// <summary> /// Gets textual form of modification type /// </summary> /// <param name="method"></param> /// <returns></returns> public static string GetModificationType(FieldStore fs, Method method) { if (!fs.ModificationTypeDictionary.ContainsKey(method)) return "UNKNOWN"; FieldModificationType fmt = fs.ModificationTypeDictionary[method]; return GetModificationTypeStr(fmt); }
/// <summary> /// Gets textual form of modification type /// </summary> /// <param name="method"></param> /// <returns></returns> public static string GetPreciseModificationType(FieldStore fs, Method method) { if (!fs.PreciseModificationTypeDictionary.ContainsKey(method)) { return("UNKNOWN"); } FieldModificationType fmt = fs.PreciseModificationTypeDictionary[method]; return(GetModificationTypeStr(fmt)); }
/// <summary> /// Gets the set of write methods associated with a field in the given type /// </summary> /// <param name="field"></param> /// <returns></returns> public bool TryGetWriteMethods(Field field, TypeEx declaringType, out SafeSet<Method> writeMethods) { SafeDebug.AssumeNotNull(field, "field"); SafeDebug.AssumeNotNull(declaringType, "declaringType"); //Declaring type should include defintinion if (declaringType == null || declaringType.Definition == null) { this.Log.LogWarning(WikiTopics.MissingWikiTopic, "WriteMethods", "Missing definition for the declaring type " + declaringType.FullName); writeMethods = null; return false; } FieldStore fs; if (this.FieldDictionary.TryGetValue(field, out fs)) { if (fs.WriteMethods.TryGetValue(declaringType, out writeMethods)) return true; else { writeMethods = new SafeSet<Method>(); fs.WriteMethods[declaringType] = writeMethods; } } else { fs = new FieldStore(); fs.FieldName = field; writeMethods = new SafeSet<Method>(); fs.WriteMethods[declaringType] = writeMethods; this.FieldDictionary[field] = fs; } foreach (MethodDefinition instanceMethod in declaringType.Definition.DeclaredInstanceMethods) { //Ignore abstract methods if (instanceMethod.IsAbstract) continue; //If the DISABLE_CALLING_METHODS_WITHIN_CLASS is set to true, then private methods need not be considered //since they will be filtered out. if (PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS && instanceMethod.DeclaredVisibility == Visibility.Private) continue; Method method = instanceMethod.Instantiate(declaringType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, instanceMethod)); MethodEffects me; if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, declaringType, method, null, out me)) { this.Log.LogWarning(WikiTopics.MissingWikiTopic, "methodeffects", "Failed to get the method effects for method " + method); continue; } if (me.WrittenInstanceFields.Contains(field.ShortName)) { writeMethods.Add(method); } FieldModificationType fmt; if (me.ModificationTypeDictionary.TryGetValue(field.ShortName, out fmt)) { fs.ModificationTypeDictionary[method] = fmt; } } //Check whether there are any private methods in calling methods. //If yes, replace them with their callers. if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS) { var newWriteMethods = new SafeSet<Method>(); GetCallingMethods(field, declaringType, writeMethods, newWriteMethods); writeMethods.Clear(); writeMethods.AddRange(newWriteMethods); } TypeEx baseType = declaringType.BaseType; if (baseType != null && baseType.FullName != "System.Object") { SafeSet<Method> innerWriteMethods; this.TryGetWriteMethods(field, baseType, out innerWriteMethods); if (innerWriteMethods != null) writeMethods.AddRange(innerWriteMethods); } return true; }
/// <summary> /// Function the retrieves associated Persistent store for each MethodStore /// </summary> /// <param name="ms"></param> /// <param name="pms"></param> /// <returns></returns> public static bool TryGetPersistentFieldStore(IPexComponent host, FieldStore fs, out PersistentFieldStore pfs) { pfs = new PersistentFieldStore(); pfs.FieldName = MethodOrFieldAnalyzer.GetPersistentStringFormOfField(fs.FieldName); //foreach(var value in fs.FieldValues) // pfs.FieldValues.Add(value); //TODO: Performance can be improved via caching over here foreach (var m in fs.ReadMethods) pfs.ReadMethods.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m)); foreach (var typeex in fs.WriteMethods.Keys) { HashSet<string> wmethods = new HashSet<string>(); pfs.WriteMethods.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfTypeEx(typeex), wmethods); SafeSet<Method> methods; bool bresult = fs.WriteMethods.TryGetValue(typeex, out methods); SafeDebug.Assume(bresult, "Failed to get associated set of methods for a type"); var assemblyname = typeex.Definition.Module.Assembly.Location; var typename = typeex.FullName; foreach (var m in methods) { wmethods.Add(assemblyname + PexMeConstants.PexMePersistenceFormSeparator + typename + PexMeConstants.PexMePersistenceFormSeparator + MethodOrFieldAnalyzer.GetMethodSignature(m)); } } foreach (var m in fs.ModificationTypeDictionary.Keys) { var value = fs.ModificationTypeDictionary[m]; pfs.ModificationTypeDictionary.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m), value); } foreach (var m in fs.PreciseModificationTypeDictionary.Keys) { var value = fs.PreciseModificationTypeDictionary[m]; pfs.PreciseModificationTypeDictionary.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m), value); } return true; }
private bool IsEligibleForLooping(MethodSignatureSequence seq, Field field, Dictionary<string, Method> writeMethods, FieldStore fs, out string loop_method) { string prevMethod = ""; int numTimes = 1; foreach (var method in seq.Sequence) { if (method == prevMethod) numTimes++; else numTimes = 1; if (numTimes >= PexMeConstants.LOOP_THRESHOLD) { //Check whether this loop_method modifies the culprit field //exactly by ONE (We current handle only INCREMENT_BY_ONE CASE) if (!writeMethods.ContainsKey(method)) continue; var wm = writeMethods[method]; FieldModificationType fmt; if (!fs.PreciseModificationTypeDictionary.TryGetValue(wm, out fmt)) continue; if (fmt != FieldModificationType.INCREMENT_ONE) continue; loop_method = method; return true; } prevMethod = method; } loop_method = ""; return false; }
/// <summary> /// Adds a monitored field to the database. Updates two kinds of hashmaps /// a. Field to Method mapper, which gives what the methods modifying a given field /// b. Method to Field mapper, which gives what fields are modified by each method (later used to identify a minimized set of methods) /// </summary> /// <param name="tm"></param> /// <param name="method"></param> /// <param name="f"></param> /// <param name="indices"></param> /// <param name="fieldValue"></param> public void AddMonitoredField(TermManager tm, Method method, Field f, Term[] indices, Term fieldValue, Term initialValue) { string arrayIndex = ""; using (PexMeTermRewriter pexmeRewriter = new PexMeTermRewriter(tm)) { fieldValue = pexmeRewriter.VisitTerm(default(TVoid), fieldValue); //update the field value to accomodate array-type field //if (indices.Length == 0) //not an array-type field if (indices.Length == 1) //is an array-type field { arrayIndex = " at index of " + indices[0].UniqueIndex.ToString(); } if (initialValue != null) { initialValue = pexmeRewriter.VisitTerm(default(TVoid), initialValue); } } //Updating the method store MethodStore ms; if (!methodDic.TryGetValue(method, out ms)) { ms = new MethodStore(); ms.methodName = method; methodDic[method] = ms; } ms.WriteFields.Add(f); //TODO: Gather information of read fields //Updating the field store FieldStore fs; if (!fieldDic.TryGetValue(f, out fs)) { fs = new FieldStore(); fs.FieldName = f; fieldDic[f] = fs; } TypeEx declaringType; if (!method.TryGetDeclaringType(out declaringType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "monitorfield", "Failed to get the declaring type for the method " + method.FullName); return; } SafeSet <Method> writeMethods; if (!fs.WriteMethods.TryGetValue(declaringType, out writeMethods)) { writeMethods = new SafeSet <Method>(); fs.WriteMethods[declaringType] = writeMethods; } writeMethods.Add(method); var sb = new SafeStringBuilder(); var swriter = new TermSExpWriter(tm, new SafeStringWriter(sb), true, false); swriter.Write(fieldValue); sb.Append(arrayIndex); int value; if (tm.TryGetI4Constant(fieldValue, out value)) { int initialval; if (initialValue != null) { tm.TryGetI4Constant(initialValue, out initialval); } else { initialval = 0; } sb.Append(" constant value: " + value); if (f.Type.ToString() != "System.Boolean") { if (value < initialval) { fs.ModificationTypeDictionary[method] = FieldModificationType.DECREMENT; } else if (value > initialval) { fs.ModificationTypeDictionary[method] = FieldModificationType.INCREMENT; if (value == initialval + 1) { fs.PreciseModificationTypeDictionary[method] = FieldModificationType.INCREMENT_ONE; } } else { fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } } else { if (value == 0) { fs.ModificationTypeDictionary[method] = FieldModificationType.FALSE_SET; } else { fs.ModificationTypeDictionary[method] = FieldModificationType.TRUE_SET; } } } else if (tm.IsDefaultValue(fieldValue)) { if (initialValue != null && !tm.IsDefaultValue(initialValue)) { fs.ModificationTypeDictionary[method] = FieldModificationType.NULL_SET; } else { fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } sb.Append(" null reference "); } else { if (initialValue == null) { fs.ModificationTypeDictionary[method] = FieldModificationType.NON_NULL_SET; } else { fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } sb.Append(" not-null reference "); } fs.FieldValues.Add(sb.ToString()); }
/// <summary> /// Adds a monitored field to the database. Updates two kinds of hashmaps /// a. Field to Method mapper, which gives what the methods modifying a given field /// b. Method to Field mapper, which gives what fields are modified by each method (later used to identify a minimized set of methods) /// </summary> /// <param name="tm"></param> /// <param name="method"></param> /// <param name="f"></param> /// <param name="indices"></param> /// <param name="fieldValue"></param> public void AddMonitoredField(TermManager tm, Method method, Field f, Term[] indices, Term fieldValue, Term initialValue) { string arrayIndex = ""; using (PexMeTermRewriter pexmeRewriter = new PexMeTermRewriter(tm)) { fieldValue = pexmeRewriter.VisitTerm(default(TVoid), fieldValue); //update the field value to accomodate array-type field //if (indices.Length == 0) //not an array-type field if (indices.Length == 1) //is an array-type field { arrayIndex = " at index of " + indices[0].UniqueIndex.ToString(); } if(initialValue != null) initialValue = pexmeRewriter.VisitTerm(default(TVoid), initialValue); } //Updating the method store MethodStore ms; if(!methodDic.TryGetValue(method, out ms)) { ms = new MethodStore(); ms.methodName = method; methodDic[method] = ms; } ms.WriteFields.Add(f); //TODO: Gather information of read fields //Updating the field store FieldStore fs; if (!fieldDic.TryGetValue(f, out fs)) { fs = new FieldStore(); fs.FieldName = f; fieldDic[f] = fs; } TypeEx declaringType; if (!method.TryGetDeclaringType(out declaringType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "monitorfield", "Failed to get the declaring type for the method " + method.FullName); return; } SafeSet<Method> writeMethods; if (!fs.WriteMethods.TryGetValue(declaringType, out writeMethods)) { writeMethods = new SafeSet<Method>(); fs.WriteMethods[declaringType] = writeMethods; } writeMethods.Add(method); var sb = new SafeStringBuilder(); var swriter = new TermSExpWriter(tm, new SafeStringWriter(sb), true, false); swriter.Write(fieldValue); sb.Append(arrayIndex); int value; if (tm.TryGetI4Constant(fieldValue, out value)) { int initialval; if (initialValue != null) tm.TryGetI4Constant(initialValue, out initialval); else initialval = 0; sb.Append(" constant value: " + value); if (f.Type.ToString() != "System.Boolean") { if (value < initialval) fs.ModificationTypeDictionary[method] = FieldModificationType.DECREMENT; else if (value > initialval) { fs.ModificationTypeDictionary[method] = FieldModificationType.INCREMENT; if (value == initialval + 1) fs.PreciseModificationTypeDictionary[method] = FieldModificationType.INCREMENT_ONE; } else fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } else { if (value == 0) fs.ModificationTypeDictionary[method] = FieldModificationType.FALSE_SET; else fs.ModificationTypeDictionary[method] = FieldModificationType.TRUE_SET; } } else if (tm.IsDefaultValue(fieldValue)) { if (initialValue != null && !tm.IsDefaultValue(initialValue)) fs.ModificationTypeDictionary[method] = FieldModificationType.NULL_SET; else fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; sb.Append(" null reference "); } else { if (initialValue == null) fs.ModificationTypeDictionary[method] = FieldModificationType.NON_NULL_SET; else fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; sb.Append(" not-null reference "); } fs.FieldValues.Add(sb.ToString()); }
/// <summary> /// Gets the set of write methods associated with a field in the given type /// </summary> /// <param name="field"></param> /// <returns></returns> public bool TryGetWriteMethods(Field field, TypeEx declaringType, out SafeSet <Method> writeMethods) { SafeDebug.AssumeNotNull(field, "field"); SafeDebug.AssumeNotNull(declaringType, "declaringType"); //Declaring type should include defintinion if (declaringType == null || declaringType.Definition == null) { this.Log.LogWarning(WikiTopics.MissingWikiTopic, "WriteMethods", "Missing definition for the declaring type " + declaringType.FullName); writeMethods = null; return(false); } FieldStore fs; if (this.FieldDictionary.TryGetValue(field, out fs)) { if (fs.WriteMethods.TryGetValue(declaringType, out writeMethods)) { return(true); } else { writeMethods = new SafeSet <Method>(); fs.WriteMethods[declaringType] = writeMethods; } } else { fs = new FieldStore(); fs.FieldName = field; writeMethods = new SafeSet <Method>(); fs.WriteMethods[declaringType] = writeMethods; this.FieldDictionary[field] = fs; } foreach (MethodDefinition instanceMethod in declaringType.Definition.DeclaredInstanceMethods) { //Ignore abstract methods if (instanceMethod.IsAbstract) { continue; } //If the DISABLE_CALLING_METHODS_WITHIN_CLASS is set to true, then private methods need not be considered //since they will be filtered out. if (PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS && instanceMethod.DeclaredVisibility == Visibility.Private) { continue; } Method method = instanceMethod.Instantiate(declaringType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, instanceMethod)); MethodEffects me; if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, declaringType, method, null, out me)) { this.Log.LogWarning(WikiTopics.MissingWikiTopic, "methodeffects", "Failed to get the method effects for method " + method); continue; } if (me.WrittenInstanceFields.Contains(field.ShortName)) { writeMethods.Add(method); } FieldModificationType fmt; if (me.ModificationTypeDictionary.TryGetValue(field.ShortName, out fmt)) { fs.ModificationTypeDictionary[method] = fmt; } } //Check whether there are any private methods in calling methods. //If yes, replace them with their callers. if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS) { var newWriteMethods = new SafeSet <Method>(); GetCallingMethods(field, declaringType, writeMethods, newWriteMethods); writeMethods.Clear(); writeMethods.AddRange(newWriteMethods); } TypeEx baseType = declaringType.BaseType; if (baseType != null && baseType.FullName != "System.Object") { SafeSet <Method> innerWriteMethods; this.TryGetWriteMethods(field, baseType, out innerWriteMethods); if (innerWriteMethods != null) { writeMethods.AddRange(innerWriteMethods); } } return(true); }