// - used in the closure (FIXME: Strictly only those vars that are live at the call site -- but we dont have this info!)
Set<Variable> newDirtyVars = new HashSet<Variable>(dirtyVars);
for (Variable v : dirtyVars) {
if (spillAllVars || cl_bsp.scopeUsesVariable(v)) {
// FIXME: This may not need check for local variable if it is guaranteed to only be local variables.
instrs.add(new StoreToBindingInstr(s, v.getName(), v));
newDirtyVars.remove(v);
} // These variables will be spilt inside the closure -- so they will no longer be dirty after the call site!
else if (cl_bsp.scopeDefinesVariable(v)) {
newDirtyVars.remove(v);
}
}
dirtyVars = newDirtyVars;
instrs.next();
// add stores in the closure
((BindingStorePlacementProblem) cl_cfg.getDataFlowSolution(bsp.getName())).addStoreAndBindingAllocInstructions();
} // Call has no closure && it requires stores
else if (call.requiresBinding()) {
instrs.previous();
if (!bindingAllocated) {
instrs.add(new AllocateBindingInstr(s));
bindingAllocated = true;
}
for (Variable v : dirtyVars) {
instrs.add(new StoreToBindingInstr(s, v.getName(), v));
}
instrs.next();
dirtyVars.clear();
}
} else if ((i instanceof ClosureReturnInstr) || (i instanceof BREAK_Instr)) {
// At closure return and break instructions (both of which are exits from the closure),
// we need a binding store on exit only for vars that are both:
//
// (a) dirty,
// (b) live on exit from the closure
// condition reqd. because the variable could be dirty but not used outside.
// Ex: s=0; a.each { |i| j = i+1; sum += j; }; puts sum
// i,j are dirty inside the block, but not used outside
//
// If this also happens to be exit BB, we would have intersected already earlier -- so no need to do it again!
if (!amExitBB) {
/**
LiveVariablesProblem lvp = (LiveVariablesProblem)cfg.getDataFlowSolution(DataFlowConstants.LVP_NAME);
java.util.Collection<Variable> liveVars = lvp.getVarsLiveOnEntry();
System.out.println("\n[@Closure Instr<" + i + ">] For CFG " + cfg + ":");
System.out.println("\t--> Dirty vars here : " + java.util.Arrays.toString(dirtyVars.toArray()));
System.out.println("\t--> Vars live on entry: " + (liveVars == null ? "NONE" : java.util.Arrays.toString(liveVars.toArray())));
liveVars = lvp.getVarsLiveOnExit();
System.out.println("\t--> Vars live on exit : " + (liveVars == null ? "NONE" : java.util.Arrays.toString(liveVars.toArray())));
**/
LiveVariablesProblem lvp = (LiveVariablesProblem)cfg.getDataFlowSolution(DataFlowConstants.LVP_NAME);
java.util.Collection<Variable> liveVars = lvp.getVarsLiveOnExit();
if (liveVars != null)
dirtyVars.retainAll(liveVars); // Intersection with variables live on exit from the scope
else
dirtyVars.clear();
}
instrs.previous();
for (Variable v : dirtyVars) {
instrs.add(new StoreToBindingInstr(s, v.getName(), v));
}
instrs.next();
// Nothing is dirty anymore -- everything that needs spilling has been spilt
dirtyVars.clear();
}
Variable v = i.getResult();
if ((v != null) && (v instanceof LocalVariable)) dirtyVars.add(v);
}
// If this is the exit BB, add binding stores for all vars that are still dirty
if (amExitBB) {
for (Variable v : dirtyVars) {
instrs.add(new StoreToBindingInstr(s, v.getName(), v));
}
}
}