You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Denis Benoit <De...@fbn.ca> on 2002/05/21 15:36:42 UTC

[PATCH] Stack based "finallies" in Generator.java

Hi Kin-Man,

Here is the patch as promised.

. It follows what we agreed about the "two arrays" simulating stacks;
. It prevents generating any extra code if there is no Tags in the JSP,
  now this case is easy to determine thanks to pageInfo.getMaxTagNesting :)

This is a first draft, I'll continue testing it, if you see something you
don't like just give tell me so, and I'll correct it.

Thanks!

Index: jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java
===================================================================
RCS file: /home/cvspublic/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java,v
retrieving revision 1.14
diff -c -r1.14 Generator.java
*** jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java	15 May 2002 20:42:03 -0000	1.14
--- jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java	21 May 2002 01:08:45 -0000
***************
*** 94,102 ****
      private JspCompilationContext ctxt;
      private boolean breakAtLF;
      private PageInfo pageInfo;
!     private FinallyApplyer finallies;
!     private int tryBit;
!     private Stack tryStack;
  
      /**
       * @param s the input string
--- 94,101 ----
      private JspCompilationContext ctxt;
      private boolean breakAtLF;
      private PageInfo pageInfo;
!     private int maxTagNesting;
! 
  
      /**
       * @param s the input string
***************
*** 226,231 ****
--- 225,256 ----
              out.println();  
              out.println();
          }
+         
+     	maxTagNesting = pageInfo.getMaxTagNesting();
+         if (maxTagNesting >= 0) {
+        		out.printil("private static final int RELEASE_ACTION = 0;");
+     		out.printil("private static final int POP_AND_RELEASE_ACTION = 1;");
+ 	    	out.println();
+ 	    	out.println();
+         }
+ 
+     
+     // Class fields declarations
+     
+     	// pseudo "Finally" state stack objects
+     	
+     	if (maxTagNesting >= 0) {
+     		String depth = Integer.toString(maxTagNesting + 1);
+ 	    	out.printil("int   finallyStackIndex = -1;");
+ 	    	out.printin("int[] finallyStackActions = new int[");
+ 	    	out.print(depth);
+ 	    	out.println("];");
+ 	    	out.printin("javax.servlet.jsp.tagext.Tag[] finallyStackTags = new javax.servlet.jsp.tagext.Tag[");
+ 	    	out.print(depth);
+ 	    	out.println("];");
+ 	    	out.println();
+ 	    	out.println();
+     	}
  
  	// Constructor (empty so far) here
  
***************
*** 238,255 ****
          out.println();
          out.println();
  
-         out.printil("private void addTagToVector(java.util.Vector tags, int index, Object tag) {");
-         out.pushIndent();
-         out.printil("if (index + 1 > tags.size())");
-         out.pushIndent();
-         out.printil("tags.setSize(index + 1);");
-         out.popIndent();
-         out.printil("tags.setElementAt(tag, index);");
-         out.popIndent();
-         out.printil("}");
-         out.println();
-         out.println();
- 
  	// Now the service method
  	out.printin("public void ");
  	out.print  (serviceMethodName);
--- 263,268 ----
***************
*** 977,998 ****
  	    declareTagVariableInfos(tagVarInfos, n.getTagData(),
  				    VariableInfo.AT_BEGIN);
  	    
!             if (implementsTryCatchFinally) {
!                 out.printil("try {");
!                 out.pushIndent();
!             } else {
!                 out.printil("// try {");
!                 out.printin("bitmask.set(");
!                 Integer tryBitVal = new Integer(tryBit++);
!                 tryStack.push(tryBitVal);
!                 out.print(tryBitVal.toString());
!                 out.println(");");
!                 out.printin("addTagToVector(tags, ");
!                 out.print(tryBitVal.toString());
!                 out.print(", ");
!                 out.print(tagHandlerVar);
!                 out.println(");");
!             }
  	    out.printin("int ");
  	    out.print(tagEvalVar);
  	    out.print(" = ");
--- 990,1006 ----
  	    declareTagVariableInfos(tagVarInfos, n.getTagData(),
  				    VariableInfo.AT_BEGIN);
  	    
!         if (implementsTryCatchFinally) {
!             out.printil("try {");
!             out.pushIndent();
!         } else {
!             out.printil("// try {");
!             out.printil("finallyStackActions[++finallyStackIndex] = RELEASE_ACTION;");
!             out.printin("finallyStackTags[finallyStackIndex] = ");
!             out.print(tagHandlerVar);
!             out.println(";");
!         }
!         
  	    out.printin("int ");
  	    out.print(tagEvalVar);
  	    out.print(" = ");
***************
*** 1008,1050 ****
  				   VariableInfo.AT_BEGIN, false);
  
  	    if (n.getBody() != null) {
- 		out.printin("if (");
- 		out.print(tagEvalVar);
- 		out.println(" != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {");
- 		out.pushIndent();
- 		
- 		if (isBodyTag) {
-                     out.printil("// try {");
-                     out.printin("bitmask.set(");
-                     Integer tryBitVal = new Integer(tryBit++);
-                     tryStack.push(tryBitVal);
-                     out.print(tryBitVal.toString());
-                     out.println(");");
-                     out.printin("addTagToVector(tags, ");
-                     out.print(tryBitVal.toString());
-                     out.print(", new Integer(");
-                     out.print(tagEvalVar);
-                     out.println("));");
  		    out.printin("if (");
  		    out.print(tagEvalVar);
! 		    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {");
! 		    // Assume EVAL_BODY_BUFFERED
  		    out.pushIndent();
  		    
! 		    out.printil("out = pageContext.pushBody();");
! 		    out.printin(tagHandlerVar);
! 		    out.println(".setBodyContent((javax.servlet.jsp.tagext.BodyContent) out);");
! 		    out.printin(tagHandlerVar);
! 		    out.println(".doInitBody();");
  		    
! 		    out.popIndent();
! 		    out.printil("}");
! 		}
  		
! 		if (IterationTag.class.isAssignableFrom(tagHandlerClass)) {
! 		    out.printil("do {");
! 		    out.pushIndent();
! 		}
  	    }
  
  	    // Declare and update NESTED variables
--- 1016,1051 ----
  				   VariableInfo.AT_BEGIN, false);
  
  	    if (n.getBody() != null) {
  		    out.printin("if (");
  		    out.print(tagEvalVar);
! 		    out.println(" != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {");
  		    out.pushIndent();
+ 		
+ 		    if (isBodyTag) {
+                 out.printil("// try {");
+ 		        out.printin("if (");
+ 		        out.print(tagEvalVar);
+ 		        out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {");
+ 		        // Assume EVAL_BODY_BUFFERED
+ 		        out.pushIndent();
  		    
! 		        out.printil("out = pageContext.pushBody();");
! 		        if (!implementsTryCatchFinally) {
! 	                out.printil("finallyStackActions[finallyStackIndex] = POP_AND_RELEASE_ACTION;");
! 		        }
! 		        out.printin(tagHandlerVar);
! 		        out.println(".setBodyContent((javax.servlet.jsp.tagext.BodyContent) out);");
! 		        out.printin(tagHandlerVar);
! 		        out.println(".doInitBody();");
  		    
! 		        out.popIndent();
! 		        out.printil("}");
!     		}
  		
! 		    if (IterationTag.class.isAssignableFrom(tagHandlerClass)) {
! 		        out.printil("do {");
! 		        out.pushIndent();
!     		}
  	    }
  
  	    // Declare and update NESTED variables
***************
*** 1085,1118 ****
  				   VariableInfo.AT_BEGIN, false);
  
  	    if (n.getBody() != null) {
! 		if (implementsBodyTag) {
!                     Integer tryBitVal = (Integer)tryStack.pop();
!                     out.printil("// } finally {");
!                     out.printin("bitmask.clear(");
!                     out.print(tryBitVal.toString());
!                     out.println(");");
! 
! 		    out.printin("if (");
! 		    out.print(tagEvalVar);
! 		    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
! 		    out.pushIndent();
! 		    out.printil("out = pageContext.popBody();");
! 		    out.popIndent();
! 
!                     finallies.beginPartMethod(tryBitVal.intValue());
!                     finallies.print("      if (");
!                     finallies.print("((Integer)tags.elementAt(");
!                     finallies.print(tryBitVal.toString());
!                     finallies.print(")).intValue()");
!                     finallies.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
!                     finallies.println("        out = pageContext.popBody();");
! 
!                     finallies.endPartMethod();
!                     out.printil("// }");
! 		}
  
! 		out.popIndent(); // EVAL_BODY
! 		out.printil("}");
  	    }
  
  	    out.printin("if (");
--- 1086,1108 ----
  				   VariableInfo.AT_BEGIN, false);
  
  	    if (n.getBody() != null) {
! 		    if (implementsBodyTag) {
!                 out.printil("// } finally {");
! 		    	if (!implementsTryCatchFinally) {
! 	                out.printil("finallyStackActions[finallyStackIndex] = RELEASE_ACTION;");
! 		    	}
! 		        out.printin("if (");
!     		    out.print(tagEvalVar);
! 	    	    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
! 		        out.pushIndent();
! 		        out.printil("out = pageContext.popBody();");
!                 out.printil("");
! 	    	    out.popIndent();
!                 out.printil("// }");
!     		}
  
!     		out.popIndent(); // EVAL_BODY
! 	    	out.printil("}");
  	    }
  
  	    out.printin("if (");
***************
*** 1124,1158 ****
  
  	    // TryCatchFinally
  	    if (implementsTryCatchFinally) {
!                 out.popIndent(); // try
! 		out.printil("} catch (Throwable _jspx_exception) {");
! 		out.pushIndent();
! 		out.printin(tagHandlerVar);
! 		out.println(".doCatch(_jspx_exception);");
! 		out.popIndent();
!                 out.printil("} finally {");
!                 out.pushIndent();
! 		out.printin(tagHandlerVar);
! 		out.println(".doFinally();");
!                 out.printin(tagHandlerVar);
!                 out.println(".release();");
!                 out.popIndent();
!                 out.printil("}");
!             } else {
!                 Integer tryBitVal = (Integer)tryStack.pop();
!                 out.printil("// } finally {");
!                 out.printin("bitmask.clear(");
!                 out.print(tryBitVal.toString());
!                 out.println(");");
!                 out.printin(tagHandlerVar);
!                 out.println(".release();");
!                 out.printil("// }");
!                 finallies.beginPartMethod(tryBitVal.intValue());
!                 finallies.printin("((javax.servlet.jsp.tagext.Tag)tags.elementAt(");
!                 finallies.print(tryBitVal.toString());
!                 finallies.print("))");
!                 finallies.println(".release();");
!                 finallies.endPartMethod();
  	    }
  
  	    // Declare and update AT_END variables
--- 1114,1139 ----
  
  	    // TryCatchFinally
  	    if (implementsTryCatchFinally) {
!             out.popIndent(); // try
! 		    out.printil("} catch (Throwable _jspx_exception) {");
! 		    out.pushIndent();
! 		    out.printin(tagHandlerVar);
! 		    out.println(".doCatch(_jspx_exception);");
! 		    out.popIndent();
!             out.printil("} finally {");
!             out.pushIndent();
! 		    out.printin(tagHandlerVar);
! 		    out.println(".doFinally();");
!             out.printin(tagHandlerVar);
!             out.println(".release();");
!             out.popIndent();
!             out.printil("}");
!         } else {
!             out.printil("// } finally {");
!             out.printil("finallyStackIndex--;");
!             out.printin(tagHandlerVar);
!             out.println(".release();");
!             out.printil("// }");
  	    }
  
  	    // Declare and update AT_END variables
***************
*** 1419,1424 ****
--- 1400,1416 ----
          out.popIndent();
          out.printil("} catch (Throwable t) {");
          out.pushIndent();
+         if (maxTagNesting >= 0) {
+ 	        out.printil("while (finallyStackIndex >= 0) {");
+ 	        out.pushIndent();
+ 	        out.printil("if (POP_AND_RELEASE_ACTION == finallyStackActions[finallyStackIndex])");
+ 	        out.pushIndent();
+ 	        out.printil("out = pageContext.popBody();");
+ 	        out.popIndent();
+ 	        out.printil("finallyStackTags[finallyStackIndex--].release();");
+ 	        out.popIndent();
+ 	        out.printil("}");
+         }
          out.printil("if (out != null && out.getBufferSize() != 0)");
          out.pushIndent();
          out.printil("out.clearBuffer();");
***************
*** 1427,1446 ****
          out.popIndent();
          out.printil("} finally {");
          out.pushIndent();
- 
-         // Do stuff here for finally actions...
- 
-         out.printil("try {");
-         out.pushIndent();
-         out.printil("finallies(bitmask, out, tags, pageContext);");
-         out.popIndent();
-         out.printil("} catch (javax.servlet.jsp.JspException e) {");
-         out.pushIndent();
-         out.printil("if (pageContext != null) pageContext.handlePageException(e);");
-         out.popIndent();
-         out.printil("}");
          out.printil("if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);");
- 
          out.popIndent();
          out.printil("}");
  
--- 1419,1425 ----
***************
*** 1448,1457 ****
          out.popIndent();
          out.printil("}");
  
-         // Call the final method
-         finallies.done();
-         out.printil(finallies.toString());
- 
          // Close the class definition
          out.popIndent();
          out.printil("}");
--- 1427,1432 ----
***************
*** 1467,1474 ****
  	pageInfo = compiler.getPageInfo();
  	beanInfo = pageInfo.getBeanRepository();
  	breakAtLF = ctxt.getOptions().getMappedFile();
-         finallies = new FinallyApplyer();
-         tryStack = new Stack();
      }
  
      /**
--- 1442,1447 ----
***************
*** 1562,1616 ****
  	public Class getTagHandlerClass() {
  	    return tagHandlerClass;
  	}
-     }
- 
-     private static class FinallyApplyer {
-         private PrintStream finalOutput;
-         private ByteArrayOutputStream rawOutput;
- 
-         FinallyApplyer() {
-             rawOutput = new ByteArrayOutputStream();
-             finalOutput = new PrintStream(rawOutput, true);
- 
-             finalOutput.println();
-             finalOutput.println("  private void finallies(java.util.BitSet bitmask, JspWriter out, java.util.Vector tags, PageContext pageContext)");
-             finalOutput.println("  throws javax.servlet.jsp.JspException {");
-         }
- 
-         public void done() {
-             finalOutput.println("  }");
-         }
- 
-         public void beginPartMethod(int bit) {
-             finalOutput.print("    if (bitmask.get(");
-             finalOutput.print(bit);
-             finalOutput.println(")) {");
-         }
- 
-         public void endPartMethod() {
-             finalOutput.println("    }");
-             finalOutput.println();
-         }
- 
-         public void println(String aLine) {
-             if (null != aLine) {
-                 finalOutput.print(aLine);
-             }
-             finalOutput.println();
-         }
- 
-         public void printin(String partLine) {
-             finalOutput.print("      ");
-             finalOutput.print(partLine);
-         }
- 
-         public void print(String partLine) {
-             finalOutput.print(partLine);
-         }
- 
-         public String toString() {
-             return rawOutput.toString();
-         }
      }
  
  }
--- 1535,1540 ----

-- 
Denis Benoit
Denis.Benoit@fbn.ca
Tél: (514)879-5168



**********************************************************************
Financière Banque Nationale et NBCN n'assument
aucune responsabilité quant à la confidentialité et l'intégrité du 
présent courriel en raison des risques d'interception inhérents à l'Internet. 
Pour cette raison, toute opinion exprimée au terme des présentes 
ne reflète pas nécessairement celle de Financière Banque Nationale
et de NBCN.
**********************************************************************
Due to the security risks involved in sending information over the
Internet, National Bank Financial  and NBCN cannot
be held responsible for ensuring the confidentiality and integrity 
of the present e-mail. For this reason, the opinions expressed herein 
do not necessarily reflect those of National Bank Financial 
and NBCN.
**********************************************************************


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>