Skip to content
Permalink
Browse files
Make sure every scope gets its own copy of GLOBAL_ENSURE_BLOCK_LABEL
* These labels were being shared across all blocks which caused buggy
  rescue maps being set up across scopes and led to infinite loops
  in block_spec.rb and raise_spec.rb when specs were run with all
  passes enabled after recent InterpreterContext changes.

* This patch fixes that up.
  • Loading branch information
subbuss committed Oct 15, 2014
1 parent 09b0be3 commit 695b38986b97b908556c3b55d9cc5266bba5a722
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 5 deletions.
@@ -1986,7 +1986,7 @@ public void buildMultipleAsgn19Assignment(final MultipleAsgn19Node multipleAsgnN
private void handleBreakAndReturnsInLambdas(IRClosure s) {
Label rBeginLabel = s.getNewLabel();
Label rEndLabel = s.getNewLabel();
Label rescueLabel = Label.GLOBAL_ENSURE_BLOCK_LABEL;
Label rescueLabel = Label.getGlobalEnsureBlockLabel();

// protect the entire body as it exists now with the global ensure block
addInstrAtBeginning(s, new ExceptionRegionStartMarkerInstr(rescueLabel));
@@ -122,7 +122,7 @@ public void addStores(Map<Operand, Operand> varRenameMap) {
BasicBlock geb = cfg.getGlobalEnsureBB();
if (geb == null) {
Variable exc = cfgScope.createTemporaryVariable();
geb = new BasicBlock(cfg, Label.GLOBAL_ENSURE_BLOCK_LABEL);
geb = new BasicBlock(cfg, Label.getGlobalEnsureBlockLabel());
geb.addInstr(new ReceiveJRubyExceptionInstr(exc)); // JRuby implementation exception handling
geb.addInstr(new ThrowExceptionInstr(exc));
cfg.addGlobalEnsureBB(geb);
@@ -9,7 +9,7 @@
// there is exactly one label object with the same label string?
public class Label extends Operand {
public static final Label UNRESCUED_REGION_LABEL = new Label("UNRESCUED_REGION", 0);
public static final Label GLOBAL_ENSURE_BLOCK_LABEL = new Label("_GLOBAL_ENSURE_BLOCK_", 0);
private static final Label GLOBAL_ENSURE_BLOCK_LABEL = new Label("_GLOBAL_ENSURE_BLOCK_", 0);

public final String prefix;
public final int id;
@@ -18,6 +18,9 @@ public class Label extends Operand {
// to fetch the instruction to jump to given a label
private int targetPC = -1;

// Clone to make sure that every scope gets its own copy of this label
public static Label getGlobalEnsureBlockLabel() { return GLOBAL_ENSURE_BLOCK_LABEL.clone(); }

public Label(String prefix, int id) {
super(OperandType.LABEL);

@@ -50,6 +53,10 @@ public boolean equals(Object o) {
return (o instanceof Label) && id == ((Label) o).id && prefix.equals(((Label)o).prefix);
}

public boolean isGlobalEnsureBlockLabel() {
return this.equals(GLOBAL_ENSURE_BLOCK_LABEL);
}

public Label clone() {
Label newL = new Label(prefix, id);
newL.setTargetPC(getTargetPC()); // Strictly not necessary, but, copy everything over
@@ -125,7 +125,7 @@ public Object execute(IRScope scope, Object... data) {
BasicBlock geb = cfg.getGlobalEnsureBB();
if (geb == null) {
Variable exc = scope.createTemporaryVariable();
geb = new BasicBlock(cfg, Label.GLOBAL_ENSURE_BLOCK_LABEL);
geb = new BasicBlock(cfg, Label.getGlobalEnsureBlockLabel());
geb.addInstr(new ReceiveJRubyExceptionInstr(exc)); // JRuby Implementation exception handling
geb.addInstr(new ThrowExceptionInstr(exc));
cfg.addGlobalEnsureBB(geb);
@@ -408,7 +408,7 @@ private BasicBlock buildExitBasicBlock(Stack<ExceptionRegion> nestedExceptionReg
private BasicBlock createBB(Label label, Stack<ExceptionRegion> nestedExceptionRegions) {
BasicBlock basicBlock = new BasicBlock(this, label);
addBasicBlock(basicBlock);
if (label.equals(Label.GLOBAL_ENSURE_BLOCK_LABEL)) {
if (label.isGlobalEnsureBlockLabel()) {
globalEnsureBB = basicBlock;
}

0 comments on commit 695b389

Please sign in to comment.