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() ≤ 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