📄 controlflowgraph.java
字号:
/** * Does the actual merging (vmspec2, page 146). * Returns true IFF this.inFrame was changed in course of merging with inFrame. */ private boolean mergeInFrames(Frame inFrame){ // TODO: Can be performance-improved. Frame inF = (Frame) inFrames.get(lastExecutionJSR()); OperandStack oldstack = inF.getStack().getClone(); LocalVariables oldlocals = inF.getLocals().getClone(); try{ inF.getStack().merge(inFrame.getStack()); inF.getLocals().merge(inFrame.getLocals()); } catch (StructuralCodeConstraintException sce){ extendMessageWithFlow(sce); throw sce; } if ( oldstack.equals(inF.getStack()) && oldlocals.equals(inF.getLocals()) ){ return false; } else{ return true; } } /** * Returns the control flow execution chain. This is built * while execute(Frame, ArrayList)-ing the code represented * by the surrounding ControlFlowGraph. */ private String getExecutionChain(){ String s = this.toString(); for (int i=executionPredecessors.size()-1; i>=0; i--){ s = executionPredecessors.get(i)+"\n" + s; } return s; } /** * Extends the StructuralCodeConstraintException ("e") object with an at-the-end-extended message. * This extended message will then reflect the execution flow needed to get to the constraint * violation that triggered the throwing of the "e" object. */ private void extendMessageWithFlow(StructuralCodeConstraintException e){ String s = "Execution flow:\n"; e.extendMessage("", s+getExecutionChain()); } /* * Fulfils the contract of InstructionContext.getInstruction(). */ public InstructionHandle getInstruction(){ return instruction; } /** * Returns the InstructionContextImpl with an JSR/JSR_W * that was last in the ExecutionChain, without * a corresponding RET, i.e. * we were called by this one. * Returns null if we were called from the top level. */ private InstructionContextImpl lastExecutionJSR(){ int size = executionPredecessors.size(); int retcount = 0; for (int i=size-1; i>=0; i--){ InstructionContextImpl current = (InstructionContextImpl) (executionPredecessors.get(i)); Instruction currentlast = current.getInstruction().getInstruction(); if (currentlast instanceof RET) retcount++; if (currentlast instanceof JsrInstruction){ retcount--; if (retcount == -1) return current; } } return null; } /* Satisfies InstructionContext.getSuccessors(). */ public InstructionContext[] getSuccessors(){ return contextsOf(_getSuccessors()); } /** * A utility method that calculates the successors of a given InstructionHandle * That means, a RET does have successors as defined here. * A JsrInstruction has its target as its successor * (opposed to its physical successor) as defined here. */// TODO: implement caching! private InstructionHandle[] _getSuccessors(){ final InstructionHandle[] empty = new InstructionHandle[0]; final InstructionHandle[] single = new InstructionHandle[1]; final InstructionHandle[] pair = new InstructionHandle[2]; Instruction inst = getInstruction().getInstruction(); if (inst instanceof RET){ Subroutine s = subroutines.subroutineOf(getInstruction()); if (s==null){ //return empty; // RET in dead code. "empty" would be the correct answer, but we know something about the surrounding project... throw new AssertionViolatedException("Asking for successors of a RET in dead code?!"); }//TODO: removethrow new AssertionViolatedException("DID YOU REALLY WANT TO ASK FOR RET'S SUCCS?");/* InstructionHandle[] jsrs = s.getEnteringJsrInstructions(); InstructionHandle[] ret = new InstructionHandle[jsrs.length]; for (int i=0; i<jsrs.length; i++){ ret[i] = jsrs[i].getNext(); } return ret;*/ } // Terminates method normally. if (inst instanceof ReturnInstruction){ return empty; } // Terminates method abnormally, because JustIce mandates // subroutines not to be protected by exception handlers. if (inst instanceof ATHROW){ return empty; } // See method comment. if (inst instanceof JsrInstruction){ single[0] = ((JsrInstruction) inst).getTarget(); return single; } if (inst instanceof GotoInstruction){ single[0] = ((GotoInstruction) inst).getTarget(); return single; } if (inst instanceof BranchInstruction){ if (inst instanceof Select){ // BCEL's getTargets() returns only the non-default targets, // thanks to Eli Tilevich for reporting. InstructionHandle[] matchTargets = ((Select) inst).getTargets(); InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1]; ret[0] = ((Select) inst).getTarget(); System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length); return ret; } else{ pair[0] = getInstruction().getNext(); pair[1] = ((BranchInstruction) inst).getTarget(); return pair; } } // default case: Fall through. single[0] = getInstruction().getNext(); return single; } } // End Inner InstructionContextImpl Class. /** The MethofGen object we're working on. */ private final MethodGen method_gen; /** The Subroutines object for the method whose control flow is represented by this ControlFlowGraph. */ private final Subroutines subroutines; /** The ExceptionHandlers object for the method whose control flow is represented by this ControlFlowGraph. */ private final ExceptionHandlers exceptionhandlers; /** All InstructionContext instances of this ControlFlowGraph. */ private Hashtable instructionContexts = new Hashtable(); //keys: InstructionHandle, values: InstructionContextImpl /** * A Control Flow Graph. */ public ControlFlowGraph(MethodGen method_gen){ subroutines = new Subroutines(method_gen); exceptionhandlers = new ExceptionHandlers(method_gen); InstructionHandle[] instructionhandles = method_gen.getInstructionList().getInstructionHandles(); for (int i=0; i<instructionhandles.length; i++){ instructionContexts.put(instructionhandles[i], new InstructionContextImpl(instructionhandles[i])); } this.method_gen = method_gen; } /** * Returns the InstructionContext of a given instruction. */ public InstructionContext contextOf(InstructionHandle inst){ InstructionContext ic = (InstructionContext) instructionContexts.get(inst); if (ic == null){ throw new AssertionViolatedException("InstructionContext requested for an InstructionHandle that's not known!"); } return ic; } /** * Returns the InstructionContext[] of a given InstructionHandle[], * in a naturally ordered manner. */ public InstructionContext[] contextsOf(InstructionHandle[] insts){ InstructionContext[] ret = new InstructionContext[insts.length]; for (int i=0; i<insts.length; i++){ ret[i] = contextOf(insts[i]); } return ret; } /** * Returns an InstructionContext[] with all the InstructionContext instances * for the method whose control flow is represented by this ControlFlowGraph * <B>(NOT ORDERED!)</B>. */ public InstructionContext[] getInstructionContexts(){ InstructionContext[] ret = new InstructionContext[instructionContexts.values().size()]; return (InstructionContext[]) instructionContexts.values().toArray(ret); } /** * Returns true, if and only if the said instruction is not reachable; that means, * if it not part of this ControlFlowGraph. */ public boolean isDead(InstructionHandle i){ return instructionContexts.containsKey(i); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -