blob: 45b42a0ed575ac673ddf233a83665442071f47d3 [file] [log] [blame]
/*
* @(#)$Id$
*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, Sun
* Microsystems., http://www.sun.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* @author Jacek Ambroziak
* @author Santiago Pericas-Geertsen
*
*/
package org.apache.xalan.xsltc.compiler.util;
import org.apache.bcel.generic.Type;
import org.apache.bcel.generic.*;
import org.apache.xalan.xsltc.compiler.Template;
public class MethodGenerator extends MethodGen
implements org.apache.xalan.xsltc.compiler.Constants {
protected static final int INVALID_INDEX = -1;
private static final String START_ELEMENT_SIG
= "(" + STRING_SIG + ")V";
private static final String END_ELEMENT_SIG
= START_ELEMENT_SIG;
private InstructionList _mapTypeSub;
private static final int DOM_INDEX = 1;
private static final int ITERATOR_INDEX = 2;
private static final int HANDLER_INDEX = 3;
private Instruction _iloadCurrent;
private Instruction _istoreCurrent;
private final Instruction _astoreHandler;
private final Instruction _aloadHandler;
private final Instruction _astoreIterator;
private final Instruction _aloadIterator;
private final Instruction _aloadDom;
private final Instruction _astoreDom;
private final Instruction _startElement;
private final Instruction _endElement;
private final Instruction _startDocument;
private final Instruction _endDocument;
private final Instruction _attribute;
private final Instruction _namespace;
private final Instruction _setStartNode;
private final Instruction _reset;
private final Instruction _nextNode;
private SlotAllocator _slotAllocator;
private boolean _allocatorInit = false;
public MethodGenerator(int access_flags, Type return_type,
Type[] arg_types, String[] arg_names,
String method_name, String class_name,
InstructionList il, ConstantPoolGen cpg) {
super(access_flags, return_type, arg_types, arg_names, method_name,
class_name, il, cpg);
_astoreHandler = new ASTORE(HANDLER_INDEX);
_aloadHandler = new ALOAD(HANDLER_INDEX);
_astoreIterator = new ASTORE(ITERATOR_INDEX);
_aloadIterator = new ALOAD(ITERATOR_INDEX);
_aloadDom = new ALOAD(DOM_INDEX);
_astoreDom = new ASTORE(DOM_INDEX);
final int startElement =
cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
"startElement",
START_ELEMENT_SIG);
_startElement = new INVOKEINTERFACE(startElement, 2);
final int endElement =
cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
"endElement",
END_ELEMENT_SIG);
_endElement = new INVOKEINTERFACE(endElement, 2);
final int attribute =
cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
"attribute",
"("
+ STRING_SIG
+ STRING_SIG
+ ")V");
_attribute = new INVOKEINTERFACE(attribute, 3);
final int namespace =
cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
"namespace",
"("
+ STRING_SIG
+ STRING_SIG
+ ")V");
_namespace = new INVOKEINTERFACE(namespace, 3);
int index = cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
"startDocument",
"()V");
_startDocument = new INVOKEINTERFACE(index, 1);
index = cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
"endDocument",
"()V");
_endDocument = new INVOKEINTERFACE(index, 1);
index = cpg.addInterfaceMethodref(NODE_ITERATOR,
SET_START_NODE,
SET_START_NODE_SIG);
_setStartNode = new INVOKEINTERFACE(index, 2);
index = cpg.addInterfaceMethodref(NODE_ITERATOR,
"reset", "()"+NODE_ITERATOR_SIG);
_reset = new INVOKEINTERFACE(index, 1);
index = cpg.addInterfaceMethodref(NODE_ITERATOR, NEXT, NEXT_SIG);
_nextNode = new INVOKEINTERFACE(index, 1);
_slotAllocator = new SlotAllocator();
_slotAllocator.initialize(getLocalVariables());
_allocatorInit = true;
}
/**
* Allocates a local variable. If the slot allocator has already been
* initialized, then call addLocalVariable2() so that the new variable
* is known to the allocator. Failing to do this may cause the allocator
* to return a slot that is already in use.
*/
public LocalVariableGen addLocalVariable(String name, Type type,
InstructionHandle start,
InstructionHandle end)
{
return (_allocatorInit) ? addLocalVariable2(name, type, start)
: super.addLocalVariable(name, type, start, end);
}
public LocalVariableGen addLocalVariable2(String name, Type type,
InstructionHandle start)
{
return super.addLocalVariable(name, type,
_slotAllocator.allocateSlot(type),
start, null);
}
public void removeLocalVariable(LocalVariableGen lvg) {
_slotAllocator.releaseSlot(lvg);
super.removeLocalVariable(lvg);
}
public Instruction loadDOM() {
return _aloadDom;
}
public Instruction storeDOM() {
return _astoreDom;
}
public Instruction storeHandler() {
return _astoreHandler;
}
public Instruction loadHandler() {
return _aloadHandler;
}
public Instruction storeIterator() {
return _astoreIterator;
}
public Instruction loadIterator() {
return _aloadIterator;
}
public final Instruction setStartNode() {
return _setStartNode;
}
public final Instruction reset() {
return _reset;
}
public final Instruction nextNode() {
return _nextNode;
}
public final Instruction startElement() {
return _startElement;
}
public final Instruction endElement() {
return _endElement;
}
public final Instruction startDocument() {
return _startDocument;
}
public final Instruction endDocument() {
return _endDocument;
}
public final Instruction attribute() {
return _attribute;
}
public final Instruction namespace() {
return _namespace;
}
public Instruction loadCurrentNode() {
if (_iloadCurrent == null) {
int idx = getLocalIndex("current");
if (idx > 0)
_iloadCurrent = new ILOAD(idx);
else
_iloadCurrent = new ICONST(0);
}
return _iloadCurrent;
}
public Instruction storeCurrentNode() {
return _istoreCurrent != null
? _istoreCurrent
: (_istoreCurrent = new ISTORE(getLocalIndex("current")));
}
/** by default context node is the same as current node. MK437 */
public Instruction loadContextNode() {
return loadCurrentNode();
}
public Instruction storeContextNode() {
return storeCurrentNode();
}
public int getLocalIndex(String name) {
return getLocalVariable(name).getIndex();
}
public LocalVariableGen getLocalVariable(String name) {
final LocalVariableGen[] vars = getLocalVariables();
for (int i = 0; i < vars.length; i++)
if (vars[i].getName().equals(name))
return vars[i];
return null;
}
public void setMaxLocals() {
// Get the current number of local variable slots
int maxLocals = super.getMaxLocals();
int prevLocals = maxLocals;
// Get numer of actual variables
final LocalVariableGen[] localVars = super.getLocalVariables();
if (localVars != null) {
if (localVars.length > maxLocals)
maxLocals = localVars.length;
}
// We want at least 5 local variable slots (for parameters)
if (maxLocals < 5) maxLocals = 5;
super.setMaxLocals(maxLocals);
}
}