Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8d93b27b54ce
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: cb5c9110170d
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Jun 8, 2016

  1. Init bitset size after the # of variables have been computed

    * The bitset size computed was always zero
      => in.and(out) effectively pushed in to all false values since
      there were no true values in that set. Fix this by allocating
      a new 'in' bitset the same size as 'out'.
    
    * This led to unnecessarily conservative init results. Due to the
      order in which the missing inits are added, these conservative inits
      were sometimes clobbering earlier already-initialized values.
      I am not fixing that inserting logic in this patch yet since
      it shouldn't be necessary.
    
    * Fixes spec:compiler run
    subbuss committed Jun 8, 2016
    Copy the full SHA
    e4fbb0b View commit details
  2. Fix the order in which missing init instrs are added to entryBB

    * The comments in the file are self-explanatory.
    subbuss committed Jun 8, 2016
    Copy the full SHA
    cb5c911 View commit details
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@ public DefinedVariableNode(DefinedVariablesProblem prob, BasicBlock n) {

@Override
public void init() {
setSize = problem.getDFVarsCount();
// 'null' acts as the TOP for this dataflow analysis
out = null;
}
@@ -38,6 +37,7 @@ public void buildDataFlowVars(Instr i) {
@Override
public void applyPreMeetHandler() {
// 'null' acts as the TOP for this dataflow analysis
setSize = problem.getDFVarsCount();
in = null;
}

@@ -48,8 +48,10 @@ public void compute_MEET(Edge e, DefinedVariableNode pred) {
// if in is TOP, init in to a bitset with all 1's
// so the intersection computes the right value.
if (in == null) {
in = new BitSet(setSize);
in.set(0, setSize);
// Make sure 'in' and 'out' are the same size!
int n = pred.out.size();
in = new BitSet(n);
in.set(0, n);
}

in.and(pred.out);
@@ -83,6 +85,8 @@ public void identifyInits(Set<Variable> undefinedVars) {
parentScopeDepth = 0;
}

// System.out.println("BB " + basicBlock + "; state\n" + toString());

initSolution();
for (Instr i: basicBlock.getInstrs()) {
// Variables that belong to outer scopes should always
@@ -94,7 +98,7 @@ public void identifyInits(Set<Variable> undefinedVars) {
}

if (!tmp.get(problem.getDFVar(v))) {
// System.out.println("Variable " + v + " in instr " + i + " isn't defined!");
// System.out.println("Variable " + v + " in instr " + i + " in " + basicBlock + " isn't defined!");
undefinedVars.add(v);
}
}
@@ -117,8 +121,43 @@ public void finalizeSolution() {
out = tmp;
}

private String printSet(BitSet set) {
StringBuilder buf = new StringBuilder();
int count = 0;
for (int i = 0; i < set.size(); i++) {
if (set.get(i)) {
count++;
buf.append(' ').append(problem.getVariable(i));
if (count % 10 == 0) buf.append("\t\n");
}
}

if (count % 10 != 0) buf.append("\t\t");
return buf.append('\n').toString();
}

@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("\tVars defined on Entry: ");
if (in == null) {
System.out.println("-- NO in!");
} else {
buf.append(printSet(in));
}

buf.append("\n\tVars defined on Exit: ");
if (out == null) {
System.out.println("-- NO out!");
} else {
buf.append(printSet(out));
}

return buf.append('\n').toString();
}

private BitSet in; // Variables defined at entry of this node
private BitSet out; // Variables defined at exit of node
private BitSet tmp; // Temporary state while applying transfer function
private BitSet tmp; // Temporary state while applying transfer function
private int setSize; // Size of the "this.in" and "this.out" bit sets
}
14 changes: 10 additions & 4 deletions core/src/main/java/org/jruby/ir/passes/AddMissingInitsPass.java
Original file line number Diff line number Diff line change
@@ -28,14 +28,20 @@ public Object execute(IRScope scope, Object... data) {

// Add inits to entry
BasicBlock bb = scope.getCFG().getEntryBB();
Variable first = null;
for (Variable v : undefinedVars) {
// System.out.println("Adding missing init for " + v + " in " + scope);
if (first == null) {

// Add lvar inits to the end of the BB
// (so that scopes are pushed before its vars are updated)
// and tmpvar inits to the beginning of the BB
// (so that if a bad analysis causes an already initialized tmp
// to be found uninitialized, this unnecessary init doesn't
// clobber an already updated tmp. The entryBB will not have
// any loads of lvars, so lvars aren't subject to this problem).
if (v instanceof LocalVariable) {
bb.getInstrs().add(new CopyInstr(v, new Nil()));
first = v;
} else {
bb.getInstrs().add(new CopyInstr(v, first));
bb.getInstrs().add(0, new CopyInstr(v, new Nil()));
}
}