/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ALOAD;
import org.apache.bcel.generic.ASTORE;
import org.apache.bcel.generic.BranchHandle;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.DLOAD;
import org.apache.bcel.generic.DSTORE;
import org.apache.bcel.generic.FLOAD;
import org.apache.bcel.generic.FSTORE;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.ICONST;
import org.apache.bcel.generic.IfInstruction;
import org.apache.bcel.generic.ILOAD;
import org.apache.bcel.generic.IndexedInstruction;
import org.apache.bcel.generic.INVOKEINTERFACE;
import org.apache.bcel.generic.INVOKESPECIAL;
import org.apache.bcel.generic.INVOKESTATIC;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.ISTORE;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.InstructionTargeter;
import org.apache.bcel.generic.LocalVariableGen;
import org.apache.bcel.generic.LocalVariableInstruction;
import org.apache.bcel.generic.LLOAD;
import org.apache.bcel.generic.LSTORE;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.NEW;
import org.apache.bcel.generic.PUTFIELD;
import org.apache.bcel.generic.RET;
import org.apache.bcel.generic.Select;
import org.apache.bcel.generic.TargetLostException;
import org.apache.bcel.generic.Type;

import org.apache.xalan.xsltc.compiler.Pattern;
import org.apache.xalan.xsltc.compiler.XSLTC;

/**
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 */
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 static final int MAX_METHOD_SIZE = 65535;
    private static final int MAX_BRANCH_TARGET_OFFSET = 32767;
    private static final int MIN_BRANCH_TARGET_OFFSET = -32768;

    private static final int TARGET_METHOD_SIZE = 60000;
    private static final int MINIMUM_OUTLINEABLE_CHUNK_SIZE = 1000;

    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 _uniqueAttribute;
    private final Instruction _namespace;

    private final Instruction _setStartNode;
    private final Instruction _reset;
    private final Instruction _nextNode;

    private SlotAllocator _slotAllocator;
    private boolean _allocatorInit = false;
    private LocalVariableRegistry _localVariableRegistry;

    /**
     * A mapping between patterns and instruction lists used by 
     * test sequences to avoid compiling the same pattern multiple 
     * times. Note that patterns whose kernels are "*", "node()" 
     * and "@*" can between shared by test sequences.
     */
    private Hashtable _preCompiled = new Hashtable();

    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,
				      "addAttribute", 
				      "("
				      + STRING_SIG
				      + STRING_SIG
				      + ")V");
	_attribute = new INVOKEINTERFACE(attribute, 3);

	final int uniqueAttribute =
	    cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
				      "addUniqueAttribute", 
				      "("
				      + STRING_SIG
				      + STRING_SIG
				      + "I)V");
	_uniqueAttribute = new INVOKEINTERFACE(uniqueAttribute, 4);

	final int namespace =
	    cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
				      "namespaceAfterStartElement", 
				      "("
				      + 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(getLocalVariableRegistry().getLocals(false));
	_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) 
    {
        LocalVariableGen lvg;

        if (_allocatorInit) {
            lvg = addLocalVariable2(name, type, start); 
        } else {
	    lvg = super.addLocalVariable(name, type, start, end);
            getLocalVariableRegistry().registerLocalVariable(lvg);
        }

        return lvg;
    }
    
    public LocalVariableGen addLocalVariable2(String name, Type type,
					      InstructionHandle start) 
    {
	LocalVariableGen lvg = super.addLocalVariable(name, type,
                                              _slotAllocator.allocateSlot(type),
                                              start, null);
        getLocalVariableRegistry().registerLocalVariable(lvg);
        return lvg;
    }

    private LocalVariableRegistry getLocalVariableRegistry() {
        if (_localVariableRegistry == null) {
            _localVariableRegistry = new LocalVariableRegistry();
        }
        
        return _localVariableRegistry;
    }

    /**
     * Keeps track of all local variables used in the method.
     * <p>The
     * {@link MethodGen#addLocalVariable(String,Type,InstructionHandle,InstructionHandle)}</code>
     * and
     * {@link MethodGen#addLocalVariable(String,Type,int,InstructionHandle,InstructionHandle)}</code>
     * methods of {@link MethodGen} will only keep track of
     * {@link LocalVariableGen} object until it'ss removed by a call to
     * {@link MethodGen#removeLocalVariable(LocalVariableGen)}.</p>
     * <p>In order to support efficient copying of local variables to outlined
     * methods by
     * {@link #outline(InstructionHandle,InstructionHandle,String,ClassGenerator)},
     * this class keeps track of all local variables defined by the method.</p>
     */
    protected class LocalVariableRegistry {
        /**
         * <p>A <code>java.lang.ArrayList</code> of all
         * {@link LocalVariableGen}s created for this method, indexed by the
         * slot number of the local variable.  The JVM stack frame of local
         * variables is divided into "slots".  A single slot can be used to
         * store more than one variable in a method, without regard to type, so
         * long as the byte code keeps the ranges of the two disjoint.</p>
         * <p>If only one registration of use of a particular slot occurs, the
         * corresponding entry of <code>_variables</code> contains the
         * <code>LocalVariableGen</code>; if more than one occurs, the
         * corresponding entry contains all such <code>LocalVariableGen</code>s
         * registered for the same slot; and if none occurs, the entry will be
         * <code>null</code>. 
         */
        protected ArrayList _variables = new ArrayList();

        /**
         * Maps a name to a {@link LocalVariableGen}
         */
        protected HashMap _nameToLVGMap = new HashMap();

        /**
         * Registers a {@link org.apache.bcel.generic.LocalVariableGen}
         * for this method.
         * <p><b>Preconditions:</b>
         * <ul>
         * <li>The range of instructions for <code>lvg</code> does not
         * overlap with the range of instructions for any
         * <code>LocalVariableGen</code> with the same slot index previously
         * registered for this method.  <b><em>(Unchecked.)</em></b></li>
         * </ul></p>
         * @param lvg The variable to be registered
         */
        protected void registerLocalVariable(LocalVariableGen lvg) {
            int slot = lvg.getIndex();

            int registrySize = _variables.size();

            // If the LocalVariableGen uses a slot index beyond any previously
            // encountered, expand the _variables, padding with intervening null
            // entries as required.
            if (slot >= registrySize) {
                for (int i = registrySize; i < slot; i++) {
                    _variables.add(null);
                }
                _variables.add(lvg);
            } else {
                // If the LocalVariableGen reuses a slot, make sure the entry
                // in _variables contains an ArrayList and add the newly
                // registered LocalVariableGen to the list.  If the entry in
                // _variables just contains null padding, store the
                // LocalVariableGen directly.
                Object localsInSlot = _variables.get(slot);
                if (localsInSlot != null) {
                    if (localsInSlot instanceof LocalVariableGen) {
                        ArrayList listOfLocalsInSlot = new ArrayList();
                        listOfLocalsInSlot.add(localsInSlot);
                        listOfLocalsInSlot.add(lvg);
                        _variables.set(slot, listOfLocalsInSlot);
                    } else {
                        ((ArrayList) localsInSlot).add(lvg);
                    }
                } else {
                    _variables.set(slot, lvg);
                }
            }

            registerByName(lvg);
        }

        /**
         * <p>Find which {@link LocalVariableGen}, if any, is registered for a
         * particular JVM local stack frame slot at a particular position in the
         * byte code for the method.</p>
         * <p><b>Preconditions:</b>
         * <ul>
         * <li>The {@link InstructionList#setPositions()} has been called for
         * the {@link InstructionList} associated with this
         * {@link MethodGenerator}.</li>
         * </ul></p>
         * @param slot the JVM local stack frame slot number
         * @param offset the position in the byte code
         * @return the <code>LocalVariableGen</code> for the local variable
         * stored in the relevant slot at the relevant offset; <code>null</code>
         * if there is none.
         */
        protected LocalVariableGen lookupRegisteredLocalVariable(int slot,
                                                                 int offset) {
            Object localsInSlot = (_variables != null) ? _variables.get(slot)
                                                       : null;

            // If this slot index was never used, _variables.get will return
            // null; if it was used once, it will return the LocalVariableGen;
            // more than once it will return an ArrayList of all the
            // LocalVariableGens for variables stored in that slot.  For each
            // LocalVariableGen, check whether its range includes the
            // specified offset, and return the first such encountered.
            if (localsInSlot != null) {
                if (localsInSlot instanceof LocalVariableGen) {
                    LocalVariableGen lvg = (LocalVariableGen)localsInSlot;
                    if (offsetInLocalVariableGenRange(lvg, offset)) {
                        return lvg;
                    }
                } else {
                    ArrayList listOfLocalsInSlot = (ArrayList) localsInSlot;
                    int size = listOfLocalsInSlot.size();

                    for (int i = 0; i < size; i++) {
                        LocalVariableGen lvg =
                            (LocalVariableGen)listOfLocalsInSlot.get(i);
                        if (offsetInLocalVariableGenRange(lvg, offset)) {
                            return lvg;
                        }
                    }
                }
            }

            // No local variable stored in the specified slot at the specified
            return null;
        }

        /**
         * <p>Set up a mapping of the name of the specified
         * {@link LocalVariableGen} object to the <code>LocalVariableGen</code>
         * itself.</p>
         * <p>This is a bit of a hack.  XSLTC is relying on the fact that the
         * name that is being looked up won't be duplicated, which isn't
         * guaranteed.  It replaces code which used to call
         * {@link MethodGen#getLocalVariables()} and looped through the
         * <code>LocalVariableGen</code> objects it contained to find the one
         * with the specified name.  However, <code>getLocalVariables()</code>
         * has the side effect of setting the start and end for any
         * <code>LocalVariableGen</code> which did not already have them
         * set, which causes problems for outlining..</p>
         * <p>See also {@link #lookUpByName(String)} and
         * {@link #removeByNameTracking(LocalVariableGen)}</P
         * @param lvg a <code>LocalVariableGen</code>
         */
        protected void registerByName(LocalVariableGen lvg) {
            Object duplicateNameEntry = _nameToLVGMap.get(lvg.getName());

            if (duplicateNameEntry == null) {
                _nameToLVGMap.put(lvg.getName(), lvg);
            } else {
                ArrayList sameNameList;

                if (duplicateNameEntry instanceof ArrayList) {
                    sameNameList = (ArrayList) duplicateNameEntry;
                    sameNameList.add(lvg);
                } else {
                    sameNameList = new ArrayList();
                    sameNameList.add(duplicateNameEntry);
                    sameNameList.add(lvg);
                }

                _nameToLVGMap.put(lvg.getName(), sameNameList);
            }
        }

        /**
         * Remove the mapping from the name of the specified
         * {@link LocalVariableGen} to itself. 
         * See also {@link #registerByName(LocalVariableGen)} and
         * {@link #lookUpByName(String)}
         * @param lvg a <code>LocalVariableGen</code>
         */
        protected void removeByNameTracking(LocalVariableGen lvg) {
            Object duplicateNameEntry = _nameToLVGMap.get(lvg.getName());

            if (duplicateNameEntry instanceof ArrayList) {
                ArrayList sameNameList = (ArrayList) duplicateNameEntry;
                for (int i = 0; i < sameNameList.size(); i++) {
                    if (sameNameList.get(i) == lvg) {
                        sameNameList.remove(i);
                        break;
                    }
                }
            } else {
                _nameToLVGMap.remove(lvg);
            }
        }

        /**
         * <p>Given the name of a variable, finds a {@link LocalVariableGen}
         * corresponding to it.</p>
         * <p>See also {@link #registerByName(LocalVariableGen)} and
         * {@link #removeByNameTracking(LocalVariableGen)}</p>
         * @param name
         * @return
         */
        protected LocalVariableGen lookUpByName(String name) {
            LocalVariableGen lvg = null;
            Object duplicateNameEntry = _nameToLVGMap.get(name);

            if (duplicateNameEntry instanceof ArrayList) {
                ArrayList sameNameList = (ArrayList) duplicateNameEntry;

                for (int i = 0; i < sameNameList.size(); i++) {
                    lvg = (LocalVariableGen)sameNameList.get(i);
                    if (lvg.getName() == name) {
                        break;
                    }
                }
            } else {
                lvg = (LocalVariableGen) duplicateNameEntry;
            }

            return lvg;
        }

        /**
         * <p>Gets all {@link LocalVariableGen} objects for this method.</p>
         * <p>When the <code>includeRemoved</code> argument has the value
         * <code>false</code>, this method replaces uses of
         * {@link MethodGen#getLocalVariables()} which has
         * a side-effect of setting the start and end range for any
         * <code>LocalVariableGen</code> if either was <code>null</code>.  That
         * side-effect causes problems for outlining of code in XSLTC. 
         * @param includeRemoved Specifies whether all local variables ever
         * declared should be returned (<code>true</code>) or only those not
         * removed (<code>false</code>)
         * @return an array of <code>LocalVariableGen</code> containing all the
         * local variables
         */
        protected LocalVariableGen[] getLocals(boolean includeRemoved) {
            LocalVariableGen[] locals = null;
            ArrayList allVarsEverDeclared = new ArrayList();
            
            if (includeRemoved) {
                int slotCount = allVarsEverDeclared.size();

                for (int i = 0; i < slotCount; i++) {
                    Object slotEntries = _variables.get(i);
                    if (slotEntries != null) {
                        if (slotEntries instanceof ArrayList) {
                            ArrayList slotList = (ArrayList) slotEntries;

                            for (int j = 0; j < slotList.size(); j++) {
                                allVarsEverDeclared.add(slotList.get(i));
                            }
                        } else {
                            allVarsEverDeclared.add(slotEntries);
                        }
                    }
                }
            } else {
                Iterator nameVarsPairsIter = _nameToLVGMap.entrySet().iterator();

                while (nameVarsPairsIter.hasNext()) {
                    Map.Entry nameVarsPair =
                                  (Map.Entry) nameVarsPairsIter.next();
                    Object vars = nameVarsPair.getValue();
                    if (vars != null) {
                        if (vars instanceof ArrayList) {
                            ArrayList varsList = (ArrayList) vars;
                            for (int i = 0; i < varsList.size(); i++) {
                                allVarsEverDeclared.add(varsList.get(i));
                            }
                        } else {
                            allVarsEverDeclared.add(vars);
                        }
                    }
                }
            }

            locals = new LocalVariableGen[allVarsEverDeclared.size()];
            allVarsEverDeclared.toArray(locals);

            return locals;
        }
    }

    /**
     * Determines whether a particular variable is in use at a particular offset
     * in the byte code for this method.
     * <p><b>Preconditions:</b>
     * <ul>
     * <li>The {@link InstructionList#setPositions()} has been called for the
     * {@link InstructionList} associated with this {@link MethodGenerator}.
     * </li></ul></p>
     * @param lvg the {@link LocalVariableGen} for the variable
     * @param offset the position in the byte code
     * @return <code>true</code> if and only if the specified variable is in
     * use at the particular byte code offset.
     */
    boolean offsetInLocalVariableGenRange(LocalVariableGen lvg, int offset) {
        InstructionHandle lvgStart = lvg.getStart();
        InstructionHandle lvgEnd = lvg.getEnd();

        // If no start handle is recorded for the LocalVariableGen, it is
        // assumed to be in use from the beginning of the method.
        if (lvgStart == null) {
            lvgStart = getInstructionList().getStart();
        }

        // If no end handle is recorded for the LocalVariableGen, it is assumed
        // to be in use to the end of the method.
        if (lvgEnd == null) {
            lvgEnd = getInstructionList().getEnd();
        }

        // Does the range of the instruction include the specified offset?
        // Note that the InstructionHandle.getPosition method returns the
        // offset of the beginning of an instruction.  A LocalVariableGen's
        // range includes the end instruction itself, so that instruction's
        // length must be taken into consideration in computing whether the
        // varible is in range at a particular offset.
        return ((lvgStart.getPosition() <= offset)
                    && (lvgEnd.getPosition()
                            + lvgEnd.getInstruction().getLength() >= offset));
    }

    public void removeLocalVariable(LocalVariableGen lvg) {
	_slotAllocator.releaseSlot(lvg);
        getLocalVariableRegistry().removeByNameTracking(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 uniqueAttribute() {
    	return _uniqueAttribute;
    }

    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) {
        return getLocalVariableRegistry().lookUpByName(name);
    }

    public void setMaxLocals() {
	
	// Get the current number of local variable slots
	int maxLocals = super.getMaxLocals();

	// 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);
    }

    /**
     * Add a pre-compiled pattern to this mode. 
     */
    public void addInstructionList(Pattern pattern, InstructionList ilist) {
        _preCompiled.put(pattern, ilist);
    }

    /**
     * Get the instruction list for a pre-compiled pattern. Used by 
     * test sequences to avoid compiling patterns more than once.
     */
    public InstructionList getInstructionList(Pattern pattern) {
        return (InstructionList) _preCompiled.get(pattern);
    }

    /**
     * Used to keep track of an outlineable chunk of instructions in the
     * current method.  See {@link OutlineableChunkStart} and
     * {@link OutlineableChunkEnd} for more information.
     */
    private class Chunk implements Comparable {
        /**
         * {@link InstructionHandle} of the first instruction in the outlineable
         * chunk.
         */
        private InstructionHandle m_start;

        /**
         * {@link org.apache.bcel.generic.InstructionHandle} of the first
         * instruction in the outlineable chunk.
         */
        private InstructionHandle m_end;

        /**
         * Number of bytes in the instructions contained in this outlineable
         * chunk.
         */
        private int m_size;

        /**
         * <p>Constructor for an outlineable {@link MethodGenerator.Chunk}.</p>
         * <p><b>Preconditions:</b>
         * <ul>
         * <li>The {@link InstructionList#setPositions()} has been called for
         * the {@link InstructionList} associated with this
         * {@link MethodGenerator}.</li>
         * </ul></p>
         * @param start The {@link InstructionHandle} of the first
         *              instruction in the outlineable chunk.
         * @param end The {@link InstructionHandle} of the last
         *            instruction in the outlineable chunk.
         */
        Chunk(InstructionHandle start, InstructionHandle end) {
            m_start = start;
            m_end = end;
            m_size = end.getPosition() - start.getPosition();
        }

        /**
         * Determines whether this outlineable {@link MethodGenerator.Chunk} is
         * followed immediately by the argument
         * <code>MethodGenerator.Chunk</code>, with no other intervening
         * instructions, including {@link OutlineableChunkStart} or
         * {@link OutlineableChunkEnd} instructions.
         * @param neighbour an outlineable {@link MethodGenerator.Chunk}
         * @return <code>true</code> if and only if the argument chunk
         * immediately follows <code>this</code> chunk
         */
        boolean isAdjacentTo(Chunk neighbour) {
            return getChunkEnd().getNext() == neighbour.getChunkStart();
        }

        /**
         * Getter method for the start of this {@linke MethodGenerator.Chunk}
         * @return the {@link org.apache.bcel.generic.InstructionHandle} of the
         * start of this chunk
         */
        InstructionHandle getChunkStart() {
            return m_start;
        }

        /**
         * Getter method for the end of this {@link MethodGenerator.Chunk}
         * @return the {@link InstructionHandle} of the start of this chunk
         */
        InstructionHandle getChunkEnd() {
            return m_end;
        }

        /**
         * The size of this {@link MethodGenerator.Chunk}
         * @return the number of bytes in the byte code represented by this
         *         chunk.
         */
        int getChunkSize() {
            return m_size;
        }

        /**
         * Implements the <code>java.util.Comparable.compareTo(Object)</code>
         * method.
         * @return
         * <ul>
         * <li>A positive <code>int</code> if the length of <code>this</code>
         * chunk in bytes is greater than that of <code>comparand</code></li>
         * <li>A negative <code>int</code> if the length of <code>this</code>
         * chunk in bytes is less than that of <code>comparand</code></li>
         * <li>Zero, otherwise.</li>
         * </ul> 
         */
        public int compareTo(Object comparand) {
            return getChunkSize() - ((Chunk)comparand).getChunkSize();
        }
    }

    /**
     * Find the outlineable chunks in this method that would be the best choices
     * to outline, based on size and position in the method.
     * @param classGen The {@link ClassGen} with which the generated methods
     *                 will be associated 
     * @param totalMethodSize the size of the bytecode in the original method
     * @return a <code>java.util.ArrayList</code> containing the
     *  {@link MethodGenerator.Chunk}s that may be outlined from this method
     */
    private ArrayList getCandidateChunks(ClassGenerator classGen,
                                         int totalMethodSize) {
        Iterator instructions = getInstructionList().iterator();
        ArrayList candidateChunks = new ArrayList();
        ArrayList currLevelChunks = new ArrayList();
        Stack subChunkStack = new Stack();
        boolean openChunkAtCurrLevel = false;
        boolean firstInstruction = true;

        InstructionHandle currentHandle;

        if (m_openChunks != 0) {
            String msg =
                (new ErrorMsg(ErrorMsg.OUTLINE_ERR_UNBALANCED_MARKERS))
                    .toString();
            throw new InternalError(msg);
        }

        // Scan instructions in the method, keeping track of the nesting level
        // of outlineable chunks.
        //
        // currLevelChunks 
        //     keeps track of the child chunks of a chunk.  For each chunk,
        //     there will be a pair of entries:  the InstructionHandles for the
        //     start and for the end of the chunk
        // subChunkStack
        //     a stack containing the partially accumulated currLevelChunks for
        //     each chunk that's still open at the current position in the
        //     InstructionList.
        // candidateChunks
        //     the list of chunks which have been accepted as candidates chunks
        //     for outlining
        do {
            // Get the next instruction.  The loop will perform one extra
            // iteration after it reaches the end of the InstructionList, with
            // currentHandle set to null.
            currentHandle = instructions.hasNext()
                                    ? (InstructionHandle) instructions.next()
                                    : null;
            Instruction inst =
                    (currentHandle != null) ? currentHandle.getInstruction()
                                            : null;

            // At the first iteration, create a chunk representing all the
            // code in the method.  This is done just to simplify the logic -
            // this chunk can never be outlined because it will be too big.
            if (firstInstruction) {
                openChunkAtCurrLevel = true;
                currLevelChunks.add(currentHandle);
                firstInstruction = false;
            }

            // Found a new chunk
            if (inst instanceof OutlineableChunkStart) {
                // If last MarkerInstruction encountered was an
                // OutlineableChunkStart, this represents the first chunk
                // nested within that previous chunk - push the list of chunks
                // from the outer level onto the stack
                if (openChunkAtCurrLevel) {
                    subChunkStack.push(currLevelChunks);
                    currLevelChunks = new ArrayList();
                }

                openChunkAtCurrLevel = true;
                currLevelChunks.add(currentHandle);
            // Close off an open chunk
            } else if (currentHandle == null
                           || inst instanceof OutlineableChunkEnd) {
                ArrayList nestedSubChunks = null;

                // If the last MarkerInstruction encountered was an
                // OutlineableChunkEnd, it means that the current instruction
                // marks the end of a chunk that contained child chunks.
                // Those children might need to be examined below in case they
                // are better candidates for outlining than the current chunk.
                if (!openChunkAtCurrLevel) {
                    nestedSubChunks = currLevelChunks;
                    currLevelChunks = (ArrayList)subChunkStack.pop();
                }

                // Get the handle for the start of this chunk (the last entry
                // in currLevelChunks)
                InstructionHandle chunkStart =
                        (InstructionHandle) currLevelChunks.get(
                                                      currLevelChunks.size()-1);

                int chunkEndPosition =
                        (currentHandle != null) ? currentHandle.getPosition()
                                                : totalMethodSize;
                int chunkSize = chunkEndPosition - chunkStart.getPosition();

                // Two ranges of chunk size to consider:
                //
                // 1. [0,TARGET_METHOD_SIZE]
                //      Keep this chunk in consideration as a candidate,
                //      and ignore its subchunks, if any - there's nothing to be
                //      gained by outlining both the current chunk and its
                //      children!
                //
                // 2. (TARGET_METHOD_SIZE,+infinity)
                //      Ignore this chunk - it's too big.  Add its subchunks
                //      as candidates, after merging adjacent chunks to produce
                //      chunks that are as large as possible
                if (chunkSize <= TARGET_METHOD_SIZE) {
                    currLevelChunks.add(currentHandle);
                } else {
                    if (!openChunkAtCurrLevel) {
                        int childChunkCount = nestedSubChunks.size() / 2;
                        if (childChunkCount > 0) {
                            Chunk[] childChunks = new Chunk[childChunkCount];

                            // Gather all the child chunks of the current chunk
                            for (int i = 0; i < childChunkCount; i++) {
                                InstructionHandle start =
                                    (InstructionHandle) nestedSubChunks
                                                            .get(i*2);
                                InstructionHandle end =
                                    (InstructionHandle) nestedSubChunks
                                                            .get(i*2+1);

                                childChunks[i] = new Chunk(start, end);
                            }

                            // Merge adjacent siblings
                            ArrayList mergedChildChunks =
                                        mergeAdjacentChunks(childChunks);

                            // Add chunks that mean minimum size requirements
                            // to the list of candidate chunks for outlining
                            for (int i = 0; i < mergedChildChunks.size(); i++) {
                                Chunk mergedChunk =
                                    (Chunk)mergedChildChunks.get(i);
                                int mergedSize = mergedChunk.getChunkSize();

                                if (mergedSize >= MINIMUM_OUTLINEABLE_CHUNK_SIZE
                                        && mergedSize <= TARGET_METHOD_SIZE) {
                                    candidateChunks.add(mergedChunk);
                                }
                            }
                        }
                    }

                    // Drop the chunk which was too big
                    currLevelChunks.remove(currLevelChunks.size() - 1);
                }

                // currLevelChunks contains pairs of InstructionHandles.  If
                // its size is an odd number, the loop has encountered the
                // start of a chunk at this level, but not its end.
                openChunkAtCurrLevel = ((currLevelChunks.size() & 0x1) == 1);
            }

        } while (currentHandle != null);

        return candidateChunks;
    }

    /**
     * Merge adjacent sibling chunks to produce larger candidate chunks for
     * outlining
     * @param chunks array of sibling {@link MethodGenerator.Chunk}s that are
     *               under consideration for outlining.  Chunks must be in
     *               the order encountered in the {@link InstructionList}
     * @return a <code>java.util.ArrayList</code> of
     *         <code>MethodGenerator.Chunk</code>s maximally merged 
     */
    private ArrayList mergeAdjacentChunks(Chunk[] chunks) {
        int[] adjacencyRunStart = new int[chunks.length];
        int[] adjacencyRunLength = new int[chunks.length];
        boolean[] chunkWasMerged = new boolean[chunks.length];

        int maximumRunOfChunks = 0;
        int startOfCurrentRun;
        int numAdjacentRuns = 0;

        ArrayList mergedChunks = new ArrayList();

        startOfCurrentRun = 0;

        // Loop through chunks, and record in adjacencyRunStart where each
        // run of adjacent chunks begins and how many are in that run.  For
        // example, given chunks A B C D E F, if A is adjacent to B, but not
        // to C, and C, D, E and F are all adjacent,
        //   adjacencyRunStart[0] == 0; adjacencyRunLength[0] == 2
        //   adjacencyRunStart[1] == 2; adjacencyRunLength[1] == 4
        for (int i = 1; i < chunks.length; i++) {
            if (!chunks[i-1].isAdjacentTo(chunks[i])) {
                int lengthOfRun = i - startOfCurrentRun;

                // Track the longest run of chunks found
                if (maximumRunOfChunks < lengthOfRun) {
                    maximumRunOfChunks = lengthOfRun;
                }

                if (lengthOfRun > 1 ) {
                    adjacencyRunLength[numAdjacentRuns] = lengthOfRun;
                    adjacencyRunStart[numAdjacentRuns] = startOfCurrentRun;
                    numAdjacentRuns++;
                }

                startOfCurrentRun = i;
            }
        }

        if (chunks.length - startOfCurrentRun > 1) {
            int lengthOfRun = chunks.length - startOfCurrentRun;

            // Track the longest run of chunks found
            if (maximumRunOfChunks < lengthOfRun) {
                maximumRunOfChunks = lengthOfRun;
            }

            adjacencyRunLength[numAdjacentRuns] =
                        chunks.length - startOfCurrentRun;
            adjacencyRunStart[numAdjacentRuns] = startOfCurrentRun;
            numAdjacentRuns++;
        }

        // Try merging adjacent chunks to come up with better sized chunks for
        // outlining.  This algorithm is not optimal, but it should be
        // reasonably fast.  Consider an example like this, where four chunks
        // of the sizes specified in brackets are adjacent.  The best way of
        // combining these chunks would be to merge the first pair and merge
        // the last three to form two chunks, but the algorithm will merge the
        // three in the middle instead, leaving three chunks in all.
        //    [25000] [25000] [20000] [1000] [20000]

        // Start by trying to merge the maximum number of adjacent chunks, and
        // work down from there.
        for (int numToMerge = maximumRunOfChunks; numToMerge>1; numToMerge--) {
            // Look at each run of adjacent chunks
            for (int run = 0; run < numAdjacentRuns; run++) {
                int runStart = adjacencyRunStart[run];
                int runEnd = runStart + adjacencyRunLength[run] - 1;

                boolean foundChunksToMerge = false;

                // Within the current run of adjacent chunks, look at all
                // "subruns" of length numToMerge, until we run out or find
                // a subrun that can be merged.
                for (int mergeStart = runStart;
                     mergeStart+numToMerge-1 <= runEnd && !foundChunksToMerge; 
                     mergeStart++) {
                    int mergeEnd = mergeStart + numToMerge - 1;
                    int mergeSize = 0;

                    // Find out how big the subrun is
                    for (int j = mergeStart; j <= mergeEnd; j++) {
                        mergeSize = mergeSize + chunks[j].getChunkSize();
                    }

                    // If the current subrun is small enough to outline,
                    // merge it, and split the remaining chunks in the run
                    if (mergeSize <= TARGET_METHOD_SIZE) {
                        foundChunksToMerge = true;

                        for (int j = mergeStart; j <= mergeEnd; j++) {
                            chunkWasMerged[j] = true;
                        }

                        mergedChunks.add(
                                new Chunk(chunks[mergeStart].getChunkStart(),
                                          chunks[mergeEnd].getChunkEnd()));

                        // Adjust the length of the current run of adjacent
                        // chunks to end at the newly merged chunk...
                        adjacencyRunLength[run] =
                                adjacencyRunStart[run] - mergeStart;

                        int trailingRunLength = runEnd - mergeEnd;

                        // and any chunks that follow the newly merged chunk
                        // in the current run of adjacent chunks form another
                        // new run of adjacent chunks
                        if (trailingRunLength >= 2) {
                            adjacencyRunStart[numAdjacentRuns] = mergeEnd + 1;
                            adjacencyRunLength[numAdjacentRuns] =
                                                            trailingRunLength;
                            numAdjacentRuns++;
                        }
                    }
                }
            }
        }

        // Make a final pass for any chunk that wasn't merged with a sibling
        // and include it in the list of chunks after merging.
        for (int i = 0; i < chunks.length; i++) {
            if (!chunkWasMerged[i]) {
                mergedChunks.add(chunks[i]);
            }
        }

        return mergedChunks;
    }

    /**
     * Breaks up the IL for this {@link MethodGenerator} into separate
     * outlined methods so that no method exceeds the 64KB limit on the length
     * of the byte code associated with a method. 
     * @param classGen The {@link ClassGen} with which the generated methods
     *                 will be associated
     * @param originalMethodSize The number of bytes of bytecode represented by
     *                 the {@link InstructionList} of this method
     * @return an array of the outlined <code>Method</code>s and the original
     *         method itself
     */
    public Method[] outlineChunks(ClassGenerator classGen,
                                  int originalMethodSize) {
        ArrayList methodsOutlined = new ArrayList();
        int currentMethodSize = originalMethodSize;

        int outlinedCount = 0;
        boolean moreMethodsOutlined;
        String originalMethodName = getName();

        // Special handling for initialization methods.  No other methods can
        // include the less than and greater than characters in their names,
        // so we munge the names here.
        if (originalMethodName.equals("<init>")) {
            originalMethodName = "$lt$init$gt$";
        } else if (originalMethodName.equals("<clinit>")) {
            originalMethodName = "$lt$clinit$gt$";
        }

        // Loop until the original method comes in under the JVM limit or
        // the loop was unable to outline any more methods
        do {
            // Get all the best candidates for outlining, and sort them in
            // ascending order of size
            ArrayList candidateChunks = getCandidateChunks(classGen,
                                                           currentMethodSize);
            Collections.sort(candidateChunks);

            moreMethodsOutlined = false;

            // Loop over the candidates for outlining, from the largest to the
            // smallest and outline them one at a time, until the loop has
            // outlined all or the original method comes in under the JVM
            // limit on the size of a method.
            for (int i = candidateChunks.size()-1;
                 i >= 0 && currentMethodSize > TARGET_METHOD_SIZE;
                 i--) {
                Chunk chunkToOutline = (Chunk)candidateChunks.get(i);

                methodsOutlined.add(outline(chunkToOutline.getChunkStart(),
                                            chunkToOutline.getChunkEnd(),
                                            originalMethodName + "$outline$"
                                                               + outlinedCount,
                                            classGen));
                outlinedCount++;
                moreMethodsOutlined = true;

                InstructionList il = getInstructionList();
                InstructionHandle lastInst = il.getEnd();
                il.setPositions();

                // Check the size of the method now
                currentMethodSize =
                        lastInst.getPosition()
                                + lastInst.getInstruction().getLength();
            }
        } while (moreMethodsOutlined && currentMethodSize > TARGET_METHOD_SIZE);

        // Outlining failed to reduce the size of the current method
        // sufficiently.  Throw an internal error.
        if (currentMethodSize > MAX_METHOD_SIZE) {
            String msg = (new ErrorMsg(ErrorMsg.OUTLINE_ERR_METHOD_TOO_BIG))
                                  .toString();
            throw new InternalError(msg);
        }

        Method[] methodsArr = new Method[methodsOutlined.size() + 1];
        methodsOutlined.toArray(methodsArr);

        methodsArr[methodsOutlined.size()] = getThisMethod();

        return methodsArr;
    }

    /**
     * Given an outlineable chunk of code in the current {@link MethodGenerator}
     * move ("outline") the chunk to a new method, and replace the chunk in the
     * old method with a reference to that new method.  No
     * {@link OutlineableChunkStart} or {@link OutlineableChunkEnd} instructions
     * are copied.
     * @param first The {@link InstructionHandle} of the first instruction in
     *              the chunk to outline
     * @param last The <code>InstructionHandle</code> of the last instruction in
     *             the chunk to outline
     * @param outlinedMethodName The name of the new method
     * @param classGen The {@link ClassGenerator} of which the original
     *              and new methods will be members
     * @return The new {@link Method} containing the outlined code.
     */
    private Method outline(InstructionHandle first, InstructionHandle last,
                           String outlinedMethodName, ClassGenerator classGen) {
        // We're not equipped to deal with exception handlers yet.  Bail out!
        if (getExceptionHandlers().length != 0) {
            String msg = (new ErrorMsg(ErrorMsg.OUTLINE_ERR_TRY_CATCH))
                                  .toString();
            throw new InternalError(msg);
        }

        int outlineChunkStartOffset = first.getPosition();
        int outlineChunkEndOffset = last.getPosition()
                                        + last.getInstruction().getLength();

        ConstantPoolGen cpg = getConstantPool();

        // Create new outlined method with signature:
        //
        //   private final outlinedMethodName(CopyLocals copyLocals);
        //
        // CopyLocals is an object that is used to copy-in/copy-out local
        // variables that are used by the outlined method.   Only locals whose
        // value is potentially set or referenced outside the range of the
        // chunk that is being outlined will be represented in CopyLocals.  The
        // type of the variable for copying local variables is actually
        // generated to be unique - it is not named CopyLocals.
        //
        // The outlined method never needs to be referenced outside of this
        // class, and will never be overridden, so we mark it private final.
        final InstructionList newIL = new InstructionList();

        final XSLTC  xsltc = classGen.getParser().getXSLTC();
        final String argTypeName = xsltc.getHelperClassName();
        final Type[] argTypes =
            new Type[] {(new ObjectType(argTypeName)).toJCType()};
        final String argName = "copyLocals";
        final String[] argNames = new String[] {argName};

        int methodAttributes = ACC_PRIVATE | ACC_FINAL;
        final boolean isStaticMethod = (getAccessFlags() & ACC_STATIC) != 0;

        if (isStaticMethod) {
            methodAttributes = methodAttributes | ACC_STATIC;
        }

        final MethodGenerator outlinedMethodGen =
            new MethodGenerator(methodAttributes,
                                org.apache.bcel.generic.Type.VOID,
                                argTypes, argNames, outlinedMethodName,
                                getClassName(), newIL, cpg);

        // Create class for copying local variables to the outlined method.
        // The fields the class will need to contain will be determined as the
        // code in the outlineable chunk is examined.
        ClassGenerator copyAreaCG
            = new ClassGenerator(argTypeName, OBJECT_CLASS, argTypeName+".java",
                                 ACC_FINAL | ACC_PUBLIC | ACC_SUPER, null,
                                 classGen.getStylesheet()) {
                      public boolean isExternal() {
                          return true;
                      }
                  };
        ConstantPoolGen copyAreaCPG = copyAreaCG.getConstantPool();
        copyAreaCG.addEmptyConstructor(ACC_PUBLIC);

        // Number of fields in the copy class
        int copyAreaFieldCount = 0;

        // The handle for the instruction after the last one to be outlined.
        // Note that this should never end up being null.  An outlineable chunk
        // won't contain a RETURN instruction or other branch out of the chunk,
        // and the JVM specification prohibits code in a method from just
        // "falling off the end" so this should always point to a valid handle.
        InstructionHandle limit = last.getNext();

        // InstructionLists for copying values into and out of an instance of
        // CopyLocals:
        //      oldMethCoypInIL  - from locals in old method into an instance
        //                         of the CopyLocals class (oldMethCopyInIL)
        //      oldMethCopyOutIL - from CopyLocals back into locals in the old
        //                         method
        //      newMethCopyInIL  - from CopyLocals into locals in the new
        //                         method
        //      newMethCopyOutIL - from locals in new method into the instance
        //                         of the CopyLocals class
        InstructionList oldMethCopyInIL  = new InstructionList();
        InstructionList oldMethCopyOutIL = new InstructionList();
        InstructionList newMethCopyInIL  = new InstructionList();
        InstructionList newMethCopyOutIL = new InstructionList();

        // Allocate instance of class in which we'll copy in or copy out locals
        // and make two copies:  last copy is used to invoke constructor;
        // other two are used for references to fields in the CopyLocals object
        InstructionHandle outlinedMethodCallSetup =
            oldMethCopyInIL.append(new NEW(cpg.addClass(argTypeName)));
        oldMethCopyInIL.append(InstructionConstants.DUP);
        oldMethCopyInIL.append(InstructionConstants.DUP);
        oldMethCopyInIL.append(
            new INVOKESPECIAL(cpg.addMethodref(argTypeName, "<init>", "()V")));

        // Generate code to invoke the new outlined method, and place the code
        // on oldMethCopyOutIL
        InstructionHandle outlinedMethodRef;

        if (isStaticMethod) {
            outlinedMethodRef =
                oldMethCopyOutIL.append(
                    new INVOKESTATIC(cpg.addMethodref(
                                          classGen.getClassName(),
                                          outlinedMethodName,
                                          outlinedMethodGen.getSignature())));
        } else {
            oldMethCopyOutIL.append(InstructionConstants.THIS);
            oldMethCopyOutIL.append(InstructionConstants.SWAP);
            outlinedMethodRef =
                oldMethCopyOutIL.append(
                    new INVOKEVIRTUAL(cpg.addMethodref(
                                          classGen.getClassName(),
                                          outlinedMethodName,
                                          outlinedMethodGen.getSignature())));
        }

        // Used to keep track of the first in a sequence of
        // OutlineableChunkStart instructions
        boolean chunkStartTargetMappingsPending = false;
        InstructionHandle pendingTargetMappingHandle = null;

        // Used to keep track of the last instruction that was copied
        InstructionHandle lastCopyHandle = null;

        // Keeps track of the mapping from instruction handles in the old
        // method to instruction handles in the outlined method.  Only need
        // to track instructions that are targeted by something else in the
        // generated BCEL 
        HashMap targetMap   = new HashMap();

        // Keeps track of the mapping from local variables in the old method
        // to local variables in the outlined method.
        HashMap localVarMap = new HashMap();

        HashMap revisedLocalVarStart = new HashMap();
        HashMap revisedLocalVarEnd = new HashMap();

        // Pass 1: Make copies of all instructions, append them to the new list
        // and associate old instruction references with the new ones, i.e.,
        // a 1:1 mapping.  The special marker instructions are not copied.
        // Also, identify local variables whose values need to be copied into or
        // out of the new outlined method, and builds up targetMap and
        // localVarMap as described above.  The code identifies those local
        // variables first so that they can have fixed slots in the stack
        // frame for the outlined method assigned them ahead of all those
        // variables that don't need to exist for the entirety of the outlined
        // method invocation.
        for (InstructionHandle ih = first; ih != limit; ih = ih.getNext()) {
            Instruction inst = ih.getInstruction();

            // MarkerInstructions are not copied, so if something else targets
            // one, the targetMap will point to the nearest copied sibling
            // InstructionHandle:  for an OutlineableChunkEnd, the nearest
            // preceding sibling; for an OutlineableChunkStart, the nearest
            // following sibling.
            if (inst instanceof MarkerInstruction) {
                if (ih.hasTargeters()) {
                    if (inst instanceof OutlineableChunkEnd) {
                        targetMap.put(ih, lastCopyHandle);
                    } else {
                        if (!chunkStartTargetMappingsPending)  {
                            chunkStartTargetMappingsPending = true;
                            pendingTargetMappingHandle = ih;
                        }
                    }
                }
            } else {
                // Copy the instruction and append it to the outlined method's
                // InstructionList.
                Instruction c = inst.copy(); // Use clone for shallow copy

                if (c instanceof BranchInstruction) {
                    lastCopyHandle = newIL.append((BranchInstruction)c);
                } else {
                    lastCopyHandle = newIL.append(c);
                }

                if (c instanceof LocalVariableInstruction
                        || c instanceof RET) {
                    // For any instruction that touches a local variable,
                    // check whether the local variable's value needs to be
                    // copied into or out of the outlined method.  If so,
                    // generate the code to perform the necessary copying, and 
                    // use localVarMap to map the variable in the original
                    // method to the variable in the new method.
                    IndexedInstruction lvi = (IndexedInstruction)c;
                    int oldLocalVarIndex = lvi.getIndex();
                    LocalVariableGen oldLVG =
                            getLocalVariableRegistry()
                                .lookupRegisteredLocalVariable(oldLocalVarIndex,
                                                              ih.getPosition());
                    LocalVariableGen newLVG =
                            (LocalVariableGen)localVarMap.get(oldLVG);

                    // Has the code already mapped this local variable to a
                    // local in the new method?
                    if (localVarMap.get(oldLVG) == null) {
                        // Determine whether the local variable needs to be
                        // copied into or out of the outlined by checking
                        // whether the range of instructions in which the
                        // variable is accessible is outside the range of
                        // instructions in the outlineable chunk.
                        // Special case a chunk start offset of zero:  a local
                        // variable live at that position must be a method
                        // parameter, so the code doesn't need to check whether
                        // the variable is live before that point; being live
                        // at offset zero is sufficient to know that the value
                        // must be copied in to the outlined method.
                        boolean copyInLocalValue =
                            offsetInLocalVariableGenRange(oldLVG,
                                                (outlineChunkStartOffset != 0)
                                                    ? outlineChunkStartOffset-1
                                                    : 0);
                        boolean copyOutLocalValue =
                            offsetInLocalVariableGenRange(oldLVG,
                                                outlineChunkEndOffset+1);

                        // For any variable that needs to be copied into or out
                        // of the outlined method, create a field in the
                        // CopyLocals class, and generate the necessary code for
                        // copying the value.
                        if (copyInLocalValue || copyOutLocalValue) {
                            String varName = oldLVG.getName();
                            Type varType = oldLVG.getType();
                            newLVG = outlinedMethodGen.addLocalVariable(varName,
                                                                        varType,
                                                                        null,
                                                                        null);
                            int newLocalVarIndex = newLVG.getIndex();
                            String varSignature = varType.getSignature();

                            // Record the mapping from the old local to the new
                            localVarMap.put(oldLVG, newLVG);

                            copyAreaFieldCount++;
                            String copyAreaFieldName =
                                           "field" + copyAreaFieldCount;
                            copyAreaCG.addField(
                                new Field(ACC_PUBLIC,
                                        copyAreaCPG.addUtf8(copyAreaFieldName),
                                        copyAreaCPG.addUtf8(varSignature),
                                        null, copyAreaCPG.getConstantPool()));

                            int fieldRef = cpg.addFieldref(argTypeName,
                                                           copyAreaFieldName,
                                                           varSignature);

                            if (copyInLocalValue) {
                                // Generate code for the old method to store the
                                // value of the local into the correct field in
                                // CopyLocals prior to invocation of the
                                // outlined method.
                                oldMethCopyInIL.append(
                                        InstructionConstants.DUP);
                                InstructionHandle copyInLoad =
                                    oldMethCopyInIL.append(
                                        loadLocal(oldLocalVarIndex, varType));
                                oldMethCopyInIL.append(new PUTFIELD(fieldRef));

                                // If the end of the live range of the old
                                // variable was in the middle of the outlined
                                // chunk.  Make the load of its value the new
                                // end of its range.
                                if (!copyOutLocalValue) {
                                    revisedLocalVarEnd.put(oldLVG, copyInLoad);
                                }

                                // Generate code for start of the outlined
                                // method to copy the value from a field in
                                // CopyLocals to the new local in the outlined
                                // method
                                newMethCopyInIL.append(
                                        InstructionConstants.ALOAD_1);
                                newMethCopyInIL.append(new GETFIELD(fieldRef));
                                newMethCopyInIL.append(
                                        storeLocal(newLocalVarIndex, varType));
                            }

                            if (copyOutLocalValue) {
                                // Generate code for the end of the outlined
                                // method to copy the value from the new local
                                // variable into a field in CopyLocals
                                // method
                                newMethCopyOutIL.append(
                                        InstructionConstants.ALOAD_1);
                                newMethCopyOutIL.append(
                                        loadLocal(newLocalVarIndex, varType));
                                newMethCopyOutIL.append(new PUTFIELD(fieldRef));

                                // Generate code to copy the value from a field
                                // in CopyLocals into a local in the original
                                // method following invocation of the outlined
                                // method.
                                oldMethCopyOutIL.append(
                                        InstructionConstants.DUP);
                                oldMethCopyOutIL.append(new GETFIELD(fieldRef));
                                InstructionHandle copyOutStore =
                                    oldMethCopyOutIL.append(
                                        storeLocal(oldLocalVarIndex, varType));

                                // If the start of the live range of the old
                                // variable was in the middle of the outlined
                                // chunk.  Make this store into it the new start
                                // of its range.
                                if (!copyInLocalValue) {
                                    revisedLocalVarStart.put(oldLVG,
                                                             copyOutStore); 
                                }
                            }
                        }
                    }
                }

                if (ih.hasTargeters()) {
                    targetMap.put(ih, lastCopyHandle);
                }

                // If this is the first instruction copied following a sequence
                // of OutlineableChunkStart instructions, indicate that the
                // sequence of old instruction all map to this newly created
                // instruction
                if (chunkStartTargetMappingsPending) {
                    do {
                         targetMap.put(pendingTargetMappingHandle,
                                       lastCopyHandle);
                         pendingTargetMappingHandle =
                                 pendingTargetMappingHandle.getNext();
                    } while(pendingTargetMappingHandle != ih);

                    chunkStartTargetMappingsPending = false;
                }
            }
        }

        // Pass 2: Walk old and new instruction lists, updating branch targets
        // and local variable references in the new list
        InstructionHandle ih = first;
        InstructionHandle ch = newIL.getStart();

        while (ch != null) {
            // i == old instruction; c == copied instruction
            Instruction i = ih.getInstruction();
            Instruction c = ch.getInstruction();

            if (i instanceof BranchInstruction) {
                BranchInstruction bc      = (BranchInstruction)c;
                BranchInstruction bi      = (BranchInstruction)i;
                InstructionHandle itarget = bi.getTarget(); // old target

                // New target must be in targetMap
                InstructionHandle newTarget =
                    (InstructionHandle)targetMap.get(itarget);

                bc.setTarget(newTarget);

                // Handle LOOKUPSWITCH or TABLESWITCH which may have many
                // target instructions
                if (bi instanceof Select) {
                    InstructionHandle[] itargets = ((Select)bi).getTargets();
                    InstructionHandle[] ctargets = ((Select)bc).getTargets();

                    // Update all targets
                    for (int j=0; j < itargets.length; j++) {
                        ctargets[j] =
                            (InstructionHandle)targetMap.get(itargets[j]);
                    }
                }
            }  else if (i instanceof LocalVariableInstruction
                            || i instanceof RET) {
                // For any instruction that touches a local variable,
                // map the location of the variable in the original
                // method to its location in the new method.
                IndexedInstruction lvi = (IndexedInstruction)c;
                int oldLocalVarIndex = lvi.getIndex();
                LocalVariableGen oldLVG =
                        getLocalVariableRegistry()
                                .lookupRegisteredLocalVariable(oldLocalVarIndex,
                                                              ih.getPosition());
                LocalVariableGen newLVG =
                        (LocalVariableGen)localVarMap.get(oldLVG);
                int newLocalVarIndex;

                if (newLVG == null) {
                    // Create new variable based on old variable - use same
                    // name and type, but we will let the variable be active
                    // for the entire outlined method.
                    // LocalVariableGen oldLocal = oldLocals[oldLocalVarIndex];
                    String varName = oldLVG.getName();
                    Type varType = oldLVG.getType();
                    newLVG = outlinedMethodGen.addLocalVariable(varName,
                                                                varType,
                                                                null,
                                                                null);
                    newLocalVarIndex = newLVG.getIndex();
                    localVarMap.put(oldLVG, newLVG);

                    // The old variable's live range was wholly contained in
                    // the outlined chunk.  There should no longer be stores
                    // of values into it or loads of its value, so we can just
                    // mark its live range as the reference to the outlined
                    // method.
                    revisedLocalVarStart.put(oldLVG, outlinedMethodRef);
                    revisedLocalVarEnd.put(oldLVG, outlinedMethodRef);
                } else {
                    newLocalVarIndex = newLVG.getIndex();
                }
                lvi.setIndex(newLocalVarIndex);
            }

            // If the old instruction marks the end of the range of a local
            // variable, make sure that any slots on the stack reserved for
            // local variables are made available for reuse by calling
            // MethodGenerator.removeLocalVariable
            if (ih.hasTargeters()) {
                InstructionTargeter[] targeters = ih.getTargeters();

                for (int idx = 0; idx < targeters.length; idx++) {
                    InstructionTargeter targeter = targeters[idx];

                    if (targeter instanceof LocalVariableGen
                            && ((LocalVariableGen)targeter).getEnd()==ih) {
                        Object newLVG = localVarMap.get(targeter);
                        if (newLVG != null) {
                            outlinedMethodGen.removeLocalVariable(
                                                  (LocalVariableGen)newLVG);
                        }
                    }
                }
            }

            // If the current instruction in the original list was a marker,
            // it wasn't copied, so don't advance through the list of copied
            // instructions yet.
            if (!(i instanceof MarkerInstruction)) {
                ch = ch.getNext();
            }
            ih = ih.getNext();

        }

        // POP the reference to the CopyLocals object from the stack
        oldMethCopyOutIL.append(InstructionConstants.POP);

        // Now that the generation of the outlined code is complete, update
        // the old local variables with new start and end ranges, as required.
        Iterator revisedLocalVarStartPairIter = revisedLocalVarStart.entrySet()
                                                                    .iterator();
        while (revisedLocalVarStartPairIter.hasNext()) {
            Map.Entry lvgRangeStartPair =
                    (Map.Entry)revisedLocalVarStartPairIter.next();
            LocalVariableGen lvg = (LocalVariableGen)lvgRangeStartPair.getKey();
            InstructionHandle startInst =
                    (InstructionHandle)lvgRangeStartPair.getValue();

            lvg.setStart(startInst);
            
        }

        Iterator revisedLocalVarEndPairIter = revisedLocalVarEnd.entrySet()
                                                                .iterator();
        while (revisedLocalVarEndPairIter.hasNext()) {
            Map.Entry lvgRangeEndPair =
                    (Map.Entry)revisedLocalVarEndPairIter.next();
            LocalVariableGen lvg = (LocalVariableGen)lvgRangeEndPair.getKey();
            InstructionHandle endInst =
                    (InstructionHandle)lvgRangeEndPair.getValue();

            lvg.setEnd(endInst);
        }

        xsltc.dumpClass(copyAreaCG.getJavaClass());

        // Assemble the instruction lists so that the old method invokes the
        // new outlined method
        InstructionList oldMethodIL = getInstructionList();

        oldMethodIL.insert(first, oldMethCopyInIL);
        oldMethodIL.insert(first, oldMethCopyOutIL);

        // Insert the copying code into the outlined method
        newIL.insert(newMethCopyInIL);
        newIL.append(newMethCopyOutIL);
        newIL.append(InstructionConstants.RETURN);

        // Discard instructions in outlineable chunk from old method
        try {
            oldMethodIL.delete(first, last);
        } catch (TargetLostException e) {
            InstructionHandle[] targets = e.getTargets();
            // If there were still references to old instructions lingering,
            // clean those up.  The only instructions targetting the deleted
            // instructions should have been part of the chunk that was just
            // deleted, except that instructions might branch to the start of
            // the outlined chunk; similarly, all the live ranges of local
            // variables should have been adjusted, except for unreferenced
            // variables.
            for (int i = 0; i < targets.length; i++) {
                InstructionHandle lostTarget = targets[i];
                InstructionTargeter[] targeters = lostTarget.getTargeters();
                for (int j = 0; j < targeters.length; j++) {
                    if (targeters[j] instanceof LocalVariableGen) {
                        LocalVariableGen lvgTargeter =
                                             (LocalVariableGen) targeters[j];
                        // In the case of any lingering variable references,
                        // just make the live range point to the outlined
                        // function reference.  Such variables should be unused
                        // anyway.
                        if (lvgTargeter.getStart() == lostTarget) {
                            lvgTargeter.setStart(outlinedMethodRef);
                        }
                        if (lvgTargeter.getEnd() == lostTarget) {
                            lvgTargeter.setEnd(outlinedMethodRef);
                        }
                    } else {
                        targeters[j].updateTarget(lostTarget,
                                                  outlinedMethodCallSetup);
                    }
                }
            }
        }

        // Make a copy for the new method of all exceptions that might be thrown
        String[] exceptions = getExceptions();
        for (int i = 0; i < exceptions.length; i++) {
            outlinedMethodGen.addException(exceptions[i]);
        }

        return outlinedMethodGen.getThisMethod();
    }

    /**
     * Helper method to generate an instance of a subclass of
     * {@link LoadInstruction} based on the specified {@link Type} that will
     * load the specified local variable
     * @param index the JVM stack frame index of the variable that is to be
     * loaded
     * @param type the {@link Type} of the variable
     * @return the generated {@link LoadInstruction}
     */
    private static Instruction loadLocal(int index, Type type) {
        if (type == Type.BOOLEAN) {
           return new ILOAD(index);
        } else if (type == Type.INT) {
           return new ILOAD(index);
        } else if (type == Type.SHORT) {
           return new ILOAD(index);
        } else if (type == Type.LONG) {
           return new LLOAD(index);
        } else if (type == Type.BYTE) {
           return new ILOAD(index);
        } else if (type == Type.CHAR) {
           return new ILOAD(index);
        } else if (type == Type.FLOAT) {
           return new FLOAD(index);
        } else if (type == Type.DOUBLE) {
           return new DLOAD(index);
        } else {
           return new ALOAD(index);
        }
    }

    /**
     * Helper method to generate an instance of a subclass of
     * {@link StoreInstruction} based on the specified {@link Type} that will
     * store a value in the specified local variable
     * @param index the JVM stack frame index of the variable that is to be
     * stored
     * @param type the {@link Type} of the variable
     * @return the generated {@link StoredInstruction}
     */
    private static Instruction storeLocal(int index, Type type) {
        if (type == Type.BOOLEAN) {
           return new ISTORE(index);
        } else if (type == Type.INT) {
           return new ISTORE(index);
        } else if (type == Type.SHORT) {
           return new ISTORE(index);
        } else if (type == Type.LONG) {
           return new LSTORE(index);
        } else if (type == Type.BYTE) {
           return new ISTORE(index);
        } else if (type == Type.CHAR) {
           return new ISTORE(index);
        } else if (type == Type.FLOAT) {
           return new FSTORE(index);
        } else if (type == Type.DOUBLE) {
           return new DSTORE(index);
        } else {
           return new ASTORE(index);
        }
    }

    /**
     * Track the number of outlineable chunks seen.
     */
    private int m_totalChunks = 0;

    /**
     * Track the number of outlineable chunks started but not yet ended.  Used
     * to detect imbalances in byte code generation.
     */
    private int m_openChunks = 0;

    /**
     * Mark the end of the method's
     * {@link InstructionList} as the start of an outlineable chunk of code.
     * The outlineable chunk begins after the {@link InstructionHandle} that is
     * at the end of the method's {@link InstructionList}, or at the start of
     * the method if the <code>InstructionList</code> is empty.
     * See {@link OutlineableChunkStart} for more information.
     */
    public void markChunkStart() {
        // m_chunkTree.markChunkStart();
        getInstructionList()
                .append(OutlineableChunkStart.OUTLINEABLECHUNKSTART);
        m_totalChunks++;
        m_openChunks++;
    }

    /**
     * Mark the end of an outlineable chunk of code.  See
     * {@link OutlineableChunkStart} for more information.
     */
    public void markChunkEnd() {
        // m_chunkTree.markChunkEnd();
        getInstructionList()
                .append(OutlineableChunkEnd.OUTLINEABLECHUNKEND);
        m_openChunks--;
        if (m_openChunks < 0) {
            String msg = (new ErrorMsg(ErrorMsg.OUTLINE_ERR_UNBALANCED_MARKERS))
                                 .toString();
            throw new InternalError(msg);
        }
    }

    /**
     * <p>Get all {@link Method}s generated by this {@link MethodGenerator}.
     * The {@link MethodGen#getMethod()} only returns a single
     * <code>Method</code> object.  This method takes into account the Java
     * Virtual Machine Specification limit of 64KB on the size of a method, and
     * may return more than one <code>Method</code>.</p>
     * <p>If the code associated with the <code>MethodGenerator</code> would
     * exceed the 64KB limit, this method will attempt to split the code in
     * the {@link InstructionList} associated with this
     * <code>MethodGenerator</code> into several methods.</p>  
     * @param classGen the {@link ClassGenerator} of which these methods are
     *                 members
     * @return an array of all the <code>Method</code>s generated
     */
    Method[] getGeneratedMethods(ClassGenerator classGen) {
        Method[] generatedMethods;
        InstructionList il = getInstructionList();
        InstructionHandle last = il.getEnd();

        il.setPositions();

        int instructionListSize =
                    last.getPosition() + last.getInstruction().getLength(); 

        // Need to look for any branch target offsets that exceed the range
        // [-32768,32767]
        if (instructionListSize > MAX_BRANCH_TARGET_OFFSET) {
            boolean ilChanged = widenConditionalBranchTargetOffsets();

            // If any branch instructions needed widening, recompute the size
            // of the byte code for the method
            if (ilChanged) {
                il.setPositions();
                last = il.getEnd();
                instructionListSize =
                        last.getPosition() + last.getInstruction().getLength(); 
            }
        }

        if (instructionListSize > MAX_METHOD_SIZE) {
            generatedMethods = outlineChunks(classGen, instructionListSize);
        } else {
            generatedMethods = new Method[] {getThisMethod()};
        }
        return generatedMethods;
    }

    protected Method getThisMethod() {
        stripAttributes(true);
        setMaxLocals();
        setMaxStack();
        removeNOPs();

        return getMethod();
    }
    /**
     * <p>Rewrites branches to avoid the JVM limits of relative branch
     * offsets.  There is no need to invoke this method if the bytecode for the
     * {@link MethodGenerator} does not exceed 32KB.</p>
     * <p>The Java Virtual Machine Specification permits the code portion of a
     * method to be up to 64KB in length.  However, some control transfer
     * instructions specify relative offsets as a signed 16-bit quantity,
     * limiting the range to a subset of the instructions that might be in a
     * method.</p>
     * <p>The <code>TABLESWITCH</code> and <code>LOOKUPSWITCH</code>
     * instructions always use 32-bit signed relative offsets, so they are
     * immune to this problem.</p>
     * <p>The <code>GOTO</code> and <code>JSR</code>
     * instructions come in two forms, one of which uses 16-bit relative
     * offsets, and the other of which uses 32-bit relative offsets.  The BCEL
     * library decides whether to use the wide form of <code>GOTO</code> or
     * <code>JSR</code>instructions based on the relative offset of the target
     * of the instruction without any intervention by the user of the
     * library.</p>
     * <p>This leaves the various conditional branch instructions,
     * <code>IFEQ</code>, <code>IFNULL</code>, <code>IF_ICMPEQ</code>,
     * <em>et al.</em>, all of which use 16-bit signed relative offsets, with no
     * 32-bit wide form available.</p>
     * <p>This method scans the {@link InstructionList} associated with this
     * {@link MethodGenerator} and finds all conditional branch instructions
     * that might exceed the 16-bit limitation for relative branch offsets.
     * The logic of each such instruction is inverted, and made to target the
     * instruction which follows it.  An unconditional branch to the original
     * target of the instruction is then inserted between the conditional
     * branch and the instruction which previously followed it.  The
     * unconditional branch is permitted to have a 16-bit or a 32-bit relative
     * offset, as described above.  For example,
     * <code>
     * 1234:   NOP
     *          ...
     * 55278:  IFEQ -54044
     * 55280:  NOP
     * </code>
     * is rewritten as
     * <code>
     * 1234:   NOP
     *          ...
     * 55278:  IFNE 7
     * 55280:  GOTO_W -54046
     * 55285:  NOP
     * </code></p>
     * <p><b>Preconditions:</b>
     * <ul><li>The {@link InstructionList#setPositions()} has been called for
     * the <code>InstructionList</code> associated with this
     * <code>MethodGenerator</code>.
     * </li></ul></p>
     * <p><b>Postconditions:</b>
     * <ul><li>Any further changes to the <code>InstructionList</code> for this
     * <code>MethodGenerator</code> will invalidate the changes made by this
     * method.</li></ul>
     * </p>
     * @return <code>true</code> if the <code>InstructionList</code> was
     * modified; <code>false</code> otherwise
     * @see The Java Virtual Machine Specification, Second Edition
     */
    boolean widenConditionalBranchTargetOffsets() {
        boolean ilChanged = false;
        int maxOffsetChange = 0;
        InstructionList il = getInstructionList();

        // Loop through all the instructions, finding those that would be
        // affected by inserting new instructions in the InstructionList, and
        // calculating the maximum amount by which the relative offset between
        // two instructions could possibly change.
        // In part this loop duplicates code in
        // org.apache.bcel.generic.InstructionList.setPosition(), which does
        // this to determine whether to use 16-bit or 32-bit offsets for GOTO
        // and JSR instructions.  Ideally, that method would do the same for
        // conditional branch instructions, but it doesn't, so we duplicate the
        // processing here.
        for (InstructionHandle ih = il.getStart();
             ih != null;
             ih = ih.getNext()) {
            Instruction inst = ih.getInstruction();
           
            switch (inst.getOpcode()) {
                // Instructions that may have 16-bit or 32-bit branch targets.
                // The size of the branch offset might increase by two bytes.
                case Constants.GOTO:
                case Constants.JSR:
                    maxOffsetChange = maxOffsetChange + 2; 
                    break;
                // Instructions that contain padding for alignment purposes
                // Up to three bytes of padding might be needed.  For greater
                // accuracy, we should be able to discount any padding already
                // added to these instructions by InstructionList.setPosition(),
                // their APIs do not expose that information.
                case Constants.TABLESWITCH:
                case Constants.LOOKUPSWITCH:
                    maxOffsetChange = maxOffsetChange + 3;
                    break;
                // Instructions that might be rewritten by this method as a
                // conditional branch followed by an unconditional branch.
                // The unconditional branch would require five bytes. 
                case Constants.IF_ACMPEQ:
                case Constants.IF_ACMPNE:
                case Constants.IF_ICMPEQ:
                case Constants.IF_ICMPGE:
                case Constants.IF_ICMPGT:
                case Constants.IF_ICMPLE:
                case Constants.IF_ICMPLT:
                case Constants.IF_ICMPNE:
                case Constants.IFEQ:
                case Constants.IFGE:
                case Constants.IFGT:
                case Constants.IFLE:
                case Constants.IFLT:
                case Constants.IFNE:
                case Constants.IFNONNULL:
                case Constants.IFNULL:
                    maxOffsetChange = maxOffsetChange + 5;
                    break;
            }
        }

        // Now that the maximum number of bytes by which the method might grow
        // has been determined, look for conditional branches to see which
        // might possibly exceed the 16-bit relative offset.
        for (InstructionHandle ih = il.getStart();
             ih != null;
             ih = ih.getNext()) {
            Instruction inst = ih.getInstruction();

            if (inst instanceof IfInstruction) {
                IfInstruction oldIfInst = (IfInstruction)inst;
                BranchHandle oldIfHandle = (BranchHandle)ih;
                InstructionHandle target = oldIfInst.getTarget();
                int relativeTargetOffset = target.getPosition()
                                               - oldIfHandle.getPosition();

                // Consider the worst case scenario in which the conditional
                // branch and its target are separated by all the instructions
                // in the method that might increase in size.  If that results
                // in a relative offset that cannot be represented as a 32-bit
                // signed quantity, rewrite the instruction as described above.
                if ((relativeTargetOffset - maxOffsetChange
                             < MIN_BRANCH_TARGET_OFFSET)
                        || (relativeTargetOffset + maxOffsetChange
                                    > MAX_BRANCH_TARGET_OFFSET)) {
                    // Invert the logic of the IF instruction, and append
                    // that to the InstructionList following the original IF
                    // instruction
                    InstructionHandle nextHandle = oldIfHandle.getNext();
                    IfInstruction invertedIfInst = oldIfInst.negate();
                    BranchHandle invertedIfHandle = il.append(oldIfHandle,
                                                              invertedIfInst);

                    // Append an unconditional branch to the target of the
                    // original IF instruction after the new IF instruction
                    BranchHandle gotoHandle = il.append(invertedIfHandle,
                                                        new GOTO(target));

                    // If the original IF was the last instruction in
                    // InstructionList, add a new no-op to act as the target
                    // of the new IF
                    if (nextHandle == null) {
                        nextHandle = il.append(gotoHandle, NOP);
                    }

                    // Make the new IF instruction branch around the GOTO
                    invertedIfHandle.updateTarget(target, nextHandle);

                    // If anything still "points" to the old IF instruction,
                    // make adjustments to refer to either the new IF or GOTO
                    // instruction
                    if (oldIfHandle.hasTargeters()) {
                        InstructionTargeter[] targeters =
                                                  oldIfHandle.getTargeters();

                        for (int i = 0; i < targeters.length; i++) {
                            InstructionTargeter targeter = targeters[i];
                            // Ideally, one should simply be able to use
                            // InstructionTargeter.updateTarget to change
                            // references to the old IF instruction to the new
                            // IF instruction.  However, if a LocalVariableGen
                            // indicated the old IF marked the end of the range
                            // in which the IF variable is in use, the live
                            // range of the variable must extend to include the
                            // newly created GOTO instruction.  The need for
                            // this sort of specific knowledge of an
                            // implementor of the InstructionTargeter interface
                            // makes the code more fragile.  Future implementors
                            // of the interface might have similar requirements
                            // which wouldn't be accommodated seemlessly.
                            if (targeter instanceof LocalVariableGen) {
                                LocalVariableGen lvg =
                                        (LocalVariableGen) targeter;
                                if (lvg.getStart() == oldIfHandle) {
                                    lvg.setStart(invertedIfHandle);
                                } else if (lvg.getEnd() == oldIfHandle) {
                                    lvg.setEnd(gotoHandle);
                                }
                            } else {
                                targeter.updateTarget(oldIfHandle,
                                                      invertedIfHandle);
                            }
                        }
                    }

                    try {
                        il.delete(oldIfHandle);
                    } catch (TargetLostException tle) {
                        // This can never happen - we updated the list of
                        // instructions that target the deleted instruction
                        // prior to deleting it.
                        String msg =
                            new ErrorMsg(ErrorMsg.OUTLINE_ERR_DELETED_TARGET,
                                         tle.getMessage()).toString();
                        throw new InternalError(msg);
                    }

                    // Adjust the pointer in the InstructionList to point after
                    // the newly inserted IF instruction
                    ih = gotoHandle;

                    // Indicate that this method rewrote at least one IF
                    ilChanged = true;
                }
            } 
        }

        // Did this method rewrite any IF instructions?
        return ilChanged;
    }
}
