org.jruby.ir.operands.Label Maven / Gradle / Ivy
package org.jruby.ir.operands;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.persistence.IRReaderDecoder;
import org.jruby.ir.persistence.IRWriterEncoder;
import org.jruby.ir.transformations.inlining.CloneInfo;
import java.util.List;
// SSS FIXME: Should we try to enforce the canonical property that within a method,
// there is exactly one label object with the same label string?
public class Label extends Operand {
// This is for 'ensure's at the end of top-level constructs ('def foo; ensure; end' or 'class Foo; ensure; end')
public static final Label UNRESCUED_REGION_LABEL = new Label("UNRESCUED_REGION", 0);
private static final Label GLOBAL_ENSURE_BLOCK_LABEL = new Label("_GLOBAL_ENSURE_BLOCK_", 0);
public final String prefix;
public final int id;
// This is the PC (program counter == array index) for the label target -- this field is used during interpretation
// 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();
this.prefix = prefix;
this.id = id;
}
@Override
public OperandType getOperandType() {
return OperandType.LABEL;
}
@Override
public String toString() {
return prefix + '_' + id + ':' + targetPC;
}
@Override
public void addUsedVariables(List l) {
/* Nothing to do */
}
@Override
public boolean canCopyPropagate() {
return true;
}
@Override
public int hashCode() {
return 11 * (77 + System.identityHashCode(prefix)) + id;
}
@Override
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
return newL;
}
@Override
public Operand cloneForInlining(CloneInfo ii) {
return ii.getRenamedLabel(this);
}
public void setTargetPC(int i) {
this.targetPC = i;
}
public int getTargetPC() {
return this.targetPC;
}
@Override
public void encode(IRWriterEncoder e) {
super.encode(e);
e.encode(prefix);
e.encode(id);
}
public static Label decode(IRReaderDecoder d) {
String prefix = d.decodeString();
int id = d.decodeInt();
// Special case of label
if ("_GLOBAL_ENSURE_BLOCK".equals(prefix)) return new Label("_GLOBAL_ENSURE_BLOCK", 0);
// Check if this label was already created
// Important! Program would not be interpreted correctly
// if new name will be created every time
String fullLabel = prefix + '_' + id;
if (d.getVars().containsKey(fullLabel)) {
return (Label) d.getVars().get(fullLabel);
}
Label newLabel = new Label(prefix, id);
// Add to context for future reuse
d.getVars().put(fullLabel, newLabel);
return newLabel;
}
@Override
public void visit(IRVisitor visitor) {
visitor.Label(this);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy