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 ([EMAIL PROTECTED])
  
  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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to