/** * Get the number of words consumed by given instruction. */ public int getNumWordsConsumed(Instruction ins) { int numWordsConsumed = ins.consumeStack(cpg); if (numWordsConsumed == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption"); } return numWordsConsumed; }
/** * Get the stack location (counting down from top of stack, starting at 0) * containing the object instance referred to by given instruction. This * relies on the observation that in instructions which use an object * instance (such as getfield, invokevirtual, etc.), the object instance is * the first operand used by the instruction. * * <p> * The value returned may be passed to getStackValue(int). * </p> * * @param ins * the Instruction * @param cpg * the ConstantPoolGen for the method * @return stack location (counting down from top of stack, starting at 0) * containing the object instance * @throws DataflowAnalysisException */ public int getInstanceStackLocation(Instruction ins, ConstantPoolGen cpg) throws DataflowAnalysisException { int numConsumed = ins.consumeStack(cpg); if (numConsumed == Const.UNPREDICTABLE) { throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins); } return numConsumed - 1; }
private void checkConsumedAndProducedValues(Instruction ins, ValueNumber[] consumedValueList, ValueNumber[] producedValueList) { int numConsumed = ins.consumeStack(getCPG()); int numProduced = ins.produceStack(getCPG()); if (numConsumed == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins); } if (numProduced == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack production for " + ins); } if (consumedValueList.length != numConsumed) { throw new IllegalStateException("Wrong number of values consumed for " + ins + ": expected " + numConsumed + ", got " + consumedValueList.length); } if (producedValueList.length != numProduced) { throw new IllegalStateException("Wrong number of values produced for " + ins + ": expected " + numProduced + ", got " + producedValueList.length); } }
@Override public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, StackDepth fact) throws DataflowAnalysisException { Instruction ins = handle.getInstruction(); int produced = ins.produceStack(cpg); int consumed = ins.consumeStack(cpg); if (produced == Const.UNPREDICTABLE || consumed == Const.UNPREDICTABLE) { throw new IllegalStateException("Unpredictable stack delta for instruction: " + handle); } int depth = fact.getDepth(); depth += (produced - consumed); if (depth < 0) { fact.setDepth(BOTTOM); } else { fact.setDepth(depth); } }
/** * Get the slot the object instance referred to by given instruction is * located in. * * @param ins * the Instruction * @param cpg * the ConstantPoolGen for the method * @return stack slot the object instance is in * @throws DataflowAnalysisException */ public int getInstanceSlot(Instruction ins, ConstantPoolGen cpg) throws DataflowAnalysisException { if (!isValid()) { throw new DataflowAnalysisException("Accessing invalid frame at " + ins); } int numConsumed = ins.consumeStack(cpg); if (numConsumed == Const.UNPREDICTABLE) { throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins); } if (numConsumed > getStackDepth()) { throw new DataflowAnalysisException("Stack underflow " + ins); } return getNumSlots() - numConsumed; }
/** * @param methodGen method * @param start instruction to scan * @return instruction which consumes value which was on top of stack before start instruction * or null if cannot be determined */ private InstructionHandle getConsumer(MethodGen methodGen, InstructionHandle start) { int depth = 1; InstructionHandle cur = start; while(cur != null) { Instruction inst = cur.getInstruction(); depth -= inst.consumeStack(methodGen.getConstantPool()); if(depth <= 0) { return cur; } depth += inst.produceStack(methodGen.getConstantPool()); if(inst instanceof BranchInstruction) { if(inst instanceof GotoInstruction) { cur = ((GotoInstruction)inst).getTarget(); continue; } if(!(inst instanceof IfInstruction)) { return null; } } cur = cur.getNext(); } return null; }
int depth = ins.consumeStack(cpg); for(InstructionHandle prev = handle.getPrev(); prev != null; prev = prev.getPrev()) { Instruction prevInst = prev.getInstruction(); depth = ins.consumeStack(cpg); } else { return true; depth = depth - prevInst.produceStack(cpg) + prevInst.consumeStack(cpg); if(depth < 1) { throw new CFGBuilderException("Invalid stack at "+prev+" when checking "+handle);
int numConsumed = ins.consumeStack(cpg); MethodGen methodGen = classContext.getMethodGen(method); assert methodGen != null;
/** * Consume stack. This is a convenience method for instructions where the * types of popped operands can be ignored. */ protected void consumeStack(Instruction ins) { ConstantPoolGen cpg = getCPG(); TypeFrame frame = getFrame(); int numWordsConsumed = ins.consumeStack(cpg); if (numWordsConsumed == Const.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins); } if (numWordsConsumed > frame.getStackDepth()) { throw new InvalidBytecodeException("Stack underflow for " + ins + ", " + numWordsConsumed + " needed, " + frame.getStackDepth() + " avail, frame is " + frame); } try { while (numWordsConsumed-- > 0) { frame.popValue(); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Stack underflow for " + ins + ": " + e.getMessage()); } }
if (ins instanceof IfInstruction && ins.consumeStack(cpg) == 2) { isTest = true; } else if (ins instanceof InvokeInstruction && ins.consumeStack(cpg) == 2) { InvokeInstruction invoke = (InvokeInstruction) ins; isTest = "equals".equals(invoke.getMethodName(cpg)) &&"(Ljava/lang/Object;)Z".equals(invoke.getSignature(cpg)) ;
int nconsumed = inst.consumeStack(context.cpg); if(nconsumed > 0) { ValueNumber[] vns = new ValueNumber[nconsumed];
/** * Get the number of words consumed by given instruction. */ public int getNumWordsConsumed(Instruction ins) { int numWordsConsumed = ins.consumeStack(cpg); if (numWordsConsumed == Constants.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption"); } return numWordsConsumed; }
/** * Get the stack location (counting down from top of stack, starting at 0) * containing the object instance referred to by given instruction. This * relies on the observation that in instructions which use an object * instance (such as getfield, invokevirtual, etc.), the object instance is * the first operand used by the instruction. * * <p> * The value returned may be passed to getStackValue(int). * </p> * * @param ins * the Instruction * @param cpg * the ConstantPoolGen for the method * @return stack location (counting down from top of stack, starting at 0) * containing the object instance * @throws DataflowAnalysisException */ public int getInstanceStackLocation(Instruction ins, ConstantPoolGen cpg) throws DataflowAnalysisException { int numConsumed = ins.consumeStack(cpg); if (numConsumed == Constants.UNPREDICTABLE) { throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins); } return numConsumed - 1; }
private void checkConsumedAndProducedValues(Instruction ins, ValueNumber[] consumedValueList, ValueNumber[] producedValueList) { int numConsumed = ins.consumeStack(getCPG()); int numProduced = ins.produceStack(getCPG()); if (numConsumed == Constants.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins); } if (numProduced == Constants.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack production for " + ins); } if (consumedValueList.length != numConsumed) { throw new IllegalStateException("Wrong number of values consumed for " + ins + ": expected " + numConsumed + ", got " + consumedValueList.length); } if (producedValueList.length != numProduced) { throw new IllegalStateException("Wrong number of values produced for " + ins + ": expected " + numProduced + ", got " + producedValueList.length); } }
@Override public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, StackDepth fact) throws DataflowAnalysisException { Instruction ins = handle.getInstruction(); int produced = ins.produceStack(cpg); int consumed = ins.consumeStack(cpg); if (produced == Constants.UNPREDICTABLE || consumed == Constants.UNPREDICTABLE) { throw new IllegalStateException("Unpredictable stack delta for instruction: " + handle); } int depth = fact.getDepth(); depth += (produced - consumed); if (depth < 0) { fact.setDepth(BOTTOM); } else { fact.setDepth(depth); } }
/** * Get the slot the object instance referred to by given instruction is * located in. * * @param ins * the Instruction * @param cpg * the ConstantPoolGen for the method * @return stack slot the object instance is in * @throws DataflowAnalysisException */ public int getInstanceSlot(Instruction ins, ConstantPoolGen cpg) throws DataflowAnalysisException { if (!isValid()) { throw new DataflowAnalysisException("Accessing invalid frame at " + ins); } int numConsumed = ins.consumeStack(cpg); if (numConsumed == Constants.UNPREDICTABLE) { throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins); } if (numConsumed > getStackDepth()) { throw new DataflowAnalysisException("Stack underflow " + ins); } return getNumSlots() - numConsumed; }
/** * @param methodGen method * @param start instruction to scan * @return instruction which consumes value which was on top of stack before start instruction * or null if cannot be determined */ private InstructionHandle getConsumer(MethodGen methodGen, InstructionHandle start) { int depth = 1; InstructionHandle cur = start; while(cur != null) { Instruction inst = cur.getInstruction(); depth -= inst.consumeStack(methodGen.getConstantPool()); if(depth <= 0) { return cur; } depth += inst.produceStack(methodGen.getConstantPool()); if(inst instanceof BranchInstruction) { if(inst instanceof GotoInstruction) { cur = ((GotoInstruction)inst).getTarget(); continue; } if(!(inst instanceof IfInstruction)) { return null; } } cur = cur.getNext(); } return null; }
/** * Consume stack. This is a convenience method for instructions where the * types of popped operands can be ignored. */ protected void consumeStack(Instruction ins) { ConstantPoolGen cpg = getCPG(); TypeFrame frame = getFrame(); int numWordsConsumed = ins.consumeStack(cpg); if (numWordsConsumed == Constants.UNPREDICTABLE) { throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins); } if (numWordsConsumed > frame.getStackDepth()) { throw new InvalidBytecodeException("Stack underflow for " + ins + ", " + numWordsConsumed + " needed, " + frame.getStackDepth() + " avail, frame is " + frame); } try { while (numWordsConsumed-- > 0) { frame.popValue(); } } catch (DataflowAnalysisException e) { throw new InvalidBytecodeException("Stack underflow for " + ins + ": " + e.getMessage()); } }
/** * Ensures the general preconditions of an instruction that accesses the stack. * This method is here because BCEL has no such superinterface for the stack * accessing instructions; and there are funny unexpected exceptions in the * semantices of the superinterfaces and superclasses provided. * E.g. SWAP is a StackConsumer, but DUP_X1 is not a StackProducer. * Therefore, this method is called by all StackProducer, StackConsumer, * and StackInstruction instances via their visitXXX() method. * Unfortunately, as the superclasses and superinterfaces overlap, some instructions * cause this method to be called two or three times. [TODO: Fix this.] * * @see #visitStackConsumer(StackConsumer o) * @see #visitStackProducer(StackProducer o) * @see #visitStackInstruction(StackInstruction o) */ private void _visitStackAccessor(Instruction o){ int consume = o.consumeStack(cpg); // Stack values are always consumed first; then produced. if (consume > stack().slotsUsed()){ constraintViolated((Instruction) o, "Cannot consume "+consume+" stack slots: only "+stack().slotsUsed()+" slot(s) left on stack!\nStack:\n"+stack()); } int produce = o.produceStack(cpg) - ((Instruction) o).consumeStack(cpg); // Stack values are always consumed first; then produced. if ( produce + stack().slotsUsed() > stack().maxStack() ){ constraintViolated((Instruction) o, "Cannot produce "+produce+" stack slots: only "+(stack().maxStack()-stack().slotsUsed())+" free stack slot(s) left.\nStack:\n"+stack()); } }
/** * Ensures the general preconditions of an instruction that accesses the stack. * This method is here because BCEL has no such superinterface for the stack * accessing instructions; and there are funny unexpected exceptions in the * semantices of the superinterfaces and superclasses provided. * E.g. SWAP is a StackConsumer, but DUP_X1 is not a StackProducer. * Therefore, this method is called by all StackProducer, StackConsumer, * and StackInstruction instances via their visitXXX() method. * Unfortunately, as the superclasses and superinterfaces overlap, some instructions * cause this method to be called two or three times. [TODO: Fix this.] * * @see #visitStackConsumer(StackConsumer o) * @see #visitStackProducer(StackProducer o) * @see #visitStackInstruction(StackInstruction o) */ private void _visitStackAccessor(final Instruction o) { final int consume = o.consumeStack(cpg); // Stack values are always consumed first; then produced. if (consume > stack().slotsUsed()) { constraintViolated(o, "Cannot consume "+consume+" stack slots: only "+stack().slotsUsed()+" slot(s) left on stack!\nStack:\n"+stack()); } final int produce = o.produceStack(cpg) - o.consumeStack(cpg); // Stack values are always consumed first; then produced. if ( produce + stack().slotsUsed() > stack().maxStack() ) { constraintViolated(o, "Cannot produce "+produce+" stack slots: only "+(stack().maxStack()-stack().slotsUsed())+ " free stack slot(s) left.\nStack:\n"+stack()); } }