Part of patch for XALANJ-1324 and others.

Creating new marker instructions (OutlineableChunkStart, OutlineableChunkEnd
and their base class, MarkerInstruction).

In SyntaxTreeNode.translateContents, before and after generating code for the
content of an XSLT element, added references to MethodGenerator.markChunkStart
and MethodGenerator.markChunkEnd, respectively, to assist method splitting and
outlining.  These mark the boundaries of logical chunks of the generated byte
code that are eligible for outlining using MarkerInstructions.  Generated code
should not branch out of or into such chunks of code.

See org.apache.xalan.xsltc.compiler.util.MethodGenerator.outlineChunks for more
information.

Patch reviewed by Christine Li and Erin Harris.

diff --git a/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java b/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
index 5efe62c..13ca687 100644
--- a/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
+++ b/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2004 The Apache Software Foundation.
+ * Copyright 2001-2006 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
 import org.apache.bcel.generic.INVOKEINTERFACE;
 import org.apache.bcel.generic.INVOKESPECIAL;
 import org.apache.bcel.generic.INVOKEVIRTUAL;
+import org.apache.bcel.generic.InstructionHandle;
 import org.apache.bcel.generic.InstructionList;
 import org.apache.bcel.generic.NEW;
 import org.apache.bcel.generic.NEWARRAY;
@@ -496,25 +497,28 @@
      * @param methodGen BCEL Java method generator
      */
     protected void translateContents(ClassGenerator classGen,
-				     MethodGenerator methodGen) {
-	// Call translate() on all child nodes
-	final int n = elementCount();
-	for (int i = 0; i < n; i++) {
-	    final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
-	    item.translate(classGen, methodGen);
-	}
+                                     MethodGenerator methodGen) {
+        // Call translate() on all child nodes
+        final int n = elementCount();
 
-	// After translation, unmap any registers for any variables/parameters
-	// that were declared in this scope. Performing this unmapping in the
-	// same AST scope as the declaration deals with the problems of
-	// references falling out-of-scope inside the for-each element.
-	// (the cause of which being 'lazy' register allocation for references)
-	for (int i = 0; i < n; i++) {
-	    if( _contents.elementAt(i) instanceof VariableBase) {
-		final VariableBase var = (VariableBase)_contents.elementAt(i);
-		var.unmapRegister(methodGen);
-	    }
-	}
+        for (int i = 0; i < n; i++) {
+            methodGen.markChunkStart();
+            final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
+            item.translate(classGen, methodGen);
+            methodGen.markChunkEnd();
+        }
+
+        // After translation, unmap any registers for any variables/parameters
+        // that were declared in this scope. Performing this unmapping in the
+        // same AST scope as the declaration deals with the problems of
+        // references falling out-of-scope inside the for-each element.
+        // (the cause of which being 'lazy' register allocation for references)
+        for (int i = 0; i < n; i++) {
+            if( _contents.elementAt(i) instanceof VariableBase) {
+                final VariableBase var = (VariableBase)_contents.elementAt(i);
+                var.unmapRegister(methodGen);
+            }
+        }
     }
     
     /**
diff --git a/src/org/apache/xalan/xsltc/compiler/util/MarkerInstruction.java b/src/org/apache/xalan/xsltc/compiler/util/MarkerInstruction.java
new file mode 100644
index 0000000..7f2c28a
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/compiler/util/MarkerInstruction.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * $Id$
+ */
+
+package org.apache.xalan.xsltc.compiler.util;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.Visitor;
+
+/**
+ * A special abstract dummy subclass of
+ * {@link org.apache.bcel.generic.Instruction} used to mark locations of
+ * interest in an {@link org.apache.bcel.generic.InstructionList}.  It and
+ * its subclasses are only used as placeholders, and do not contribute to the
+ * actual byte code instruction stream.
+ */
+abstract class MarkerInstruction extends Instruction {
+    /**
+     * Zero-argument constructor.  Sets the opcode to an invalid value and 
+     * sets the length to zero, as it will not be written as part of the
+     * generated byte code.
+     */
+    public MarkerInstruction() {
+        super(Constants.UNDEFINED, (short) 0);
+    }
+
+    /**
+     * {@link org.apache.bcel.generic.Visitor}s will know nothing about this
+     * kind of {@link org.apche.bcel.generic.Instruction}, so this method does
+     * nothing.
+     */
+    public void accept(Visitor v) {
+    }
+
+    /**
+     * The number of JVM stack entries consumed by the instruction.
+     * This instruction is just a place holder, so it does not consume any
+     * stack entries.
+     * @param cpg The {@link org.apache.bcel.generic.ConstantPoolGen} for the
+     * current {@link org.apache.bcel.generic.ClassGen}
+     * @return <code>0</code> always 
+     */
+    final public int consumeStack(ConstantPoolGen cpg) {
+        return 0;
+    }
+    /**
+     * The number of JVM stack entries produced by the instruction.
+     * This instruction is just a place holder, so it does not produce any
+     * stack entries.
+     * @param cpg The {@link org.apache.bcel.generic.ConstantPoolGen} for the
+     * current {@link org.apache.bcel.generic.ClassGen}
+     * @return <code>0</code> always 
+     */
+    final public int produceStack(ConstantPoolGen cpg) {
+        return 0;
+    }
+
+    /**
+     * Produce a copy of the instruction.  By default a
+     * {@link MarkerInstruction} has no parameters, so the base implementation
+     * of {@link #copy()} returns the instruction itself.
+     * @return The instruction itself.
+     */
+    public Instruction copy() {
+        return this;
+    }
+    /**
+     * Dump instruction as byte code to stream out.  A {@link MarkerInstruction}
+     * has no effect on the generated byte code so it is never emitted to the
+     * output stream.
+     * @param out Output stream
+     */
+    final public void dump(DataOutputStream out) throws IOException {
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/compiler/util/OutlineableChunkEnd.java b/src/org/apache/xalan/xsltc/compiler/util/OutlineableChunkEnd.java
new file mode 100644
index 0000000..a92af82
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/compiler/util/OutlineableChunkEnd.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * $Id$
+ */
+
+package org.apache.xalan.xsltc.compiler.util;
+
+import org.apache.bcel.generic.Instruction;
+
+/**
+ * <p>Marks the end of a region of byte code that can be copied into a new
+ * method.  See the {@link OutlineableChunkStart} pseudo-instruction for
+ * details.</p>
+ */
+class OutlineableChunkEnd extends MarkerInstruction {
+    /**
+     * A constant instance of {@link OutlineableChunkEnd}.  As it has no fields,
+     * there should be no need to create an instance of this class. 
+     */
+    public static final Instruction OUTLINEABLECHUNKEND =
+                                                new OutlineableChunkEnd();
+
+    /**
+     * Private default constructor.  As it has no fields,
+     * there should be no need to create an instance of this class.  See
+     * {@link OutlineableChunkEnd#OUTLINEABLECHUNKEND}.
+     */
+    private OutlineableChunkEnd() {
+    }
+
+    /**
+     * Get the name of this instruction.  Used for debugging.
+     * @return the instruction name
+     */
+    public String getName() {
+        return OutlineableChunkEnd.class.getName();
+    }
+
+    /**
+     * Get the name of this instruction.  Used for debugging.
+     * @return the instruction name
+     */
+    public String toString() {
+        return getName();
+    }
+
+    /**
+     * Get the name of this instruction.  Used for debugging.
+     * @return the instruction name
+     */
+    public String toString(boolean verbose) {
+        return getName();
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/compiler/util/OutlineableChunkStart.java b/src/org/apache/xalan/xsltc/compiler/util/OutlineableChunkStart.java
new file mode 100644
index 0000000..c0dcf3e
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/compiler/util/OutlineableChunkStart.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * $Id$
+ */
+
+package org.apache.xalan.xsltc.compiler.util;
+
+import org.apache.bcel.generic.Instruction;
+
+/**
+ * <p>This pseudo-instruction marks the beginning of a region of byte code that
+ * can be copied into a new method, termed an "outlineable" chunk.  The size of
+ * the Java stack must be the same at the start of the region as it is at the
+ * end of the region, any value on the stack at the start of the region must not
+ * be consumed by an instruction in the region of code, the region must not
+ * contain a return instruction, no branch instruction in the region is
+ * permitted to have a target that is outside the region, and no branch
+ * instruction outside the region is permitted to have a target that is inside
+ * the region.</p>
+ * <p>The end of the region is marked by an {@link OutlineableChunkEnd}
+ * pseudo-instruction.</p>
+ * <p>Such a region of code may contain other outlineable regions.</p>
+ */
+class OutlineableChunkStart extends MarkerInstruction {
+    /**
+     * A constant instance of {@link OutlineableChunkStart}.  As it has no fields,
+     * there should be no need to create an instance of this class. 
+     */
+    public static final Instruction OUTLINEABLECHUNKSTART =
+                                                new OutlineableChunkStart();
+
+    /**
+     * Private default constructor.  As it has no fields,
+     * there should be no need to create an instance of this class.  See
+     * {@link OutlineableChunkStart#OUTLINEABLECHUNKSTART}.
+     */
+    private OutlineableChunkStart() {
+    }
+
+    /**
+     * Get the name of this instruction.  Used for debugging.
+     * @return the instruction name
+     */
+    public String getName() {
+        return OutlineableChunkStart.class.getName();
+    }
+
+    /**
+     * Get the name of this instruction.  Used for debugging.
+     * @return the instruction name
+     */
+    public String toString() {
+        return getName();
+    }
+
+    /**
+     * Get the name of this instruction.  Used for debugging.
+     * @return the instruction name
+     */
+    public String toString(boolean verbose) {
+        return getName();
+    }
+}
\ No newline at end of file