package org.jruby.ir.instructions;
import org.jruby.RubyModule;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Label;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
public class ModuleVersionGuardInstr extends TwoOperandInstr implements FixedArityInstr {
private final int expectedVersion;
private final RubyModule module;
public ModuleVersionGuardInstr(RubyModule module, int expectedVersion, Operand candidateObj, Label failurePathLabel) {
super(Operation.MODULE_GUARD, candidateObj, failurePathLabel);
this.module = module;
this.expectedVersion = expectedVersion;
}
public Operand getCandidateObject() {
return getOperand1();
}
public Label getFailurePathLabel() {
return (Label) getOperand2();
}
public RubyModule getModule() {
return module;
}
public int getExpectedVersion() {
return expectedVersion;
}
@Override
public String[] toStringNonOperandArgs() {
return new String[] { "name: " + module.getName(), "expected_version: " + expectedVersion};
}
@Override
public Instr clone(CloneInfo ii) {
return new ModuleVersionGuardInstr(module, expectedVersion, getCandidateObject().cloneForInlining(ii),
ii.getRenamedLabel(getFailurePathLabel()));
}
private boolean versionMatches(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
IRubyObject receiver = (IRubyObject) getCandidateObject().retrieve(context, self, currScope, currDynScope, temp);
return (receiver.getMetaClass().getGeneration() == getExpectedVersion());
}
@Override
public int interpretAndGetNewIPC(ThreadContext context, DynamicScope currDynScope, StaticScope currScope, IRubyObject self, Object[] temp, int ipc) {
return versionMatches(context, currScope, currDynScope, self, temp) ? ipc : getFailurePathLabel().getTargetPC();
}
@Override
public void visit(IRVisitor visitor) {
visitor.ModuleVersionGuardInstr(this);
}
}