public DiscardInfo isObviousStatically(VarInfo[] vis) { VarInfo var1 = vis[0]; VarInfo var2 = vis[1]; Object[] obv1 = SubSequence.isObviousSubSequence(var1, var2); Object[] obv2 = SubSequence.isObviousSubSequence(var2, var1); if (obv1[1] != null) { Global.implied_noninstantiated_invariants++; return new DiscardInfo(this, (DiscardCode) obv1[0], (String) obv1[1]); } else if (obv2[1] != null) { Global.implied_noninstantiated_invariants++; return new DiscardInfo(this, (DiscardCode) obv1[0], (String) obv1[1]); } // Don't instantiate if the variables can't have order if (!var1.aux.getFlag(VarInfoAux.HAS_ORDER) || !var2.aux.getFlag(VarInfoAux.HAS_ORDER)) { if (debug.isLoggable(Level.FINE)) { debug.fine( "Not instantitating for because order has no meaning: " + var1.name() + " and " + var2.name()); } return new DiscardInfo( this, DiscardCode.obvious, "Obvious statically since order has no meaning"); } return super.isObviousStatically(vis); }
protected boolean isParam() { return (base1.isParam() || base2.isParam() || base3.isParam()); // VIN // return (base1.aux.getFlag(VarInfoAux.IS_PARAM) // || base2.aux.getFlag(VarInfoAux.IS_PARAM) // || base3.aux.getFlag(VarInfoAux.IS_PARAM)); }
public DiscardInfo isObviousStatically(VarInfo[] vis) { VarInfo subvar = var1(vis); VarInfo supervar = var2(vis); // check for x[i..j] subsequence of x[] VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); if (subvar_super == supervar) { debug.fine(" returning true because subvar_super == supervar"); return new DiscardInfo(this, DiscardCode.obvious, "x[i..j] subsequence of x[] is obvious"); } Object[] obv1 = SubSequence.isObviousSubSequence(subvar, supervar); if (obv1[1] != null) { return new DiscardInfo(this, (DiscardCode) obv1[0], (String) obv1[1]); } // JHP: This is not a valid obvious check, since it doesn't imply that // the invariant is true. if (!subvar.aux.getFlag(VarInfoAux.HAS_ORDER) || !supervar.aux.getFlag(VarInfoAux.HAS_ORDER)) { // Doesn't make sense to consider subsequence if order doens't matter return new DiscardInfo( this, DiscardCode.obvious, "Order doesn't matter, so subsequence is meaningless"); } return super.isObviousStatically(vis); }
public UnaryDerivation /*@Nullable*/[] instantiate(VarInfo vi) { if (!SequenceLength.dkconfig_enabled) { return null; } if (!vi.is_direct_array()) return null; if (!vi.aux.getFlag(VarInfoAux.HAS_SIZE)) { // Don't derive if auxiliary info says size of this collection // has no meaning return null; } if (!SequenceLength.applicable(vi)) { Global.tautological_suppressed_derived_variables++; return null; } if (debug.isLoggable(Level.FINE)) { debug.fine("Instantiating for " + vi.name() + " in " + vi.ppt); } if (vi.aux.getFlag(VarInfoAux.NULL_TERMINATING)) { return new UnaryDerivation[] {new SequenceLength(vi, 0), new SequenceLength(vi, -1)}; } else { // If it can't terminate with nulls, then all members are important, // so we only need to do shift for 0 return new UnaryDerivation[] {new SequenceLength(vi, 0)}; } }
private boolean includePosteriorVarsCheckLoops(VarInfo prior) { boolean loopDetected = false; for (int i = 0, n = pi.blocklist.length; i < n; i++) { BasicBlock b = pi.blocklist[i]; VarInfo v = pi.vars[slot][b.pc1]; if (v == prior) { for (int j = 0, m = b.next != null ? b.next.length : 0; j < m; j++) { BasicBlock b1 = b.next[j]; VarInfo v1 = pi.vars[slot][b1.pc0]; if (v1 != prior) { loopDetected |= includeVarAndPosteriorVars(v1); if (v1.isPhiVar()) includePriorVarsIgnoreLoops(v1); } } } else { for (int pc = b.pc1 - 1; pc >= b.pc0; pc--) { if (pi.vars[slot][pc] == prior) { loopDetected |= includeVarAndPosteriorVars(pi.vars[slot][pc + 1]); break; } } } } return loopDetected; }
/** * Checks to see if the same invariant exists over supersequences of these variables: * * <p>(A[] op B[]) ^ (i == j) ==> A[i..] op B[j..] (A[] op B[]) ^ (i == j) ==> A[..i] op B[..j] */ private DiscardInfo superseq_implies(VarInfo[] vis) { // Make sure the variables are SequenceScalarSubsequence with the same start/end VarInfo v1 = vis[0]; VarInfo v2 = vis[1]; if (!v1.isDerived() || !(v1.derived instanceof SequenceScalarSubsequence)) return (null); if (!v2.isDerived() || !(v2.derived instanceof SequenceScalarSubsequence)) return (null); SequenceScalarSubsequence der1 = (SequenceScalarSubsequence) v1.derived; SequenceScalarSubsequence der2 = (SequenceScalarSubsequence) v2.derived; if ((der1.from_start != der2.from_start) || (der1.index_shift != der2.index_shift)) return (null); // Make sure the subscripts are equal DiscardInfo di = new DiscardInfo(this, DiscardCode.obvious, ""); if (!ppt.parent.check_implied_canonical(di, der1.sclvar(), der2.sclvar(), IntEqual.get_proto())) return (null); // See if the super-sequences have the same invariant if (!ppt.parent.check_implied_canonical( di, der1.seqvar(), der2.seqvar(), PairwiseIntLessThan.get_proto())) return (null); // Add in the vis variables to di reason (if they are different) di.add_implied_vis(vis); return (di); }
/* IOA */ public String format_ioa() { if (var1().isIOASet() || var2().isIOASet()) return "Not valid for sets: " + format(); Quantify.IOAQuantification quant1 = VarInfo.get_ioa_quantify(var1()); Quantify.IOAQuantification quant2 = VarInfo.get_ioa_quantify(var2()); return quant1.getQuantifierExp() + quant1.getVarIndexedString(0) + " " + "< " + quant2.getVarIndexedString(0) + quant1.getClosingExp(); }
// Upval info representing the implied context containing only the environment. public UpvalInfo(ProtoInfo pi) { this.pi = pi; this.slot = 0; this.nvars = 1; this.var = new VarInfo[] {VarInfo.PARAM(0)}; this.rw = false; }
public ValueAndModified computeValueAndModified(ValueTuple vt) { int source_mod = base.getModified(vt); if (source_mod == ValueTuple.MISSING_NONSENSICAL) return ValueAndModified.MISSING_NONSENSICAL; if (source_mod == ValueTuple.MISSING_FLOW) return ValueAndModified.MISSING_FLOW; return computeValueAndModifiedImpl(vt); }
public String format_simplify() { String[] form = VarInfo.simplify_quantify(QuantFlags.adjacent(), var(), var()); String comparator = "EQ"; return form[0] + "(" + comparator + " " + form[1] + " " + form[2] + ")" + form[3]; }
private VariableManager(VarInfo varInfo, String condition, String className) throws ParseException { this.varInfo = varInfo; name = varInfo.name(); compilableName = compilableName(varInfo, className); fieldName = fieldName(varInfo, className); varName = varName(varInfo, className); type = makeIndexIfNeeded(getVarType(varInfo), compilableName, varInfo, condition); }
private boolean includeVarAndPosteriorVars(VarInfo var) { if (var == null || var == VarInfo.INVALID) return false; if (var.upvalue == this) return true; var.upvalue = this; appendVar(var); if (isLoopVariable(var)) return false; boolean loopDetected = includePosteriorVarsCheckLoops(var); if (loopDetected) includePriorVarsIgnoreLoops(var); return loopDetected; }
/*@Pure*/ public /*@Nullable*/ DiscardInfo isObviousDynamically(VarInfo[] vis) { // Do not show x-1 = a (mod b). There must be a different mod // invariant over x. JHP: This should really find the invariant rather // than presuming it is true. VarInfo x = vis[0]; if ((x.derived instanceof SequenceLength) && (((SequenceLength) x.derived).shift != 0)) { return (new DiscardInfo( this, DiscardCode.obvious, "The invariant " + format() + " is implied by a mod invariant " + "over " + x.name() + " without the offset")); } return (null); }
/** * 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; }
/* IOA */ public String format_ioa() { Quantify.IOAQuantification quant = VarInfo.get_ioa_quantify(var(), var()); String result = quant.getQuantifierExp() + "(" + quant.getMembershipRestriction(0) + " /\\ " + quant.getMembershipRestriction(1); // i \in X /\ j \in X => X[i] = X[j] result += ") => " + quant.getVarIndexedString(0) + " = " + quant.getVarIndexedString(1); return result + quant.getClosingExp(); }
/** * Calculates the base name of a variable. The base name of a variable is the part of the variable * with prefixes "this." and className removed, and "orig()" replaced by "orig_". For example * orig(this.x) goes to orig_x. If className is "Class" then "Class.x" would yield "x" and * "someOtherClass.x" would yield "someOtherClass_x". Finally, Java Reserved words are replaced * with appropriate substitutes. * * @param varInfo the VarInfo for the variable whose base name is desired. * @return the base name of the variable represented by varInfo. */ private static String getBaseName(VarInfo varInfo, String className) { String name = varInfo.name(); name = replaceReservedWords(name); if (name.length() > 5 && name.substring(0, 5).equals("orig(") && name.endsWith(")")) { name = name.substring(5, name.length() - 1); name = fixPrefixes(name, className); name = "orig_" + name; } else { name = fixPrefixes(name, className); } name = name.replace('.', '_'); name = remove(name, ']'); name = remove(name, '['); return name; }
public BinaryDerivation /*@Nullable*/[] instantiate(VarInfo var1, VarInfo var2) { boolean enabled = SequencesPredicate.dkconfig_enabled; if (!enabled) return null; if (debug.isLoggable(Level.FINE)) { debug.fine("Trying to instantiate " + var1.name() + " and " + var2.name()); } if (!(var1.rep_type.isArray()) || !(var2.rep_type.isArray())) { return null; } if (!var1.aux.getFlag(VarInfoAux.HAS_ORDER) || !var2.aux.getFlag(VarInfoAux.HAS_ORDER)) { // Order doesn't matter, then predication is meaningless return null; } if (SequencesPredicate.dkconfig_boolOnly) { if (!(var2.file_rep_type == ProglangType.BOOLEAN_ARRAY)) { return null; } } if (var1.derived != null || var2.derived != null) { // From derived variables. Don't derive. return null; } if (SequencesPredicate.dkconfig_fieldOnly) { if (!var1.is_field() || !var2.is_field()) return null; if (!var1.has_same_parent(var2)) return null; } else { // There may be predications that aren't of the x.a and x.b type } // Now we finally can derive if (debug.isLoggable(Level.FINE)) { debug.fine( var1.ppt + ": " + var1.name() + " and " + var2.name() + " are worth deriving from"); } return new BinaryDerivation[] { new SequencesPredicate(var1, var2, 0, "false"), new SequencesPredicate(var1, var2, 1, "true"), // new SequencesPredicate (var1, var2, 0, "nonNull", false), }; }
// (Seems overkill to check for other transitive relationships. // Eventually that is probably the right thing, however.) public DiscardInfo isObviousDynamically(VarInfo[] vis) { // System.out.println("checking isObviousImplied for: " + format()); if (debug.isLoggable(Level.FINE)) { debug.fine("isObviousDynamically: checking " + vis[0].name() + " in " + vis[1].name()); } DiscardInfo super_result = super.isObviousDynamically(vis); if (super_result != null) { return super_result; } VarInfo subvar = var1(vis); VarInfo supervar = var2(vis); // JHP: The next check is an un-interesting check, not // an obvious check. We need to figure out how to resolve this. // Uninteresting if this is of the form x[0..i] subsequence // x[0..j]. Not necessarily obvious. VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); VarInfo supervar_super = supervar.isDerivedSubSequenceOf(); if (subvar_super != null && subvar_super == supervar_super) { debug.fine(" returning true because subvar_super == supervar_super"); return new DiscardInfo( this, DiscardCode.obvious, "x[0..i] subsequence of x[0..j] is uninteresting"); } if (isObviousSubSequenceDynamically(this, subvar, supervar)) { return new DiscardInfo( this, DiscardCode.obvious, subvar.name() + " is an obvious subsequence of " + supervar.name()); } return null; }
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); } }
/** * 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); } } }
/** * Returns whether or not the specified ternary slice should be created. The slice should not be * created if any of the following are true - Any var is an array - Any of the vars are not * compatible with the others - Any var is not (integral or float) * * <p>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). In addition, we * do want to create the reflexive ones and partially reflexive invariants. * * @see daikon.PptTopLevel#is_slice_ok(VarInfo, VarInfo, VarInfo) */ public static boolean is_slice_ok(VarInfo v1, VarInfo v2, VarInfo v3) { // Vars must be compatible return (v1.compatible(v2) && v1.compatible(v3) && v2.compatible(v3)); }
/** * Returns whether or not the specified binary slice should be created. The slice should not be * created if the vars not compatible. * * <p>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). * * @see daikon.PptTopLevel#is_slice_ok(VarInfo, VarInfo) */ public static boolean is_slice_ok(VarInfo v1, VarInfo v2) { return v1.compatible(v2); }
// 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(); }
protected VarInfo makeVarInfo() { return VarInfo.make_subscript(base, null, index); }
public boolean isDerivedFromNonCanonical() { // We insist that both are canonical, not just one. return !(base1.isCanonical() && base2.isCanonical() && base3.isCanonical()); }
/** * @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}; }
public String format_esc() { String[] form = VarInfo.esc_quantify(false, var(), var()); return form[0] + "((i+1 == j) ==> (" + form[1] + " < " + form[2] + "))" + form[3]; }
public String format_esc() { String[] form = VarInfo.esc_quantify(false, var(), var()); return form[0] + "(" + form[1] + " == " + form[2] + ")" + form[3]; }
/** * 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; }
public int derivedDepth() { return 1 + Math.max(base1.derivedDepth(), Math.max(base2.derivedDepth(), base3.derivedDepth())); }