private boolean isPEI ( InstructionHandle handle ) throws CFGBuilderException { Instruction ins = handle . getInstruction ( ) ; if ( ! ( ins instanceof ExceptionThrower ) ) { return false ; } if ( ins instanceof NEW ) { return false ; } // if (ins instanceof ATHROW) return false; if ( ins instanceof GETSTATIC ) { return false ; } if ( ins instanceof PUTSTATIC ) { return false ; } if ( ins instanceof ReturnInstruction ) { return false ; } if ( ins instanceof INSTANCEOF ) { return false ; } if ( ins instanceof MONITOREXIT ) { return false ; } if ( ins instanceof LDC ) { return false ; } if ( ins instanceof GETFIELD && ! methodGen . isStatic ( ) ) { // Assume that GETFIELD on this object is not PEI return ! isSafeFieldSource ( handle . getPrev ( ) ) ; } if ( ins instanceof PUTFIELD && ! methodGen . isStatic ( ) ) { // Assume that PUTFIELD on this object is not PEI int depth = ins . consumeStack ( cpg ) ; for ( InstructionHandle prev = handle . getPrev ( ) ; prev != null ; prev = prev . getPrev ( ) ) { Instruction prevInst = prev . getInstruction ( ) ; if ( prevInst instanceof BranchInstruction ) { if ( prevInst instanceof GotoInstruction ) { // Currently we support only jumps to the PUTFIELD itself // This will cover simple cases like this.a = flag ? foo : bar if ( ( ( BranchInstruction ) prevInst ) . getTarget ( ) == handle ) { depth = ins . consumeStack ( cpg ) ; } else { return true ; } } else if ( ! ( prevInst instanceof IfInstruction ) ) { // As IF instructions may fall through then the stack depth remains unchanged // Actually we should not go here for normal Java bytecode: switch or jsr should not appear in this context return true ; } } depth = depth - prevInst . produceStack ( cpg ) + prevInst . consumeStack ( cpg ) ; if ( depth < 1 ) { throw new CFGBuilderException ( "Invalid stack at " + prev + " when checking " + handle ) ; } if ( depth == 1 ) { InstructionHandle prevPrev = prev . getPrev ( ) ; if ( prevPrev != null && prevPrev . getInstruction ( ) instanceof BranchInstruction ) { continue ; } return ! isSafeFieldSource ( prevPrev ) ; } } } return true ; }
Return whether or not the given instruction can throw exceptions .