boolean isConstant(VarInfo vi) { PptTopLevel ppt = vi.ppt; boolean isStaticConstant = vi.is_static_constant; boolean isDynamicConstant = ((ppt.constants != null) && ppt.constants.is_constant(vi)); PptSlice view = ppt.findSlice(vi); // TODO: This should be generalized to other types of scalar OneOfScalar oos = (view == null) ? null : OneOfScalar.find(view); OneOfFloat oof = (view == null) ? null : OneOfFloat.find(view); boolean isOneOfConstant = (((oos != null) && (oos.num_elts() == 1) && (!oos.is_hashcode())) || ((oof != null) && (oof.num_elts() == 1) // no hashcode test for floats // && (! oof.is_hashcode()) )); return isStaticConstant || isDynamicConstant || isOneOfConstant; }
/** * Creates a valuetuple for the receiver using the vt of the original. The method copies over * the values of variables shared by both program points and sets the rest of the variables in * the receiver's valuetuple as missing. Also, adds the orig and derived variables to the * receiver and returns the newly created valuetuple. */ private static ValueTuple copySample( PptTopLevel receiver, PptTopLevel original, ValueTuple vt, int nonce) { // Make the vt for the receiver ppt // Object values[] = new Object[receiver.num_tracevars]; // int mods[] = new int[receiver.num_tracevars]; Object values[] = new Object[receiver.var_infos.length - receiver.num_static_constant_vars]; int mods[] = new int[receiver.var_infos.length - receiver.num_static_constant_vars]; // Build the vt for the receiver ppt by looking through the current // vt and filling in the gaps. int k = 0; for (Iterator<VarInfo> i = receiver.var_info_iterator(); i.hasNext(); ) { VarInfo var = i.next(); if (var.is_static_constant) continue; boolean found = false; for (Iterator<VarInfo> j = original.var_info_iterator(); j.hasNext(); ) { VarInfo var2 = j.next(); if (var.name().equals(var2.name())) { values[k] = vt.getValueOrNull(var2); mods[k] = vt.getModified(var2); found = true; break; } } if (!found) { values[k] = null; mods[k] = 2; } k++; } ValueTuple receiver_vt = new ValueTuple(values, mods); FileIO.add_orig_variables(receiver, receiver_vt.vals, receiver_vt.mods, nonce); FileIO.add_derived_variables(receiver, receiver_vt.vals, receiver_vt.mods); return receiver_vt; }
/** * process the sample by checking it against each existing invariant and issuing an error if any * invariant is falsified or weakened. */ public void process_sample(PptMap all_ppts, PptTopLevel ppt, ValueTuple vt, Integer nonce) { this.all_ppts = all_ppts; debug.fine("processing sample from: " + ppt.name); // Add orig and derived variables FileIO.add_orig_variables(ppt, vt.vals, vt.mods, nonce); FileIO.add_derived_variables(ppt, vt.vals, vt.mods); // Intern the sample vt = new ValueTuple(vt.vals, vt.mods); // If this is an enter point, just remember it for later if (ppt.ppt_name.isEnterPoint()) { Assert.assertTrue(nonce != null); if (dir_file != null) { // Yoav: I had to do a hack to handle the case that several dtrace files are concatenated // together, // and Sung's dtrace files have unterminated calls, and when concatenating two files you // can have the same nonce. // So I have to remove the nonce found from the call_map call_map.remove(nonce); } else Assert.assertTrue(call_map.get(nonce) == null); call_map.put(nonce, new EnterCall(ppt, vt)); debug.fine("Skipping enter sample"); return; } // If this is an exit point, process the saved enter point if (ppt.ppt_name.isExitPoint()) { Assert.assertTrue(nonce != null); EnterCall ec = call_map.get(nonce); if (ec != null) { call_map.remove(nonce); debug.fine("Processing enter sample from " + ec.ppt.name); add(ec.ppt, ec.vt); } else { // didn't find the enter if (!quiet) System.out.printf("couldn't find enter for nonce %d at ppt %s\n", nonce, ppt.name()); return; } } add(ppt, vt); }
/** * Returns true if the two original variables are related in a way that makes subsequence or * subset detection not informative. */ public static boolean isObviousSubSequenceDynamically( Invariant inv, VarInfo subvar, VarInfo supervar) { VarInfo[] vis = {subvar, supervar}; ProglangType rep1 = subvar.rep_type; ProglangType rep2 = supervar.rep_type; if (!(((rep1 == ProglangType.INT_ARRAY) && (rep2 == ProglangType.INT_ARRAY)) || ((rep1 == ProglangType.DOUBLE_ARRAY) && (rep2 == ProglangType.DOUBLE_ARRAY)) || ((rep1 == ProglangType.STRING_ARRAY) && (rep2 == ProglangType.STRING_ARRAY)))) return false; if (debug.isLoggable(Level.FINE)) { debug.fine( "Checking isObviousSubSequenceDynamically " + subvar.name() + " in " + supervar.name()); } Object[] di = isObviousSubSequence(subvar, supervar); if (di[1] != null) { inv.log("ObvSubSeq- true from isObviousSubSequence: " + di[1]); return true; } debug.fine(" not isObviousSubSequence(statically)"); PptTopLevel ppt_parent = subvar.ppt; // If the elements of supervar are always the same (EltOneOf), // we aren't going to learn anything new from this invariant, // since each sequence should have an EltOneOf over it. if (false) { PptSlice1 slice = ppt_parent.findSlice(supervar); if (slice == null) { System.out.println("No slice: parent =" + ppt_parent); } else { System.out.println("Slice var =" + slice.var_infos[0]); for (Invariant superinv : slice.invs) { System.out.println("Inv = " + superinv); if (superinv instanceof EltOneOf) { EltOneOf eltinv = (EltOneOf) superinv; if (eltinv.num_elts() > 0) { inv.log(" obvious because of " + eltinv.format()); return true; } } } } } // Obvious if subvar is always just [] if (true) { PptSlice1 slice = ppt_parent.findSlice(subvar); if (slice != null) { for (Invariant subinv : slice.invs) { if (subinv instanceof OneOfSequence) { OneOfSequence seqinv = (OneOfSequence) subinv; if (seqinv.num_elts() == 1) { Object elt = seqinv.elt(); if (elt instanceof long[] && ((long[]) elt).length == 0) { Debug.log( debug, inv.getClass(), inv.ppt, vis, "ObvSubSeq- True from subvar being []"); return true; } if (elt instanceof double[] && ((double[]) elt).length == 0) { inv.log("ObvSubSeq- True from subvar being []"); return true; } } } } } } // Check for a[0..i] subseq a[0..j] but i < j. VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); VarInfo supervar_super = supervar.isDerivedSubSequenceOf(); if (subvar_super != null && subvar_super == supervar_super) { // both sequences are derived from the same supersequence if ((subvar.derived instanceof SequenceScalarSubsequence || subvar.derived instanceof SequenceScalarArbitrarySubsequence) && (supervar.derived instanceof SequenceScalarSubsequence || supervar.derived instanceof SequenceScalarArbitrarySubsequence)) { VarInfo sub_left_var = null, sub_right_var = null, super_left_var = null, super_right_var = null; // I'm careful not to access foo_shift unless foo_var has been set // to a non-null value, but Java is too stupid to recognize that. int sub_left_shift = 42, sub_right_shift = 69, super_left_shift = 1492, super_right_shift = 1776; if (subvar.derived instanceof SequenceScalarSubsequence) { SequenceScalarSubsequence sub = (SequenceScalarSubsequence) subvar.derived; if (sub.from_start) { sub_right_var = sub.sclvar(); sub_right_shift = sub.index_shift; } else { sub_left_var = sub.sclvar(); sub_left_shift = sub.index_shift; } } else if (subvar.derived instanceof SequenceScalarArbitrarySubsequence) { SequenceScalarArbitrarySubsequence sub = (SequenceScalarArbitrarySubsequence) subvar.derived; sub_left_var = sub.startvar(); sub_left_shift = (sub.left_closed ? 0 : 1); sub_right_var = sub.endvar(); sub_right_shift = (sub.right_closed ? 0 : -1); } else { Assert.assertTrue(false); } if (supervar.derived instanceof SequenceScalarSubsequence) { SequenceScalarSubsequence super_ = (SequenceScalarSubsequence) supervar.derived; if (super_.from_start) { super_right_var = super_.sclvar(); super_right_shift = super_.index_shift; } else { super_left_var = super_.sclvar(); super_left_shift = super_.index_shift; } } else if (supervar.derived instanceof SequenceScalarArbitrarySubsequence) { SequenceScalarArbitrarySubsequence super_ = (SequenceScalarArbitrarySubsequence) supervar.derived; super_left_var = super_.startvar(); super_left_shift = (super_.left_closed ? 0 : 1); super_right_var = super_.endvar(); super_right_shift = (super_.right_closed ? 0 : -1); } else { Assert.assertTrue(false); } boolean left_included, right_included; if (super_left_var == null) left_included = true; else if (sub_left_var == null) // we know super_left_var != null here left_included = false; else left_included = VarInfo.compare_vars( super_left_var, super_left_shift, sub_left_var, sub_left_shift, true /* <= */); if (super_right_var == null) right_included = true; else if (sub_right_var == null) // we know super_right_var != null here right_included = false; else right_included = VarInfo.compare_vars( super_right_var, super_right_shift, sub_right_var, sub_right_shift, false /* >= */); // System.out.println("Is " + subvar.name() + " contained in " // + supervar.name() // + "? left: " + left_included + ", right: " // + right_included); if (left_included && right_included) { inv.log("ObvSubSeq- True a[0..i] subseq a[0..j] and i < j"); return true; } } else if ((subvar.derived instanceof SequenceStringSubsequence) && (supervar.derived instanceof SequenceStringSubsequence)) { // Copied from just above SequenceStringSubsequence sss1 = (SequenceStringSubsequence) subvar.derived; SequenceStringSubsequence sss2 = (SequenceStringSubsequence) supervar.derived; VarInfo index1 = sss1.sclvar(); int shift1 = sss1.index_shift; boolean start1 = sss1.from_start; VarInfo index2 = sss2.sclvar(); int shift2 = sss2.index_shift; boolean start2 = sss2.from_start; if (start1 == start2) if (VarInfo.compare_vars(index1, shift1, index2, shift2, start1)) { inv.log("True from comparing indices"); return true; } } else { Assert.assertTrue( false, "how can this happen? " + subvar.name() + " " + subvar.derived.getClass() + " " + supervar.name() + " " + supervar.derived.getClass()); } } // Also need to check A[0..i] subseq A[0..j] via compare_vars. // A subseq B[0..n] => A subseq B List<Derivation> derivees = supervar.derivees(); // For each variable derived from supervar ("B") for (Derivation der : derivees) { // System.out.println(" ... der = " + der.getVarInfo().name() + " " + der); if (der instanceof SequenceScalarSubsequence) { // If that variable is "B[0..n]" VarInfo supervar_part = der.getVarInfo(); // Get the canonical version; being equal to it is good enough. if (supervar_part.get_equalitySet_leader() == subvar) { Debug.log(debug, inv.getClass(), inv.ppt, vis, "ObvSubSeq- True from canonical leader"); return true; } if (supervar_part.isCanonical()) { if (subvar == supervar_part) { System.err.println( "Error: variables " + subvar.name() + " and " + supervar_part.name() + " are identical. Canonical"); System.err.println(subvar.isCanonical()); System.err.println(supervar_part.isCanonical()); throw new Error(); } // Check to see if there is a subsequence over the supervar if (ppt_parent.is_subsequence(subvar, supervar_part)) { if (Debug.logOn()) inv.log( "ObvSubSeq- true from A subseq B[0..n] " + subvar.name() + "/" + supervar_part.name()); return (true); } } } } return false; }
private void add(PptTopLevel ppt, ValueTuple vt, int nonce) { // if this is a numbered exit, apply to the combined exit as well if (ppt.ppt_name.isNumberedExitPoint()) { // Daikon.create_combined_exits(all_ppts); PptTopLevel parent = all_ppts.get(ppt.ppt_name.makeExit()); if (parent != null) { parent.get_missingOutOfBounds(ppt, vt); add(parent, vt, nonce); } else { // make parent and apply // this is a hack. it should probably filter out orig and derived // vars instead of taking the first n. int len = ppt.num_tracevars + ppt.num_static_constant_vars; VarInfo[] exit_vars = new VarInfo[len]; for (int j = 0; j < len; j++) { exit_vars[j] = new VarInfo(ppt.var_infos[j]); exit_vars[j].varinfo_index = ppt.var_infos[j].varinfo_index; exit_vars[j].value_index = ppt.var_infos[j].value_index; exit_vars[j].equalitySet = null; } parent = new PptTopLevel(ppt.ppt_name.makeExit().getName(), exit_vars); Daikon.init_ppt(parent, all_ppts); all_ppts.add(parent); parent.get_missingOutOfBounds(ppt, vt); add(parent, vt, nonce); } } // If the point has no variables, skip it if (ppt.var_infos.length == 0) { // The sample should be skipped but Daikon does not do this so // DaikonSimple will not do this to be consistent. // The better idea is for Daikon to assert that these valuetuples are // empty and then skip the sample. assert vt.size() == 0; return; } // Instantiate slices and invariants if this is the first sample if (ppt.num_samples() == 0) { instantiate_views_and_invariants(ppt); } // manually inc the sample number because DaikonSimple does not // use any of PptTopLevel's add methods which increase the sample // number ppt.incSampleNumber(); // Loop through each slice for (Iterator<PptSlice> i = ppt.views_iterator(); i.hasNext(); ) { PptSlice slice = i.next(); Iterator<Invariant> k = slice.invs.iterator(); boolean missing = false; for (VarInfo v : slice.var_infos) { // If any var has encountered out of array bounds values, // stop all invariants in this slice. The presumption here is that // an index out of bounds implies that the derived variable (eg a[i]) // doesn't really make any sense (essentially that i is not a valid // index for a). Invariants on the derived variable are thus not // relevant. // If any variables are out of bounds, remove the invariants if (v.missingOutOfBounds()) { while (k.hasNext()) { Invariant inv = k.next(); k.remove(); } missing = true; break; } // If any variables are missing, skip this slice if (v.isMissing(vt)) { missing = true; break; } } // keep a list of the falsified invariants if (!missing) { while (k.hasNext()) { Invariant inv = k.next(); Invariant pre_inv = inv.clone(); for (VarInfo vi : inv.ppt.var_infos) { assert vt.getValue(vi) != null : vi; } if (inv.ppt instanceof PptSlice2) assert inv.ppt.var_infos.length == 2; InvariantStatus status = inv.add_sample(vt, 1); if (status == InvariantStatus.FALSIFIED) { k.remove(); } } } // update num_samples and num_values of a slice manually // because DaikonSimple does not call any of PptTopLevel's // add methods for (int j = 0; j < vt.vals.length; j++) { if (!vt.isMissing(j)) { ValueSet vs = ppt.value_sets[j]; vs.add(vt.vals[j]); } } ppt.mbtracker.add(vt, 1); } }
/** * Process the sample by checking it against each existing invariant at the program point and * removing the invariant from the list of possibles if any invariant is falsified. */ public void process_sample( PptMap all_ppts, PptTopLevel ppt, ValueTuple vt, /*@Nullable*/ Integer nonce) { this.all_ppts = all_ppts; // Add samples to orig and derived variables FileIO.add_orig_variables(ppt, vt.vals, vt.mods, nonce); FileIO.add_derived_variables(ppt, vt.vals, vt.mods); // Intern the sample vt = new ValueTuple(vt.vals, vt.mods); // DaikonSimple must make the object program point manually because // the new Chicory produced dtrace files do not contain object ppts // in the dtrace part of the file (the program point is declared). // Make the object ppt PptName ppt_name = ppt.ppt_name; PptTopLevel object_ppt = null; PptTopLevel class_ppt = null; ValueTuple object_vt = null; ValueTuple class_vt = null; if ((ppt_name.isEnterPoint() && !ppt_name.isConstructor()) || ppt_name.isExitPoint()) { object_ppt = all_ppts.get(ppt_name.makeObject()); class_ppt = all_ppts.get(ppt_name.makeClassStatic()); } // C programs do not have object ppts // check whether the ppt is a static or instance method // that decides whether the sample is copied over to the object and/or // class ppt if (object_ppt != null) { // the check assumes that static fields are not stored first in the // object ppt if (ppt.find_var_by_name(object_ppt.var_infos[0].name()) != null) { // object and class ppt should be created object_vt = copySample(object_ppt, ppt, vt, nonce); if (class_ppt != null) { class_vt = copySample(class_ppt, ppt, vt, nonce); } } else { // only class ppt should be created if (class_ppt != null) { class_vt = copySample(class_ppt, ppt, vt, nonce); } object_vt = null; object_ppt = null; } } // If this is an enter point, just remember it for later if (ppt_name.isEnterPoint()) { assert nonce != null; assert call_map.get(nonce) == null; List<Call> value = new ArrayList<Call>(); value.add(new Call(ppt, vt)); if (object_ppt != null) { value.add(new Call(object_ppt, object_vt)); } if (class_ppt != null) { value.add(new Call(class_ppt, class_vt)); } call_map.put(nonce, value); last_nonce = nonce; wait = true; return; } // If this is an exit point, process the saved enter (and sometimes // object) point if (ppt_name.isExitPoint()) { assert nonce != null; List<Call> value = call_map.remove(nonce); add(ppt, vt, nonce); for (Call ec : value) { add(ec.ppt, ec.vt, nonce); } wait = false; } if (object_ppt != null) add(object_ppt, object_vt, nonce); // apply object vt if (class_ppt != null) add(class_ppt, class_vt, nonce); }
// Note that some slightly inefficient code has been added to aid // in debugging. When creating binary and ternary views and debugging // is on, the outer loops will not terminate prematurely on innapropriate // (i.e., non-canonical) variables. This allows explicit debug statements // for each possible combination, simplifying determining why certain // slices were not created. // // Note that '///*' indicates code duplicated from PptTopLevel's // version but commented out because DaikonSimple does not need // to perform these checks public static void instantiate_views_and_invariants(PptTopLevel ppt) { // used only for debugging int old_num_vars = ppt.var_infos.length; int old_num_views = ppt.numViews(); boolean debug_on = debug.isLoggable(Level.FINE); // / 1. all unary views // Unary slices/invariants. // Currently, there are no constraints on the unary // slices. Since we are trying to create all of the invariants, the // variables does not have to be a leader and can be a constant. // Note that the always missing check is only applicable when the // dynamic constants optimization is turned on (so we do not do the // check here). Vector<PptSlice> unary_views = new Vector<PptSlice>(ppt.var_infos.length); for (VarInfo vi : ppt.var_infos) { // /* if (!is_slice_ok(vi)) // /* continue; PptSlice1 slice1 = new PptSlice1(ppt, vi); slice1.instantiate_invariants(); unary_views.add(slice1); } ppt.addViews(unary_views); unary_views = null; // / 2. all binary views // Binary slices/invariants. Vector<PptSlice> binary_views = new Vector<PptSlice>(); for (int i1 = 0; i1 < ppt.var_infos.length; i1++) { VarInfo var1 = ppt.var_infos[i1]; // Variables can be constant and missing in DaikonSimple invariants // /* if (!is_var_ok_binary(var1)) // /* continue; for (int i2 = i1; i2 < ppt.var_infos.length; i2++) { VarInfo var2 = ppt.var_infos[i2]; // Variables can be constant and missing in DaikonSimple invariants // /* if (!is_var_ok_binary(var2)) // /* continue; if (!(var1.compatible(var2) || (var1.type.isArray() && var1.eltsCompatible(var2)) || (var2.type.isArray() && var2.eltsCompatible(var1)))) { continue; } PptSlice2 slice2 = new PptSlice2(ppt, var1, var2); slice2.instantiate_invariants(); binary_views.add(slice2); } } ppt.addViews(binary_views); binary_views = null; // 3. all ternary views Vector<PptSlice> ternary_views = new Vector<PptSlice>(); for (int i1 = 0; i1 < ppt.var_infos.length; i1++) { VarInfo var1 = ppt.var_infos[i1]; if (!is_var_ok(var1)) continue; for (int i2 = i1; i2 < ppt.var_infos.length; i2++) { VarInfo var2 = ppt.var_infos[i2]; if (!is_var_ok(var2)) continue; for (int i3 = i2; i3 < ppt.var_infos.length; i3++) { VarInfo var3 = ppt.var_infos[i3]; if (!is_var_ok(var3)) continue; if (!is_slice_ok(var1, var2, var3)) { continue; } PptSlice3 slice3 = new PptSlice3(ppt, var1, var2, var3); slice3.instantiate_invariants(); ternary_views.add(slice3); } } } ppt.addViews(ternary_views); // This method didn't add any new variables. assert old_num_vars == ppt.var_infos.length; ppt.repCheck(); }
/** * This does the work of main, but it never calls System.exit, so it is appropriate to be called * progrmmatically. Termination of the program with a message to the user is indicated by throwing * Daikon.TerminationMessage. * * <p>Difference from Daikon's mainHelper: turn off optimization flags (equality, dynamic * constants, NIS suppression). * * @see #main(String[]) * @see daikon.Daikon.TerminationMessage * @see daikon.Daikon#mainHelper(String[]) */ public static void mainHelper(final String[] args) throws IOException, FileNotFoundException { // set up logging information daikon.LogHelper.setupLogs(daikon.LogHelper.INFO); // No optimizations used in the simple incremental algorithm so // optimizations are turned off. Daikon.use_equality_optimization = false; Daikon.dkconfig_use_dynamic_constant_optimization = false; Daikon.suppress_implied_controlled_invariants = false; NIS.dkconfig_enabled = false; // The flag tells FileIO and Daikon to use DaikonSimple // specific methods (e.g. FileIO.read_declaration_file). // When FileIO reads and processes // samples, it must use the SimpleProcessor rather than the // default Processor. Daikon.using_DaikonSimple = true; // Read command line options Daikon.FileOptions files = Daikon.read_options(args, usage); // DaikonSimple does not supply nor use the spinfo_files and map_files Set<File> decls_files = files.decls; Set<String> dtrace_files = files.dtrace; if ((decls_files.size() == 0) && (dtrace_files.size() == 0)) { throw new Daikon.TerminationMessage("No .decls or .dtrace files specified"); } // Create the list of all invariant types Daikon.setup_proto_invs(); // Create the program points for enter and numbered exits and // initializes the points (adding orig and derived variables) all_ppts = FileIO.read_declaration_files(decls_files); // Create the combined exits (and add orig and derived vars) // Daikon.create_combined_exits(all_ppts); // Read and process the data trace files SimpleProcessor processor = new SimpleProcessor(); FileIO.read_data_trace_files(dtrace_files, all_ppts, processor, true); // System.exit(0); // Print out the invariants for each program point (sort first) for (Iterator<PptTopLevel> t = all_ppts.pptIterator(); t.hasNext(); ) { PptTopLevel ppt = t.next(); // We do not need to print out program points that have not seen // any samples. if (ppt.num_samples() == 0) { continue; } List<Invariant> invs = PrintInvariants.sort_invariant_list(ppt.invariants_vector()); List<Invariant> filtered_invs = Daikon.filter_invs(invs); // The dkconfig_quiet printing is used for creating diffs between // DaikonSimple // and Daikon's output. The second kind of printing is used for // debugging. Since the names of the program points are the same for both // Daikon and DaikonSimple, diffing the two output will result in // only differences in the invariants, but we can not see at which program // points these differing invariants appear. Using the second kind of // printing, // Daikon's output does not have the '+' in the program point name, so in // addition // to the invariants showing up in the diff, we will also see the program // point // names. if (Daikon.dkconfig_quiet) { System.out.println("===================================================="); System.out.println(ppt.name()); } else { System.out.println("===================================================+"); System.out.println(ppt.name() + " +"); } // Sometimes the program points actually differ in number of // samples seen due to differences in how Daikon and DaikonSimple // see the variable hierarchy. System.out.println(ppt.num_samples()); for (Invariant inv : filtered_invs) { System.out.println(inv.getClass()); System.out.println(inv); } } }
/** * Extract consequents from a implications at a single program point. It only searches for top * level Program points because Implications are produced only at those points. */ public static void extract_consequent_maybe(PptTopLevel ppt, PptMap all_ppts) { ppt.simplify_variable_names(); List<Invariant> invs = new ArrayList<Invariant>(); if (invs.size() > 0) { String pptname = cleanup_pptname(ppt.name()); for (Invariant maybe_as_inv : invs) { Implication maybe = (Implication) maybe_as_inv; // don't print redundant invariants. if (Daikon.suppress_redundant_invariants_with_simplify && maybe.ppt.parent.redundant_invs.contains(maybe)) { continue; } // don't print out invariants with min(), max(), or sum() variables boolean mms = false; VarInfo[] varbls = maybe.ppt.var_infos; for (int v = 0; !mms && v < varbls.length; v++) { mms |= varbls[v].isDerivedSequenceMinMaxSum(); } if (mms) { continue; } if (maybe.ppt.parent.ppt_name.isExitPoint()) { for (int i = 0; i < maybe.ppt.var_infos.length; i++) { VarInfo vi = maybe.ppt.var_infos[i]; if (vi.isDerivedParam()) { continue; } } } Invariant consequent = maybe.consequent(); Invariant predicate = maybe.predicate(); Invariant inv, cluster_inv; boolean cons_uses_cluster = false, pred_uses_cluster = false; // extract the consequent (predicate) if the predicate // (consequent) uses the variable "cluster". Ignore if they // both depend on "cluster" if (consequent.usesVarDerived("cluster")) cons_uses_cluster = true; if (predicate.usesVarDerived("cluster")) pred_uses_cluster = true; if (!(pred_uses_cluster ^ cons_uses_cluster)) { continue; } else if (pred_uses_cluster) { inv = consequent; cluster_inv = predicate; } else { inv = predicate; cluster_inv = consequent; } if (!inv.isInteresting()) { continue; } if (!inv.isWorthPrinting()) { continue; } if (contains_constant_non_012(inv)) { continue; } // filter out unwanted invariants // 1) Invariants involving sequences if (inv instanceof daikon.inv.binary.twoSequence.TwoSequence || inv instanceof daikon.inv.binary.sequenceScalar.SequenceScalar || inv instanceof daikon.inv.binary.sequenceString.SequenceString || inv instanceof daikon.inv.unary.sequence.SingleSequence || inv instanceof daikon.inv.unary.stringsequence.SingleStringSequence) { continue; } if (inv instanceof daikon.inv.ternary.threeScalar.LinearTernary || inv instanceof daikon.inv.binary.twoScalar.LinearBinary) { continue; } String inv_string = inv.format_using(OutputFormat.JAVA); if (orig_pattern.matcher(inv_string).find() || dot_class_pattern.matcher(inv_string).find()) { continue; } String fake_inv_string = simplify_inequalities(inv_string); HashedConsequent real = new HashedConsequent(inv, null); if (!fake_inv_string.equals(inv_string)) { // For instance, inv_string is "x != y", fake_inv_string is "x == y" HashedConsequent fake = new HashedConsequent(inv, inv_string); boolean added = store_invariant( cluster_inv.format_using(OutputFormat.JAVA), fake_inv_string, fake, pptname); if (!added) { // We couldn't add "x == y", (when we're "x != y") because // it already exists; so don't add "x == y" either. continue; } } store_invariant(cluster_inv.format_using(OutputFormat.JAVA), inv_string, real, pptname); } } }
private void add(PptTopLevel ppt, ValueTuple vt) { // Add the sample to any splitters if (ppt.has_splitters()) { for (PptSplitter ppt_split : ppt.splitters) { PptConditional ppt_cond = ppt_split.choose_conditional(vt); if (ppt_cond != null) add(ppt_cond, vt); else debug.fine(": sample doesn't pick conditional"); } } // if this is a numbered exit, apply to the combined exit as well if (!(ppt instanceof PptConditional) && ppt.ppt_name.isNumberedExitPoint()) { PptTopLevel parent = all_ppts.get(ppt.ppt_name.makeExit()); if (parent != null) { parent.get_missingOutOfBounds(ppt, vt); add(parent, vt); } } // If the point has no variables, skip it if (ppt.var_infos.length == 0) return; // We should have received sample here before, or there is nothing // to check. // Yoav added: It can be that the different dtrace and inv files have different program points if (false && ppt.num_samples() <= 0) Assert.assertTrue( ppt.num_samples() > 0, "ppt " + ppt.name + " has 0 samples and " + ppt.var_infos.length + " variables"); // Loop through each slice slice_loop: for (Iterator<PptSlice> i = ppt.views_iterator(); i.hasNext(); ) { PptSlice slice = i.next(); if (debug_detail.isLoggable(Level.FINE)) debug_detail.fine( ": processing slice " + slice + "vars: " + Debug.toString(slice.var_infos, vt)); // If any variables are missing, skip this slice for (int j = 0; j < slice.var_infos.length; j++) { VarInfo v = slice.var_infos[j]; int mod = vt.getModified(v); if (v.isMissing(vt)) { if (debug_detail.isLoggable(Level.FINE)) debug_detail.fine(": : Skipping slice, " + v.name() + " missing"); continue slice_loop; } if (v.missingOutOfBounds()) { if (debug_detail.isLoggable(Level.FINE)) debug.fine(": : Skipping slice, " + v.name() + " out of bounds"); continue slice_loop; } } // Loop through each invariant for (Invariant inv : slice.invs) { if (debug_detail.isLoggable(Level.FINE)) debug_detail.fine(": : Processing invariant: " + inv); if (!inv.isActive()) { if (debug_detail.isLoggable(Level.FINE)) debug_detail.fine(": : skipped non-active " + inv); continue; } // Yoav added if (!activeInvariants.contains(inv)) { // System.out.printf ("skipping invariant %s:%s\n", inv.ppt.name(), // inv.format()); continue; } // String invRep = invariant2str(ppt, inv); testedInvariants.add(inv); InvariantStatus status = inv.add_sample(vt, 1); sample_cnt++; if (status != InvariantStatus.NO_CHANGE) { LineNumberReader lnr = FileIO.data_trace_state.reader; String line = (lnr == null) ? "?" : String.valueOf(lnr.getLineNumber()); if (!quiet) { output_stream.println( "At ppt " + ppt.name + ", Invariant '" + inv.format() + "' invalidated by sample " + Debug.toString(slice.var_infos, vt) + "at line " + line + " in file " + FileIO.data_trace_state.filename); } failedInvariants.add(inv); activeInvariants.remove(inv); error_cnt++; } } } }
private static void checkInvariants() throws IOException { // Read the invariant file PptMap ppts = FileIO.read_serialized_pptmap(inv_file, true); // Yoav: make sure we have unique invariants InvariantFilters fi = InvariantFilters.defaultFilters(); // Set<String> allInvariantsStr = new HashSet<String>(); Set<Invariant> allInvariants = new HashSet<Invariant>(); for (PptTopLevel ppt : ppts.all_ppts()) for (Iterator<PptSlice> i = ppt.views_iterator(); i.hasNext(); ) { PptSlice slice = i.next(); for (Invariant inv : slice.invs) { if (doConf && inv.getConfidence() < Invariant.dkconfig_confidence_limit) { // System.out.printf ("inv ignored (conf): %s:%s\n", inv.ppt.name(), // inv.format()); continue; } if (doFilter && fi.shouldKeep(inv) == null) { // System.out.printf ("inv ignored (filter): %s:%s\n", // inv.ppt.name(), inv.format()); continue; } activeInvariants.add(inv); // String n = invariant2str(ppt, inv); // if (!allInvariants.contains(inv) && allInvariantsStr.contains(n)) throw new // Daikon.TerminationMessage("Two invariants have the same ppt.name+inv.rep:"+n); allInvariants.add(inv); // allInvariantsStr.add(n); } } // Read and process the data trace files FileIO.Processor processor = new InvariantCheckProcessor(); Daikon.FileIOProgress progress = new Daikon.FileIOProgress(); progress.start(); progress.clear(); FileIO.read_data_trace_files(dtrace_files, ppts, processor, false); progress.shouldStop = true; System.out.println(); System.out.printf( "%s: %,d errors found in %,d samples (%s)\n", inv_file, error_cnt, sample_cnt, toPercentage(error_cnt, sample_cnt)); int failedCount = failedInvariants.size(); int testedCount = testedInvariants.size(); String percent = toPercentage(failedCount, testedCount); System.out.println( inv_file + ": " + failedCount + " false positives, out of " + testedCount + ", which is " + percent + "."); if (false) { for (Invariant inv : failedInvariants) { System.out.printf("+%s:%s\n", inv.ppt.name(), inv.format()); } } }