// Look up a previously instantiated SubSequence relationship. public static SubSequence find(PptSlice ppt) { Assert.assertTrue(ppt.arity() == 2); for (Invariant inv : ppt.invs) { if (inv instanceof SubSequence) return (SubSequence) inv; } return null; }
// Look up a previously instantiated invariant. public static EltwiseIntEqual find(PptSlice ppt) { Assert.assertTrue(ppt.arity() == 1); for (Invariant inv : ppt.invs) { if (inv instanceof EltwiseIntEqual) return (EltwiseIntEqual) inv; } return null; }
/** * 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); }
public boolean isSameFormula(Invariant inv) { Assert.assertTrue(inv instanceof SubSequence); return (true); }
/** * 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; }
/** * @return Array "a" such that a[0] is a valid discardCode and a[1] is a valid discardString. If * the Invariant is not an obvious subsequence, both are null */ public static Object[] isObviousSubSequence(VarInfo subvar, VarInfo supervar) { // Must typecheck since this could be called with non sequence variables in // some methods. 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 new Object[] {null, null}; } if (debug.isLoggable(Level.FINE)) { debug.fine("isObviousSubSequence " + subvar.name() + "in " + supervar.name()); } // Standard discard reason/string DiscardCode discardCode = DiscardCode.obvious; String discardString = subvar.name() + " obvious subset/subsequence of " + supervar.name(); // For unions and intersections, it probably doesn't make sense to // do subsequence or subset detection. This is mainly to prevent // invariants of the form (x subset of union(x, y)) but this means // we also miss those of the form (z subset of union(x,y)) which // might be useful. Subsequence, however, seems totally useless // on unions and intersections. if (supervar.derived instanceof SequenceScalarIntersection || supervar.derived instanceof SequenceScalarUnion || subvar.derived instanceof SequenceScalarIntersection || subvar.derived instanceof SequenceScalarUnion) { discardCode = DiscardCode.obvious; discardString = "Invariants involving subsets/subsequences of unions/intersections" + "are suppressed"; debug.fine(" returning true because of union or intersection"); return new Object[] {discardCode, discardString}; } if (subvar.derived instanceof SequencesPredicate) { // It's not useful that predicate(x[], b[]) is a subsequence or subset // of x[] SequencesPredicate derived = (SequencesPredicate) subvar.derived; if (derived.var1().equals(supervar)) { discardCode = DiscardCode.obvious; discardString = subvar.name() + " is derived from " + supervar.name(); debug.fine(" returning true because of predicate slicing"); return new Object[] {discardCode, discardString + " [pred slicing]"}; } } VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); if (subvar_super == null) { // If it's not a union, intersection or a subsequence, it's not obvious debug.fine(" returning false because subvar_super == null"); return new Object[] {null, null}; } if (subvar_super == supervar) { // System.out.println("SubSequence.isObviousDerived(" + subvar.name() + ", " + supervar.name + // ") = true"); // System.out.println(" details: subvar_super=" + subvar_super.name + "; supervar_super=" + // supervar.isDerivedSubSequenceOf() == null ? "null" : // supervar.isDerivedSubSequenceOf().name); discardCode = DiscardCode.obvious; discardString = subvar.name() + "==" + supervar.name(); debug.fine(" returning true because subvar_super == supervar"); return new Object[] {discardCode, discardString + " [subvar_super == supervar]"}; } // a[i+a..j+b] cmp a[i+c..j+d] VarInfo supervar_super = supervar.isDerivedSubSequenceOf(); // we know subvar_super != null due to check above if (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)) { // In "A[i..j] subseq B[k..l]": i=sub_left_var, j=sub_right_var, // k=super_left_var, l=super_right_var. 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 = false, right_included = false; if (super_left_var == null) left_included = true; if (super_left_var == sub_left_var) { if (super_left_shift < sub_left_shift) left_included = true; } if (super_right_var == null) right_included = true; if (super_right_var == sub_right_var) { if (super_right_shift > sub_right_shift) right_included = true; } if (left_included && right_included) { discardCode = DiscardCode.obvious; discardString = subvar.name() + " obvious subset/subsequence of " + supervar.name(); return new Object[] {discardCode, discardString + " [obvious]"}; } } else if ((subvar.derived instanceof SequenceStringSubsequence) && (supervar.derived instanceof SequenceStringSubsequence)) { // Copied from (an old version) just above // XXX I think this code is dead; why isn't it just produced // from the above by macro expansion? -smcc 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 (index1 == index2) { if (start1 == true && start2 == true) { if (shift1 <= shift2) return new Object[] {discardCode, discardString + " [shift1]"}; } else if (start1 == false && start2 == false) { if (shift1 >= shift2) return new Object[] {discardCode, discardString + " [shift2]"}; } } } else { Assert.assertTrue( false, "how can this happen? " + subvar.name() + " " + subvar.derived.getClass() + " " + supervar.name() + " " + supervar.derived.getClass()); } } return new Object[] {null, null}; }
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++; } } } }