You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ko...@apache.org on 2005/12/28 21:26:00 UTC

svn commit: r359623 - /jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/bcel/analyser/Subroutines.java

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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org