* -------------------------------------------------------------------- */
boolean mightRequireGlobalEnsureBlock = false;
Set<LocalVariable> dirtyVars = null;
IRScope cfgScope = getScope();
CFG cfg = cfgScope.cfg();
this.scopeHasLocalVarStores = false;
this.scopeHasUnrescuedExceptions = false;
if (cfgScope instanceof IRClosure) {
mightRequireGlobalEnsureBlock = true;
dirtyVars = new HashSet<LocalVariable>();
}
// Add local-var stores
for (StoreLocalVarPlacementNode bspn: flowGraphNodes) {
boolean bbAddedStores;
// SSS: This is highly conservative. If the bb has an exception raising instr.
// and we dont have a rescuer, only then do we have unrescued exceptions.
// Right now, we are only checking for rescuers.
boolean bbHasUnrescuedExceptions = !bspn.hasExceptionsRescued();
if (mightRequireGlobalEnsureBlock && bbHasUnrescuedExceptions) {
bbAddedStores = bspn.addStores(varRenameMap, dirtyVars);
} else {
bbAddedStores = bspn.addStores(varRenameMap, null);
}
scopeHasUnrescuedExceptions = scopeHasUnrescuedExceptions || bbHasUnrescuedExceptions;
scopeHasLocalVarStores = scopeHasLocalVarStores || bbAddedStores;
}
// Allocate global-ensure block, if necessary
if ((mightRequireGlobalEnsureBlock == true) && !dirtyVars.isEmpty()) {
ListIterator<Instr> instrs;
BasicBlock geb = cfg.getGlobalEnsureBB();
if (geb == null) {
Variable exc = cfgScope.createTemporaryVariable();
geb = new BasicBlock(cfg, Label.getGlobalEnsureBlockLabel());
geb.addInstr(new ReceiveJRubyExceptionInstr(exc)); // JRuby implementation exception handling
geb.addInstr(new ThrowExceptionInstr(exc));
cfg.addGlobalEnsureBB(geb);
}
instrs = geb.getInstrs().listIterator(geb.getInstrs().size());
Instr i = instrs.previous();
// Assumption: Last instr should always be a control-transfer instruction