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]

Reply via email to