Author: kohsuke Date: Wed Dec 28 12:25:59 2005 New Revision: 359623 URL: http://svn.apache.org/viewcvs?rev=359623&view=rev Log: fixed an instrumentation bug where an exception handler is used inside a finally block.
Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Subroutines.java Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Subroutines.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Subroutines.java?rev=359623&r1=359622&r2=359623&view=diff ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Subroutines.java (original) +++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Subroutines.java Wed Dec 28 12:25:59 2005 @@ -52,11 +52,6 @@ * of a JSR of JSR_W instruction and ends at a corresponding RET * instruction. Note also that the control flow of a subroutine * may be complex and non-linear; and that subroutines may be nested. - * JustIce also mandates subroutines not to be protected by exception - * handling code (for the sake of control flow predictability). - * To understand JustIce's notion of subroutines, please read - * - * TODO: refer to the paper. * * WARNING! These classes are a fork of the bcel verifier. * @@ -403,31 +398,42 @@ // set of InstructionHandles reachable from the top Set closure = new HashSet(); - // Do a BFS with "actual" as the root of the graph. - InstructionHandle actual = (InstructionHandle) (iter.next()); - // Init Queue + // Init Queue. Start with the entry point of closure. + InstructionHandle leader = (InstructionHandle) (iter.next()); ArrayList Q = new ArrayList(); - Q.add(actual); - - /* DFS ALGORITHM MODIFICATION: Start out with multiple "root" nodes, as exception handlers are starting points of top-level code, too. [why top-level? TODO: Refer to the special JustIce notion of subroutines.]*/ - if (actual == all[0]){ - for (int j=0; j<handlers.length; j++){ - Q.add(handlers[j].getHandlerPC()); - } - } - /* CONTINUE NORMAL BFS ALGORITHM */ + Q.add(leader); - while (!Q.isEmpty()){ - InstructionHandle u = (InstructionHandle) Q.remove(Q.size()-1); - if(closure.add(u)) { - InstructionHandle[] successors = getSuccessors(u); - for (int i=0; i<successors.length; i++){ - Q.add(successors[i]); + while (!Q.isEmpty()){ + while (!Q.isEmpty()){ + InstructionHandle u = (InstructionHandle) Q.remove(Q.size()-1); + if(closure.add(u)) { + InstructionHandle[] successors = getSuccessors(u); + for (int i=0; i<successors.length; i++){ + Q.add(successors[i]); + } + } + } + // check if exception handlers are reachable from the closure computed thus far. + // conceptually, an exception handler is a successor of each instruction inside + // the protected region, but the computation works faster if we don't implement it + // in a straight-forward way. Instead, we occasionally check if the first instruction + // of the protected region is in the closure, and if so, we know that the exception + // handler should also be in the closure. + // + // "one instruction must be always in at-most one subroutine" JVM requirement + // guarantees that the entire protected region always belongs to the same closure, + // so just checking the start instruction is suffice. + for( int i=0; i<handlers.length; i++ ) { + if(closure.contains(handlers[i].getStartPC())) { + InstructionHandle handlerPC = handlers[i].getHandlerPC(); + if(!closure.contains(handlerPC)) { + Q.add(handlerPC); + } } } } - // DFS ended above. - ((SubroutineImpl) (actual==all[0]?getTopLevel():getSubroutine(actual))).setInstructions(closure); + // DFS ended above. + ((SubroutineImpl) (leader==all[0]?getTopLevel():getSubroutine(leader))).setInstructions(closure); for (Iterator itr = closure.iterator(); itr.hasNext();) { InstructionHandle h = (InstructionHandle) itr.next(); @@ -436,29 +442,11 @@ } } - if (actual != all[0]){// If we don't deal with the top-level 'subroutine' - ((SubroutineImpl) getSubroutine(actual)).setLeavingRET(); + if (leader != all[0]){// If we don't deal with the top-level 'subroutine' + ((SubroutineImpl) getSubroutine(leader)).setLeavingRET(); } } - // Now make sure no instruction of a Subroutine is protected by exception handling code - // as is mandated by JustIces notion of subroutines. - /*for (int i=0; i<handlers.length; i++){ - InstructionHandle _protected = handlers[i].getStartPC(); - while (_protected != handlers[i].getEndPC().getNext()){// Note the inclusive/inclusive notation of "generic API" exception handlers! - Enumeration subs = subroutines.elements(); - while (subs.hasMoreElements()){ - Subroutine sub = (Subroutine) subs.nextElement(); - if (sub != subroutines.get(all[0])){ // We don't want to forbid top-level exception handlers. - if (sub.contains(_protected)){ - throw new StructuralCodeConstraintException("Subroutine instruction '"+_protected+"' is protected by an exception handler, '"+handlers[i]+"'. This is forbidden by the JustIce verifier due to its clear definition of subroutines."); - } - } - } - _protected = _protected.getNext(); - } - }*/ - // Now make sure no subroutine is calling a subroutine // that uses the same local variable for the RET as themselves // (recursively). @@ -567,7 +555,7 @@ private static InstructionHandle[] getSuccessors(InstructionHandle instruction){ Instruction inst = instruction.getInstruction(); - if (inst instanceof RET){ + if (inst instanceof RET){ return empty; } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]