📄 abstractframemodelingvisitor.java
字号:
/* * Bytecode Analysis Framework * Copyright (C) 2003,2004 University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package edu.umd.cs.findbugs.ba;import org.apache.bcel.Constants;import org.apache.bcel.generic.*;/** * A common base class for frame modeling visitors. * This class provides a default implementation which copies values * between frame slots whenever appropriate. For example, its handler * for the ALOAD bytecode will get the value from the referenced * local in the frame and push it onto the stack. Bytecodes which * do something other than copying values are modeled by popping * values as appropriate, and pushing the "default" value onto the stack * for each stack slot produced, where the default value is the one * returned by the getDefaultValue() method. * <p/> * <p> Subclasses should override the visit methods for any bytecode instructions * which require special handling. * * @author David Hovemeyer * @see Frame * @see DataflowAnalysis */public abstract class AbstractFrameModelingVisitor <Value, FrameType extends Frame<Value>> implements Visitor { private FrameType frame; private ConstantPoolGen cpg; /** * Constructor. * * @param cpg the ConstantPoolGen of the method to be analyzed */ public AbstractFrameModelingVisitor(ConstantPoolGen cpg) { this.frame = null; this.cpg = cpg; } /** * Get the ConstantPoolGen for the method. */ public ConstantPoolGen getCPG() { return cpg; } /** * Set the frame. * * @param frame the Frame object */ public void setFrame(FrameType frame) { this.frame = frame; } /** * Get the frame. * * @return the Frame object */ public FrameType getFrame() { return frame; } /** * Produce a "default" value. * This is what is pushed onto the stack by the * handleNormalInstruction() method for instructions which produce stack values. */ public abstract Value getDefaultValue(); /** * 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 IllegalStateException(); return numWordsConsumed; } /** * Get the number of words produced by given instruction. */ public int getNumWordsProduced(Instruction ins) { int numWordsProduced = ins.produceStack(cpg); if (numWordsProduced == Constants.UNPREDICTABLE) throw new IllegalStateException(); return numWordsProduced; } /** * This is called for illegal bytecodes. * * @throws IllegalStateException */ private void illegalBytecode(Instruction ins) { throw new IllegalStateException("Illegal bytecode: " + ins); } /* ---------------------------------------------------------------------- * Empty visit methods * ---------------------------------------------------------------------- */ public void visitStackInstruction(StackInstruction obj) { } public void visitLocalVariableInstruction(LocalVariableInstruction obj) { } public void visitBranchInstruction(BranchInstruction obj) { } public void visitLoadClass(LoadClass obj) { } public void visitFieldInstruction(FieldInstruction obj) { } public void visitIfInstruction(IfInstruction obj) { } public void visitConversionInstruction(ConversionInstruction obj) { } public void visitPopInstruction(PopInstruction obj) { } public void visitJsrInstruction(JsrInstruction obj) { } public void visitGotoInstruction(GotoInstruction obj) { } public void visitStoreInstruction(StoreInstruction obj) { } public void visitTypedInstruction(TypedInstruction obj) { } public void visitSelect(Select obj) { } public void visitUnconditionalBranch(UnconditionalBranch obj) { } public void visitPushInstruction(PushInstruction obj) { } public void visitArithmeticInstruction(ArithmeticInstruction obj) { } public void visitCPInstruction(CPInstruction obj) { } public void visitInvokeInstruction(InvokeInstruction obj) { } public void visitArrayInstruction(ArrayInstruction obj) { } public void visitAllocationInstruction(AllocationInstruction obj) { } public void visitReturnInstruction(ReturnInstruction obj) { } public void visitFieldOrMethod(FieldOrMethod obj) { } public void visitConstantPushInstruction(ConstantPushInstruction obj) { } public void visitExceptionThrower(ExceptionThrower obj) { } public void visitLoadInstruction(LoadInstruction obj) { } public void visitVariableLengthInstruction(VariableLengthInstruction obj) { } public void visitStackProducer(StackProducer obj) { } public void visitStackConsumer(StackConsumer obj) { } /* ---------------------------------------------------------------------- * General instruction handlers * ---------------------------------------------------------------------- */ /** * Handler for all instructions which pop values from the stack * and store them in a local variable. Note that two locals * are stored into for long and double stores. */ public void handleStoreInstruction(StoreInstruction obj) { try { int numConsumed = obj.consumeStack(cpg); if (numConsumed == Constants.UNPREDICTABLE) throw new IllegalStateException(); int index = obj.getIndex(); // Store values into consecutive locals corresponding // to the order in which the values appeared on the stack. while (numConsumed-- > 0) { Value value = frame.popValue(); frame.setValue(index++, value); } } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } /** * Handler for all instructions which load values from a local variable * and push them on the stack. Note that two locals are loaded for * long and double loads. */ public void handleLoadInstruction(LoadInstruction obj) { int numProduced = obj.produceStack(cpg); if (numProduced == Constants.UNPREDICTABLE) throw new IllegalStateException(); int index = obj.getIndex() + numProduced; // Load values from locals in reverse order. // This restores them to the stack in a way consistent // with visitStoreInstruction(). while (numProduced-- > 0) { Value value = frame.getValue(--index); frame.pushValue(value); } } /** * This is called to handle any instruction which does not simply * copy values between stack slots. */ public void handleNormalInstruction(Instruction ins) { modelNormalInstruction(ins, getNumWordsConsumed(ins), getNumWordsProduced(ins)); } /** * Model the stack for instructions handled by handleNormalInstruction(). * Subclasses may override to provide analysis-specific behavior. */ public void modelNormalInstruction(Instruction ins, int numWordsConsumed, int numWordsProduced) { try { while (numWordsConsumed-- > 0) frame.popValue(); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } while (numWordsProduced-- > 0) frame.pushValue(getDefaultValue()); } /* ---------------------------------------------------------------------- * Visit methods for scalar STORE instructions * ---------------------------------------------------------------------- */ public void visitASTORE(ASTORE obj) { handleStoreInstruction(obj); } public void visitDSTORE(DSTORE obj) { handleStoreInstruction(obj); } public void visitFSTORE(FSTORE obj) { handleStoreInstruction(obj); } public void visitISTORE(ISTORE obj) { handleStoreInstruction(obj); } public void visitLSTORE(LSTORE obj) { handleStoreInstruction(obj); } /* ---------------------------------------------------------------------- * Visit methods for scalar LOAD instructions * ---------------------------------------------------------------------- */ public void visitALOAD(ALOAD obj) { handleLoadInstruction(obj); } public void visitDLOAD(DLOAD obj) { handleLoadInstruction(obj); } public void visitFLOAD(FLOAD obj) { handleLoadInstruction(obj); } public void visitILOAD(ILOAD obj) { handleLoadInstruction(obj); } public void visitLLOAD(LLOAD obj) { handleLoadInstruction(obj); } /* ---------------------------------------------------------------------- * Visit methods for POP, DUP, and SWAP instructions * ---------------------------------------------------------------------- */ public void visitPOP(POP obj) { handleNormalInstruction(obj); } public void visitPOP2(POP2 obj) { handleNormalInstruction(obj); } public void visitDUP(DUP obj) { try { Value value = frame.popValue(); frame.pushValue(value); frame.pushValue(value); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } public void visitDUP_X1(DUP_X1 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); frame.pushValue(value1); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } public void visitDUP_X2(DUP_X2 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); Value value3 = frame.popValue(); frame.pushValue(value1); frame.pushValue(value3); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } public void visitDUP2(DUP2 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); frame.pushValue(value2); frame.pushValue(value1); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } public void visitDUP2_X1(DUP2_X1 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); Value value3 = frame.popValue(); frame.pushValue(value2); frame.pushValue(value1); frame.pushValue(value3); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } public void visitDUP2_X2(DUP2_X2 obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); Value value3 = frame.popValue(); Value value4 = frame.popValue(); frame.pushValue(value2); frame.pushValue(value1); frame.pushValue(value4); frame.pushValue(value3); frame.pushValue(value2); frame.pushValue(value1); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } public void visitSWAP(SWAP obj) { try { Value value1 = frame.popValue(); Value value2 = frame.popValue(); frame.pushValue(value1); frame.pushValue(value2); } catch (DataflowAnalysisException e) { throw new IllegalStateException(e.toString()); } } /* ---------------------------------------------------------------------- * Illegal bytecodes * ---------------------------------------------------------------------- */ public void visitIMPDEP1(IMPDEP1 obj) { illegalBytecode(obj); } public void visitIMPDEP2(IMPDEP2 obj) { illegalBytecode(obj); } public void visitBREAKPOINT(BREAKPOINT obj) { illegalBytecode(obj); } /* ---------------------------------------------------------------------- * Bytecodes that have "default" semantics * ---------------------------------------------------------------------- */ public void visitACONST_NULL(ACONST_NULL obj) { handleNormalInstruction(obj); } public void visitGETSTATIC(GETSTATIC obj) { handleNormalInstruction(obj); } public void visitIF_ICMPLT(IF_ICMPLT obj) { handleNormalInstruction(obj); } public void visitMONITOREXIT(MONITOREXIT obj) { handleNormalInstruction(obj); } public void visitIFLT(IFLT obj) { handleNormalInstruction(obj); } public void visitBASTORE(BASTORE obj) { handleNormalInstruction(obj); } public void visitCHECKCAST(CHECKCAST obj) { handleNormalInstruction(obj); } public void visitFCMPG(FCMPG obj) { handleNormalInstruction(obj); } public void visitI2F(I2F obj) { handleNormalInstruction(obj); } public void visitATHROW(ATHROW obj) { handleNormalInstruction(obj); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -