You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by zo...@apache.org on 2003/08/01 02:53:04 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler Comment.java Constants.java Text.java XSLTC.java

zongaro     2003/07/31 17:53:04

  Modified:    java/src/org/apache/xalan/xsltc/compiler Comment.java
                        Constants.java Text.java XSLTC.java
  Log:
  Added code to create static char[] fields in the translet containing the
  literal text in the source stylesheet.  The code generation for xsl:comment and
  for literal text that constructs text nodes takes advantage of this by using
  the serializer's comment(char[],int,int) and characters(char[],int,int) methods,
  respectively, rather than the comment(String) and characters(String) methods.
  The former pair of methods avoid some potential overhead in the serializer from
  copying the contents of strings to char[] objects.
  
  Reviewed by Morris Kwan (mkwan@ca.ibm.com)
  
  Revision  Changes    Path
  1.7       +62 -28    xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Comment.java
  
  Index: Comment.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Comment.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Comment.java	30 Jan 2003 18:45:59 -0000	1.6
  +++ Comment.java	1 Aug 2003 00:53:03 -0000	1.7
  @@ -68,6 +68,7 @@
   import org.apache.bcel.generic.GETFIELD;
   import org.apache.bcel.generic.INVOKEINTERFACE;
   import org.apache.bcel.generic.INVOKEVIRTUAL;
  +import org.apache.bcel.generic.PUSH;
   import org.apache.bcel.generic.InstructionList;
   import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
   import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
  @@ -89,32 +90,65 @@
   	final ConstantPoolGen cpg = classGen.getConstantPool();
   	final InstructionList il = methodGen.getInstructionList();
   
  -	// Save the current handler base on the stack
  -	il.append(methodGen.loadHandler());
  -	il.append(DUP);		// first arg to "comment" call
  -
  -	// Get the translet's StringValueHandler
  -	il.append(classGen.loadTranslet());
  -	il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
  -					       "stringValueHandler",
  -					       STRING_VALUE_HANDLER_SIG)));
  -	il.append(DUP);
  -	il.append(methodGen.storeHandler());
  -
  -	// translate contents with substituted handler
  -	translateContents(classGen, methodGen);
  -
  -	// get String out of the handler
  -	il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_VALUE_HANDLER,
  -						     "getValue",
  -						     "()" + STRING_SIG)));
  -	// call "comment"
  -	final int comment =
  -	    cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  -				      "comment", 
  -				      "(" + STRING_SIG + ")V");
  -	il.append(new INVOKEINTERFACE(comment, 2));
  -	// Restore old handler base from stack
  -	il.append(methodGen.storeHandler());
  +        // Shortcut for literal strings
  +        Text rawText = null;
  +        if (elementCount() == 1) {
  +            Object content = elementAt(0);
  +            if (content instanceof Text) {
  +                rawText = (Text) content;
  +            }
  +        }
  +
  +        // If the content is literal text, call comment(char[],int,int) or
  +        // comment(String), as appropriate.  Otherwise, use a
  +        // StringValueHandler to gather the textual content of the xsl:comment
  +        // and call comment(String) with the result.
  +        if (rawText != null) {
  +            il.append(methodGen.loadHandler());
  +
  +            if (rawText.canLoadAsArrayOffsetLength()) {
  +                rawText.loadAsArrayOffsetLength(classGen, methodGen);
  +                final int comment =
  +                        cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  +                                                  "comment",
  +                                                  "([CII)V");
  +                il.append(new INVOKEINTERFACE(comment, 4));
  +            } else {
  +                il.append(new PUSH(cpg, rawText.getText()));
  +                final int comment =
  +                        cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  +                                                  "comment",
  +                                                  "(" + STRING_SIG + ")V");
  +                il.append(new INVOKEINTERFACE(comment, 2));
  +            }
  +        } else {
  +            // Save the current handler base on the stack
  +            il.append(methodGen.loadHandler());
  +            il.append(DUP);             // first arg to "comment" call
  +
  +            // Get the translet's StringValueHandler
  +            il.append(classGen.loadTranslet());
  +            il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
  +                                                   "stringValueHandler",
  +                                                   STRING_VALUE_HANDLER_SIG)));
  +            il.append(DUP);
  +            il.append(methodGen.storeHandler());
  +
  +            // translate contents with substituted handler
  +            translateContents(classGen, methodGen);
  +
  +            // get String out of the handler
  +            il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_VALUE_HANDLER,
  +                                                         "getValue",
  +                                                         "()" + STRING_SIG)));
  +            // call "comment"
  +            final int comment =
  +                        cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  +                                                  "comment",
  +                                                  "(" + STRING_SIG + ")V");
  +            il.append(new INVOKEINTERFACE(comment, 2));
  +            // Restore old handler base from stack
  +            il.append(methodGen.storeHandler());
  +        }
       }
   }
  
  
  
  1.35      +5 -1      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Constants.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- Constants.java	25 Jun 2003 17:08:31 -0000	1.34
  +++ Constants.java	1 Aug 2003 00:53:03 -0000	1.35
  @@ -409,6 +409,10 @@
   
       public static final String DOM_FIELD
   	= "_dom";
  +    public static final String STATIC_CHAR_DATA_FIELD
  +        = "_scharData";
  +    public static final String STATIC_CHAR_DATA_FIELD_SIG
  +        = "[C";
       public static final String FORMAT_SYMBOLS_FIELD	 
   	= "format_symbols";
   
  
  
  
  1.16      +66 -7     xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Text.java
  
  Index: Text.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Text.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- Text.java	25 Jun 2003 14:40:35 -0000	1.15
  +++ Text.java	1 Aug 2003 00:53:03 -0000	1.16
  @@ -65,6 +65,7 @@
   package org.apache.xalan.xsltc.compiler;
   
   import org.apache.bcel.generic.ConstantPoolGen;
  +import org.apache.bcel.generic.GETSTATIC;
   import org.apache.bcel.generic.INVOKEINTERFACE;
   import org.apache.bcel.generic.InstructionList;
   import org.apache.bcel.generic.PUSH;
  @@ -179,12 +180,23 @@
   		il.append(new INVOKEINTERFACE(esc, 2));
   	    }
   
  -	    final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
  -							     "characters",
  -							     "(" + STRING_SIG + ")V");
  -	    il.append(methodGen.loadHandler());
  -	    il.append(new PUSH(cpg, _text));
  -	    il.append(new INVOKEINTERFACE(characters, 2));
  +            il.append(methodGen.loadHandler());
  +
  +            // Call characters(String) or characters(char[],int,int), as
  +            // appropriate.
  +            if (!canLoadAsArrayOffsetLength()) {
  +                final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
  +                                                           "characters",
  +                                                           "("+STRING_SIG+")V");
  +                il.append(new PUSH(cpg, _text));
  +                il.append(new INVOKEINTERFACE(characters, 2));
  +            } else {
  +                final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
  +                                                                 "characters",
  +                                                                 "([CII)V");
  +                loadAsArrayOffsetLength(classGen, methodGen);
  +	        il.append(new INVOKEINTERFACE(characters, 4));
  +            }
   
   	    // Restore character escaping setting to whatever it was.
   	    // Note: setEscaping(bool) returns the original (old) value
  @@ -196,5 +208,52 @@
   	    }
   	}
   	translateContents(classGen, methodGen);
  +    }
  +
  +    /**
  +     * Check whether this Text node can be stored in a char[] in the translet.
  +     * Calling this is precondition to calling loadAsArrayOffsetLength.
  +     * @see #loadAsArrayOffsetLength(ClassGenerator,MethodGenerator)
  +     * @return true if this Text node can be
  +     */
  +    public boolean canLoadAsArrayOffsetLength() {
  +        // Magic number!  21845*3 == 65535.  BCEL uses a DataOutputStream to
  +        // serialize class files.  The Java run-time places a limit on the size
  +        // of String data written using a DataOutputStream - it cannot require
  +        // more than 64KB when represented as UTF-8.  The number of bytes
  +        // required to represent a Java string as UTF-8 cannot be greater
  +        // than three times the number of char's in the string, hence the
  +        // check for 21845.
  +
  +        return (_text.length() <= 21845);
  +    }
  +
  +    /**
  +     * Generates code that loads the array that will contain the character
  +     * data represented by this Text node, followed by the offset of the
  +     * data from the start of the array, and then the length of the data.
  +     *
  +     * The pre-condition to calling this method is that
  +     * canLoadAsArrayOffsetLength() returns true.
  +     * @see #canLoadArrayOffsetLength()
  +     */
  +    public void loadAsArrayOffsetLength(ClassGenerator classGen,
  +                                        MethodGenerator methodGen) {
  +        final ConstantPoolGen cpg = classGen.getConstantPool();
  +        final InstructionList il = methodGen.getInstructionList();
  +        final XSLTC xsltc = classGen.getParser().getXSLTC();
  +
  +        // The XSLTC object keeps track of character data
  +        // that is to be stored in char arrays.
  +        final int offset = xsltc.addCharacterData(_text);
  +        final int length = _text.length();
  +        String charDataFieldName =
  +            STATIC_CHAR_DATA_FIELD + (xsltc.getCharacterDataCount()-1);
  +
  +        il.append(new GETSTATIC(cpg.addFieldref(xsltc.getClassName(),
  +                                       charDataFieldName,
  +                                       STATIC_CHAR_DATA_FIELD_SIG)));
  +        il.append(new PUSH(cpg, offset));
  +        il.append(new PUSH(cpg, _text.length()));
       }
   }
  
  
  
  1.53      +57 -1     xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XSLTC.java
  
  Index: XSLTC.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XSLTC.java,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -r1.52 -r1.53
  --- XSLTC.java	24 Apr 2003 15:45:32 -0000	1.52
  +++ XSLTC.java	1 Aug 2003 00:53:03 -0000	1.53
  @@ -126,6 +126,9 @@
       private Vector    _namespaceIndex; // Index of all registered namespaces
       private Hashtable _namespaces; // Hashtable of all registered namespaces
   
  +    // All literal text in the stylesheet
  +    private Vector m_characterData;
  +
       // These define the various methods for outputting the translet
       public static final int FILE_OUTPUT        = 0;
       public static final int JAR_OUTPUT         = 1;
  @@ -838,4 +841,57 @@
   	return _debug;
       }
   
  +
  +    /**
  +     * Retrieve a string representation of the character data to be stored
  +     * in the translet as a <code>char[]</code>.  There may be more than
  +     * one such array required.
  +     * @param index The index of the <code>char[]</code>.  Zero-based.
  +     * @return String The character data to be stored in the corresponding
  +     *               <code>char[]</code>.
  +     */
  +    public String getCharacterData(int index) {
  +        return ((StringBuffer) m_characterData.elementAt(index)).toString();
  +    }
  +
  +    /**
  +     * Get the number of char[] arrays, thus far, that will be created to
  +     * store literal text in the stylesheet.
  +     */
  +    public int getCharacterDataCount() {
  +        return (m_characterData != null) ? m_characterData.size() : 0;
  +    }
  +
  +    /**
  +     * Add literal text to char arrays that will be used to store character
  +     * data in the stylesheet.
  +     * @param newData String data to be added to char arrays.
  +     *                Pre-condition:  <code>newData.length() &le; 21845</code>
  +     * @return int offset at which character data will be stored
  +     */
  +    public int addCharacterData(String newData) {
  +        StringBuffer currData;
  +        if (m_characterData == null) {
  +            m_characterData = new Vector();
  +            currData = new StringBuffer();
  +            m_characterData.addElement(currData);
  +        } else {
  +            currData = (StringBuffer) m_characterData
  +                                           .elementAt(m_characterData.size()-1);
  +        }
  +
  +        // Character data could take up to three-times as much space when
  +        // written to the class file as UTF-8.  The maximum size for a
  +        // constant is 65535/3.  If we exceed that,
  +        // (We really should use some "bin packing".)
  +        if (newData.length() + currData.length() > 21845) {
  +            currData = new StringBuffer();
  +            m_characterData.addElement(currData);
  +        }
  +
  +        int newDataOffset = currData.length();
  +        currData.append(newData);
  +
  +        return newDataOffset;
  +    }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org