package gov.nasa.jpf.vm.va; import java.util.Collection; import cmu.conditional.Conditional; import cmu.conditional.IChoice; import de.fosd.typechef.featureexpr.FeatureExpr; import de.fosd.typechef.featureexpr.FeatureExprFactory; /** * Uses two different kinsd of {@link StackHandler}. * One stack for unconditional values to avoid map. * Another stack for conditional values. * * The HybridStackHandler checks when to use which {@link StackHandler} and may transform on stack to the other. * * @author Jens Meinicke * */ public class HybridStackHandler implements Cloneable, IStackHandler { /** Locals are directly accessed with index **/ private IStackHandler stackHandler; public IStackHandler getStackHandler() { return stackHandler; } public static NormalStack normalStack = NormalStack.OneStack; public enum NormalStack { OneStack, JPFStack; } public static LiftedStack liftedStack = LiftedStack.Buffered; public enum LiftedStack { Default, Buffered } private static IStackHandler createNomalStack(FeatureExpr ctx, int nLocals, int nOperands) { switch (normalStack) { case JPFStack: return new JPFStackHandler(ctx, nLocals, nOperands); case OneStack: return new OneStackHandler(ctx, nLocals, nOperands); default: throw new RuntimeException(normalStack + " not supported"); } } private static IStackHandler createLiftedStack(FeatureExpr ctx, int nLocals, int nOperands) { switch (liftedStack) { case Buffered: return new BufferedStackHandler(ctx, nLocals, nOperands); case Default: return new StackHandler(ctx, nLocals, nOperands); default: throw new RuntimeException(liftedStack + " not supported"); } } protected int length = 0; private boolean lifted = false; public boolean isLifted() { return lifted; } public FeatureExpr stackCTX; private final int nLocals; private final int nOperands; public HybridStackHandler(FeatureExpr ctx, int nLocals, int nOperands) { stackHandler = createNomalStack(ctx, nLocals, nOperands); stackCTX = ctx; this.nLocals = nLocals; this.nOperands = nOperands; } /** * Copy constructor */ public HybridStackHandler(HybridStackHandler stackHandler) { this.stackHandler = stackHandler.stackHandler.clone(); this.stackCTX= this.stackHandler.getCtx(); this.nLocals = stackHandler.nLocals; this.nOperands = stackHandler.nOperands; this.lifted = stackHandler.lifted; } public HybridStackHandler() { stackHandler = createNomalStack(FeatureExprFactory.True(), 0, 0); stackCTX = FeatureExprFactory.True(); this.nLocals = 0; this.nOperands = 0; this.lifted = false; } @Override public FeatureExpr getCtx() { return stackCTX; } @Override public int getStackWidth() { return stackHandler.getStackWidth(); } @Override public int getLocalWidth() { return stackHandler.getLocalWidth(); } @Override public String getMaxLocal() { return stackHandler.getMaxLocal(); } @Override public IStackHandler clone() { return new HybridStackHandler(this); } @Override public int getLength() { return stackHandler.getLength(); } @Override public Conditional<Stack> getStack() { return stackHandler.getStack(); } @Override public void pushLocal(FeatureExpr ctx, int index) { checkCTX(ctx); stackHandler.pushLocal(ctx, index); } @Override public void pushLongLocal(FeatureExpr ctx, int index) { stackHandler.pushLongLocal(ctx, index); } @Override public void storeOperand(FeatureExpr ctx, int index) { checkCTX(ctx); stackHandler.storeOperand(ctx, index); } @Override public void storeLongOperand(FeatureExpr ctx, int index) { stackHandler.storeLongOperand(ctx, index); } @Override public void setLocal(FeatureExpr ctx, int index, Conditional<Integer> value, boolean isRef) { checkCTX(ctx); checkValue(value); stackHandler.setLocal(ctx, index, value, isRef); } @Override public void setLocal(FeatureExpr ctx, int index, int value, boolean isRef) { checkCTX(ctx); stackHandler.setLocal(ctx, index, value, isRef); } @Override public Conditional<Integer> getLocal(FeatureExpr ctx, int index) { return stackHandler.getLocal(ctx, index); } @Override public boolean isRefLocal(FeatureExpr ctx, int index) { return stackHandler.isRefLocal(ctx, index); } @Override public <T> void push(FeatureExpr ctx, T value) { stackHandler.push(ctx, value); } @Override public void push(FeatureExpr ctx, Object value, boolean isRef) { checkCTX(ctx); checkValueO(value, ctx); stackHandler.push(ctx, value, isRef); } /* (non-Javadoc) * @see gov.nasa.jpf.vm.IStackHandler#pop(de.fosd.typechef.featureexpr.FeatureExpr) */ @Override public Conditional<Integer> pop(final FeatureExpr ctx) { return pop(ctx, Type.INT); } /* (non-Javadoc) * @see gov.nasa.jpf.vm.IStackHandler#popLong(de.fosd.typechef.featureexpr.FeatureExpr) */ @Override public Conditional<Long> popLong(final FeatureExpr ctx) { return pop(ctx, Type.LONG); } /* (non-Javadoc) * @see gov.nasa.jpf.vm.IStackHandler#popDouble(de.fosd.typechef.featureexpr.FeatureExpr) */ @Override public Conditional<Double> popDouble(final FeatureExpr ctx) { return pop(ctx, Type.DOUBLE); } /* (non-Javadoc) * @see gov.nasa.jpf.vm.IStackHandler#popFloat(de.fosd.typechef.featureexpr.FeatureExpr) */ @Override public Conditional<Float> popFloat(final FeatureExpr ctx) { return pop(ctx, Type.FLOAT); } @Override public <T> Conditional<T> pop(FeatureExpr ctx, Type t) { checkCTX(ctx); return stackHandler.pop(ctx, t); } @Override public void pop(FeatureExpr ctx, int n) { checkCTX(ctx); stackHandler.pop(ctx, n); } @Override public Conditional<Integer> peek(FeatureExpr ctx) { return stackHandler.peek(ctx); } @Override public Conditional<Integer> peek(FeatureExpr ctx, int offset) { return stackHandler.peek(ctx, offset); } @Override public Conditional<Double> peekDouble(FeatureExpr ctx, int offset) { return stackHandler.peekDouble(ctx, offset); } @Override public Conditional<Long> peekLong(FeatureExpr ctx, int offset) { return stackHandler.peekLong(ctx, offset); } @Override public Conditional<Float> peekFloat(FeatureExpr ctx, int offset) { return stackHandler.peekFloat(ctx, offset); } @Override public boolean isRef(FeatureExpr ctx, int offset) { checkCTX(ctx); return stackHandler.isRef(ctx, offset); } @Override public void set(FeatureExpr ctx, int offset, int value, boolean isRef) { stackHandler.set(ctx, offset, value, isRef); } @Override public Conditional<Integer> getTop() { return stackHandler.getTop(); } @Override public void setTop(FeatureExpr ctx, int i) { stackHandler.setTop(ctx, i); } @Override public void clear(FeatureExpr ctx) { checkCTX(ctx); stackHandler.clear(ctx); } @Override public int[] getSlots() { return stackHandler.getSlots(); } @Override public int[] getSlots(FeatureExpr ctx) { return stackHandler.getSlots(ctx); } @Override public boolean hasAnyRef(FeatureExpr ctx) { return stackHandler.hasAnyRef(ctx); } @Override public void dup_x1(FeatureExpr ctx) { checkCTX(ctx); stackHandler.dup_x1(ctx); } @Override public void dup2_x2(FeatureExpr ctx) { checkCTX(ctx); stackHandler.dup2_x2(ctx); } @Override public void dup2_x1(FeatureExpr ctx) { checkCTX(ctx); stackHandler.dup2_x1(ctx); } @Override public void dup2(FeatureExpr ctx) { checkCTX(ctx); stackHandler.dup2(ctx); } @Override public void dup(FeatureExpr ctx) { checkCTX(ctx); stackHandler.dup(ctx); } @Override public void dup_x2(FeatureExpr ctx) { checkCTX(ctx); stackHandler.dup_x2(ctx); } @Override public void swap(FeatureExpr ctx) { checkCTX(ctx); stackHandler.swap(ctx); } @Override public void setCtx(FeatureExpr ctx) { stackCTX = ctx; stackHandler.setCtx(ctx); } @Override public Collection<Integer> getAllReferences() { return stackHandler.getAllReferences(); } @Override public void IINC(FeatureExpr ctx, int index, int increment) { stackHandler.IINC(ctx, index, increment); } @Override public Object getLocal(int index) { return stackHandler.getLocal(index); } private void checkCTX(FeatureExpr ctx) { if (!lifted && !stackCTX.equals(ctx)) { createNewStackHandler(); } } private void checkValue(Conditional<?> value) { if (!lifted && !value.isOne()) { if (!((Conditional<?>)value).simplify(stackCTX).isOne()) { createNewStackHandler(); } } } private void checkValueO(Object value, FeatureExpr ctx) { if (!lifted && value instanceof IChoice<?>) { if (!((Conditional<?>)value).simplify(ctx).simplify(stackCTX).isOne()) { createNewStackHandler(); } } } private void createNewStackHandler() { lifted = true; final IStackHandler newStackHandler = createLiftedStack(stackCTX, nLocals, nOperands); int i = 0; final int[] slots = stackHandler.getSlots(); for (;i < nLocals;i++) { newStackHandler.setLocal(stackCTX, i, slots[i], stackHandler.isRefLocal(FeatureExprFactory.True(), i)); } for (;i <= nLocals + stackHandler.getTop().getValue();i++) { newStackHandler.push(stackCTX, slots[i], stackHandler.isRefLocal(FeatureExprFactory.True(), i)); } stackHandler = newStackHandler; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final HybridStackHandler other = (HybridStackHandler) obj; if (stackHandler == null) { if (other.stackHandler != null) return false; } else if (!stackHandler.equals(other.stackHandler)) return false; return true; } @Override public String toString() { return stackHandler.toString(); } }