/*
 *
 *  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.
 *
 */

package macromedia.abc;

import static macromedia.asc.embedding.avmplus.ActionBlockConstants.*;
import macromedia.asc.util.IntegerPool;
import macromedia.asc.util.IntList;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

/**
 * abc encoder. If the encoder is provided with multiple constant pools, it will use do merging.
 *
 * @author Clement Wong
 */
public class Encoder implements Visitor
{
	public Encoder(int majorVersion, int minorVersion)
	{
		this.majorVersion = majorVersion;
		this.minorVersion = minorVersion;

		poolIndex = 0;
		peepHole = false;
		disableDebugging = false;
		removeMetadata = false;

    }

	private ConstantPool pool;
	private int majorVersion, minorVersion;
	private int poolIndex, opcodePass, exPass;
	private boolean disableDebugging, removeMetadata, peepHole;

    private HashSet<String> keep_metadata = new HashSet<String>();

	private BytecodeBuffer2 methodInfo;
	private ByteArrayPool2 metadataInfo;
	private BytecodeBuffer2 classInfo;
	private BytecodeBuffer2 scriptInfo;
	private BytecodeBuffer2 methodBodies;
	private BytecodeBuffer3 opcodes;
	private BytecodeBuffer exceptions;

	private BytecodeBuffer currentBuffer;

    private ConstantPool[] pools;

	public void enablePeepHole()
	{
		peepHole = true;
	}

	public void disableDebugging()
	{
		disableDebugging = true;
        pool.history.disableDebugging();
	}

	public void removeMetadata()
	{
		removeMetadata = true;
	}

    public void addMetadataToKeep(String meta_name)
    {
        keep_metadata.add(meta_name);
    }

	public void addConstantPools(ConstantPool[] pools)
	{
        this.pools = pools;
		pool = ConstantPool.merge(pools);
        if( disableDebugging )
            pool.history.disableDebugging();
	}
	
	public void test()
	{
		// C: testing only...
		for (int i = 0, size = pools.length; i < size; i++)
		{
			/*
			for (int j = 1, count = pools[i].intpositions.length; j < count; j++)
			{
				int original = pools[i].getInt(j);
				int real = pool.getInt(pool.history.getIndex(i, 0, j));

				if (original != real)
				{
					throw new DecoderException("Error (int) in constant pooling merging...");
				}
			}

			for (int j = 1, count = pools[i].uintpositions.length; j < count; j++)
			{
				long original = pools[i].getLong(j);
				long real = pool.getLong(pool.history.getIndex(i, 1, j));

				if (original != real)
				{
					throw new DecoderException("Error (uint) in constant pooling merging...");
				}
			}

			for (int j = 1, count = pools[i].doublepositions.length; j < count; j++)
			{
				double original = pools[i].getDouble(j);
				double real = pool.getDouble(pool.history.getIndex(i, 2, j));

				if (original != real)
				{
					throw new DecoderException("Error (double) in constant pooling merging...");
				}
			}

			for (int j = 1, count = pools[i].strpositions.length; j < count; j++)
			{
				String original = pools[i].getString(j);
				System.out.println("(" + i + "," + j + ")-->(0," + pool.history.getIndex(i, 3, j) + "): " + original);
			}

			for (int j = 1, count = pools[i].nspositions.length; j < count; j++)
			{
				String original = pools[i].getNamespaceName(j);
				String real = pool.getNamespaceName(pool.history.getIndex(i, 4, j));

				if (!original.equals(real))
				{
					throw new DecoderException("Error (namespace) in constant pooling merging...");
				}
			}

			for (int j = 1, count = pools[i].nsspositions.length; j < count; j++)
			{
				String[] original = pools[i].getNamespaceSet(j);
				String[] real = pool.getNamespaceSet(pool.history.getIndex(i, 5, j));

				if (original.length != real.length)
				{
					throw new DecoderException("Error (namespace set) in constant pooling merging...");
				}
				else
				{
					for (int k = 0, len = original.length; k < len; k++)
					{
						if (!original[k].equals(real[k]))
						{
							throw new DecoderException("Error (namespace set) in constant pooling merging...");
						}
					}
				}
			}

			for (int j = 1, count = pools[i].mnpositions.length; j < count; j++)
			{
				Object original = pools[i].getGeneralMultiname(j);
				Object real = pool.getGeneralMultiname(pool.history.getIndex(i, 6, j));

				if (original.getClass() != real.getClass())
				{
					throw new DecoderException("Error (multiname) in constant pooling merging...");
				}

				if (original instanceof QName && !((QName) original).equals(real))
				{
					throw new DecoderException("Error (multiname) in constant pooling merging...");
				}

				if (original instanceof MultiName && !((MultiName) original).equals(real))
				{
					throw new DecoderException("Error (multiname) in constant pooling merging...");
				}
			}
			*/
		}
	}

	public void configure(Decoder[] decoders)
	{
		int estimatedSize = 0, total = 0;
		int[] sizes = new int[decoders.length];
		for (int i = 0, size = sizes.length; i < size; i++)
		{
			estimatedSize += decoders[i].methodInfo.estimatedSize;
			sizes[i] = decoders[i].methodInfo.size();
			total += sizes[i];
		}
		methodInfo = new BytecodeBuffer2(estimatedSize, sizes);
		methodInfo.writeU32(total);


		estimatedSize = 0; total = 0;
		sizes = new int[decoders.length];
		for (int i = 0, size = sizes.length; i < size; i++)
		{
			estimatedSize += decoders[i].metadataInfo.estimatedSize;
			sizes[i] = decoders[i].metadataInfo.size();
			total += sizes[i];
		}
		metadataInfo = new ByteArrayPool2(sizes);


		estimatedSize = 0; total = 0;
		sizes = new int[decoders.length];
		for (int i = 0, size = sizes.length; i < size; i++)
		{
			estimatedSize += decoders[i].classInfo.estimatedSize;
			sizes[i] = decoders[i].classInfo.size();
			total += sizes[i];
		}
		classInfo = new BytecodeBuffer2(estimatedSize, sizes);
		classInfo.writeU32(total);


		estimatedSize = 0; total = 0;
		sizes = new int[decoders.length];
		for (int i = 0, size = sizes.length; i < size; i++)
		{
			estimatedSize += decoders[i].scriptInfo.estimatedSize;
			sizes[i] = decoders[i].scriptInfo.size();
			total += sizes[i];
		}
		scriptInfo = new BytecodeBuffer2(estimatedSize, sizes);
		scriptInfo.writeU32(total);


		estimatedSize = 0; total = 0;
		sizes = new int[decoders.length];
		for (int i = 0, size = sizes.length; i < size; i++)
		{
			estimatedSize += decoders[i].methodBodies.estimatedSize;
			sizes[i] = decoders[i].methodBodies.size();
			total += sizes[i];
		}
		methodBodies = new BytecodeBuffer2(estimatedSize, sizes);
		methodBodies.writeU32(total);

		opcodes = new BytecodeBuffer3(decoders, 4096);
		exceptions = new BytecodeBuffer(4096);
	}

	public void useConstantPool(int index)
	{
		poolIndex = index;
	}

	public byte[] toABC()
	{
		/*
		System.out.println();
		System.out.println("--Constant Pool--");
		System.out.println("total: " + pool.history.total + " duplicate: " + pool.history.duplicate);
		System.out.println("totalBytes: " + pool.history.totalBytes + " duplicateBytes: " + pool.history.duplicateBytes);
		System.out.println("--Method Info--");
		System.out.println("before: " + methodInfo.estimatedSize + " after: " + methodInfo.size());
		System.out.println("--Metadata Info--");
		System.out.println("before: " + metadataInfo.estimatedSize + " after: " + metadataInfo.size());
		System.out.println("--Class Info--");
		System.out.println("before: " + classInfo.estimatedSize + " after: " + classInfo.size());
		System.out.println("--Script Info--");
		System.out.println("before: " + scriptInfo.estimatedSize + " after: " + scriptInfo.size());
		System.out.println("--Method Bodies--");
		System.out.println("before: " + methodBodies.estimatedSize + " after: " + methodBodies.size());
		System.out.println();
		*/
		
		int size = pool.in.size() + methodInfo.size() + metadataInfo.size() + classInfo.size() + scriptInfo.size() + methodBodies.size();
		ByteArrayOutputStream baos = new ByteArrayOutputStream(size);

		try
		{
			baos.write((byte) minorVersion);
			baos.write((byte) (minorVersion >> 8));
			baos.write((byte) majorVersion);
			baos.write((byte) (majorVersion >> 8));

			pool.writeTo(baos);
			methodInfo.writeTo(baos);
			metadataInfo.writeTo(baos);
			classInfo.writeTo(baos);
			scriptInfo.writeTo(baos);
			methodBodies.writeTo(baos);
		}
		catch (IOException ex)
		{
			return null;
		}

		return baos.toByteArray();
	}

	public void methodInfo(int returnType, int[] paramTypes, int nativeName, int flags, int[] values, int[] value_kinds, int[] param_names)
	{
		if (paramTypes == null)
		{
			methodInfo.writeU32(0);
		}
		else
		{
			methodInfo.writeU32(paramTypes.length);
		}

		methodInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, returnType));

		for (int i = 0, paramCount = (paramTypes == null) ? 0 : paramTypes.length; i < paramCount; i++)
		{
			methodInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, paramTypes[i]));
		}

		methodInfo.writeU32((disableDebugging) ? 0 : pool.history.getIndex(poolIndex, IndexHistory.cp_string, nativeName));

        if( disableDebugging )
        {
            // Nuke the param names if we're getting rid of debugging info, don't want them showing
            // up in release code
            flags &= ~METHOD_HasParamNames;
        }

		methodInfo.writeU8(flags);

		if ((flags & METHOD_HasOptional) != 0)
		{
			if (values == null)
			{
				methodInfo.writeU32(0);
			}
			else
			{
				methodInfo.writeU32(values.length);
			}
		}

		for (int i = 0, optionalCount = (values == null) ? 0 : values.length; i < optionalCount; i++)
		{
			int kind = -1;

			switch (value_kinds[i])
			{
		    case CONSTANT_Utf8:
				kind = IndexHistory.cp_string;
				break;
		    case CONSTANT_Integer:
				kind = IndexHistory.cp_int;
				break;
		    case CONSTANT_UInteger:
				kind = IndexHistory.cp_uint;
				break;
		    case CONSTANT_Double:
				kind = IndexHistory.cp_double;
				break;
		    case CONSTANT_Decimal:
				kind = IndexHistory.cp_decimal;
				break;
		    case CONSTANT_Namespace:
		    case CONSTANT_PrivateNamespace:
            case CONSTANT_PackageNamespace:
            case CONSTANT_PackageInternalNs:
            case CONSTANT_ProtectedNamespace:
            case CONSTANT_ExplicitNamespace:
            case CONSTANT_StaticProtectedNs:
				kind = IndexHistory.cp_ns;
				break;
			case CONSTANT_Qname:
			case CONSTANT_QnameA:
		    case CONSTANT_Multiname:
		    case CONSTANT_MultinameA:
            case CONSTANT_TypeName:
                kind = IndexHistory.cp_mn;
				break;
		    case CONSTANT_Namespace_Set:
				kind = IndexHistory.cp_nsset;
				break;
			}

			int newIndex = 0;

			switch(value_kinds[i])
			{
			case 0:
			case CONSTANT_False:
			case CONSTANT_True:
			case CONSTANT_Null:
				// The index doesn't matter, as long as its non 0
				// there are no boolean values in any cpool, instead the value will be determined by the kind byte
				newIndex = values[i];
				break;
			default:
			{
				if (kind == -1)
				{
					System.out.println("writing MethodInfo: don't know what constant type it is... " + value_kinds[i] + "," + values[i]);
				}
				newIndex = pool.history.getIndex(poolIndex, kind, values[i]);
			}
			}

			methodInfo.writeU32(newIndex);
			methodInfo.writeU8(value_kinds[i]);
		}
        // Nuke the param names if we're not keeping debugging around
        if( (flags & METHOD_HasParamNames) != 0 && param_names != null)
        {
            for( int i = 0 ; i < param_names.length; ++i )
            {
                methodInfo.writeU32( pool.history.getIndex(poolIndex, IndexHistory.cp_string, returnType) );
            }
        }
	}

	public void metadataInfo(int index, int name, int[] keys, int[] values)
	{


        try
        {
            String s = pools[poolIndex].getString(name);
            if (removeMetadata && !keep_metadata.contains(s) )
                return;

            BytecodeBuffer b = new BytecodeBuffer(6);
            b.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, name));
            if (keys == null)
            {
                b.writeU32(0);
            }
            else
            {
                b.writeU32(keys.length);
            }

            for (int i = 0, keyCount = (keys == null) ? 0 : keys.length; i < keyCount; i++)
            {
                b.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, keys[i]));
            }

            for (int i = 0, valueCount = (values == null) ? 0 : values.length; i < valueCount; i++)
            {
                b.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, values[i]));
            }

            metadataInfo.addByteArray(poolIndex, index, b);
        }
        catch( DecoderException ex)
        {
            // this should never happen
            // ex.printStackTrace();
        }
	}

	public void startInstance(int name, int superName, boolean isDynamic, boolean isFinal, boolean isInterface, int[] interfaces, int iinit, int protectedNamespace)
	{
		classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name));
		classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, superName));

		int flags = 0;
		flags = (isFinal) ? (flags | CLASS_FLAG_final) : flags;
		flags = (!isDynamic) ? (flags | CLASS_FLAG_sealed) : flags;
		flags = (isInterface) ? (flags | CLASS_FLAG_interface) : flags;
		flags = (protectedNamespace != 0) ? (flags | CLASS_FLAG_protected) : flags;
		classInfo.writeU8(flags);

		if (protectedNamespace != 0)
		{
			classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_ns, protectedNamespace));
		}
		
		if (interfaces == null)
		{
			classInfo.writeU32(0);
		}
		else
		{
			classInfo.writeU32(interfaces.length);
		}

		for (int i = 0, interfaceCount = interfaces == null ? 0 : interfaces.length; i < interfaceCount; i++)
		{
			classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, interfaces[i]));
		}

		classInfo.writeU32(methodInfo.getIndex(poolIndex, iinit));

		currentBuffer = classInfo;
	}

	public void endInstance()
	{
		currentBuffer = null;
	}

	public void startClass(int name, int cinit)
	{
		classInfo.writeU32(methodInfo.getIndex(poolIndex, cinit));

		currentBuffer = classInfo;
	}

	public void endClass()
	{
		currentBuffer = null;
	}

	public void startScript(int initID)
	{
		scriptInfo.writeU32(methodInfo.getIndex(poolIndex, initID));

		currentBuffer = scriptInfo;
	}

	public void endScript()
	{
		currentBuffer = null;
	}

	public void startMethodBody(int methodInfo, int maxStack, int maxRegs, int scopeDepth, int maxScope, int codeStart, long codeLength)
	{
		methodBodies.writeU32(this.methodInfo.getIndex(poolIndex, methodInfo));
		methodBodies.writeU32(maxStack);
		methodBodies.writeU32(maxRegs);
		methodBodies.writeU32(scopeDepth);
		methodBodies.writeU32(maxScope);

		currentBuffer = methodBodies;
		opcodePass = 1;
		exPass = 1;
	}

	public void endMethodBody()
	{
		currentBuffer = null;
		opcodes.clear();
		exceptions.clear();
	}

	public void startOpcodes(int methodInfo)
	{
	}

	public void endOpcodes()
	{
		if (opcodePass == 1)
		{
			opcodePass = 2;
		}
		else if (opcodePass == 2)
		{
			methodBodies.writeU32(opcodes.size());
			methodBodies.writeBytes(opcodes, 0, opcodes.size());
		}
	}

	public void exception(long start, long end, long target, int type, int name)
	{
		if (exPass == 2)
		{
			exceptions.writeU32(opcodes.getOffset(start));
			exceptions.writeU32(opcodes.getOffset(end));
			exceptions.writeU32(opcodes.getOffset(target));
			exceptions.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, type));
			if (minorVersion != 15)
			{
				exceptions.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name));
			}
		}
	}

	public void startExceptions(int exceptionCount)
	{
		if (exPass == 2)
		{
			exceptions.writeU32(exceptionCount);
		}
	}

	public void endExceptions()
	{
		if (exPass == 1)
		{
			exPass++;
		}
		else if (exPass == 2)
		{
			methodBodies.writeBytes(exceptions, 0, exceptions.size());
		}
	}

	public void traitCount(int traitCount)
	{
		currentBuffer.writeU32(traitCount);
	}

//	private void encodeMetaData(int kind, int[] metadata)
//	{
//		if (((kind >> 4) & TRAIT_FLAG_metadata) != 0)
//		{
//			if (metadata == null)
//			{
//				currentBuffer.writeU32(0);
//			}
//			else
//			{
//				currentBuffer.writeU32(metadata.length);
//			}
//
//			for (int i = 0, length = metadata == null ? 0 : metadata.length; i < length; i++)
//			{
//				currentBuffer.writeU32(metadataInfo.getIndex(poolIndex, metadata[i]));
//			}
//		}
//	}

    private void encodeMetaData(int kind, IntList metadata)
    {
        if (((kind >> 4) & TRAIT_FLAG_metadata) != 0)
        {
            if (metadata == null)
            {
                currentBuffer.writeU32(0);
            }
            else
            {
                currentBuffer.writeU32(metadata.size());
            }

            for (int i = 0, length = metadata == null ? 0 : metadata.size(); i < length; i++)
            {
                currentBuffer.writeU32(metadata.get(i));
            }
        }
    }

    private IntList trimMetadata(int[] metadata)
    {
        IntList newMetadata = new IntList();
        int length = metadata != null ? metadata.length : 0;
        for( int i = 0; i < length; ++i)
        {
            int new_index = metadataInfo.getIndex(poolIndex, metadata[i]) ;
            if( new_index != -1 )
            {
                newMetadata.add(new_index);
            }
        }
        return newMetadata;
    }

	public void slotTrait(int trait_kind, int name, int slotId, int type, int value, int value_kind, int[] metadata)
	{
		currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name));
        IntList new_metadata = trimMetadata(metadata);
		if ( ((trait_kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 )
		{
			trait_kind = trait_kind & ~(TRAIT_FLAG_metadata << 4);
		}
		currentBuffer.writeU8(trait_kind);

		currentBuffer.writeU32(slotId);
		currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, type));

		int kind = -1;

		switch(value_kind)
		{
		case CONSTANT_Utf8:
			kind = IndexHistory.cp_string;
			break;
		case CONSTANT_Integer:
			kind = IndexHistory.cp_int;
			break;
		case CONSTANT_UInteger:
			kind = IndexHistory.cp_uint;
			break;
		case CONSTANT_Double:
			kind = IndexHistory.cp_double;
			break;
		case CONSTANT_Decimal:
			kind = IndexHistory.cp_decimal;
			break;
		case CONSTANT_Namespace:
		case CONSTANT_PrivateNamespace:
        case CONSTANT_PackageNamespace:
        case CONSTANT_PackageInternalNs:
        case CONSTANT_ProtectedNamespace:
        case CONSTANT_ExplicitNamespace:
        case CONSTANT_StaticProtectedNs:			
			kind = IndexHistory.cp_ns;
			break;
		case CONSTANT_Qname:
		case CONSTANT_QnameA:
		case CONSTANT_Multiname:
		case CONSTANT_MultinameA:
        case CONSTANT_TypeName:
            kind = IndexHistory.cp_mn;
			break;
		case CONSTANT_Namespace_Set:
			kind = IndexHistory.cp_nsset;
			break;
		}

		int newIndex = 0;
		switch(value_kind)
		{
		case 0:
		case CONSTANT_False:
		case CONSTANT_True:
		case CONSTANT_Null:
			newIndex = value;
			break;
		default:
		{
			if (kind == -1)
			{
				System.out.println("writing slotTrait: don't know what constant type it is... " + value_kind + "," + value);
			}
			newIndex = pool.history.getIndex(poolIndex, kind, value);
		}
		}

		currentBuffer.writeU32(newIndex);
		if (value != 0)
		{
			currentBuffer.writeU8(value_kind);
		}

		encodeMetaData(trait_kind, new_metadata);
	}

	public void methodTrait(int trait_kind, int name, int dispId, int methodInfo, int[] metadata)
	{
		currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name));
        IntList new_metadata = trimMetadata(metadata);
		if ( ((trait_kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 )
		{
			trait_kind = trait_kind & ~(TRAIT_FLAG_metadata << 4);
		}
		currentBuffer.writeU8(trait_kind);

		//currentBuffer.writeU32(0);
		currentBuffer.writeU32(dispId);
		currentBuffer.writeU32(this.methodInfo.getIndex(poolIndex, methodInfo));

		encodeMetaData(trait_kind, new_metadata);
	}

	public void classTrait(int kind, int name, int slotId, int classIndex, int[] metadata)
	{
		currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name));
        IntList new_metadata = trimMetadata(metadata);
		if ( ((kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 )
		{
			kind = kind & ~(TRAIT_FLAG_metadata << 4);
		}
		currentBuffer.writeU8(kind);

		currentBuffer.writeU32(slotId);
		currentBuffer.writeU32(classInfo.getIndex(poolIndex, classIndex));

		encodeMetaData(kind, new_metadata);
	}

	public void functionTrait(int kind, int name, int slotId, int methodInfo, int[] metadata)
	{
		currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name));
        IntList new_metadata = trimMetadata(metadata);
		if ( ((kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 )
		{
			kind = kind & ~(TRAIT_FLAG_metadata << 4);
		}
		currentBuffer.writeU8(kind);

		currentBuffer.writeU32(slotId);
		currentBuffer.writeU32(this.methodInfo.getIndex(poolIndex, methodInfo));

		encodeMetaData(kind, new_metadata);
	}

	static final int W = 8;
	int[] window = new int[W];
    int window_size = 0;
	int head = 0;
	boolean reachable = true;
	
	void clearWindow()
	{
		for (int i=0; i < W; i++)
			window[i] = 0;
        window_size = 0;
	}
	
	void beginop(int opcode)
	{
		window[head] = opcodes.size();
		head = (head+1) & (W-1);
        if( window_size < 8 )
            ++window_size;
		opcodes.writeU8(opcode);
	}
	
	int opat(int i)
	{
		if (peepHole)
		{
            if( i <= window_size )
            {
                int ip = window[(head-i) & (W-1)];
                if (ip < opcodes.size())
                    return opcodes.readU8(ip);
            }
		}
		return 0;
	}
	
	void setOpcodeAt(int i, int opcode)
	{
		assert peepHole;

        if( i <= window_size )
        {
            int ip = window[(head-i) & (W-1)];
            if (ip < opcodes.size())
                opcodes.writeU8(ip, opcode);
        }
	}
	
	int readByteAt(int i)
	{
        if( i <= window_size )
        {
            int ip = 1+window[(head-i) & (W-1)];
            return (byte) opcodes.readU8(ip);
        }
        return 0;
	}
	
	int readIntAt(int i)
	{
        if( i <= window_size )
        {
            int ip = 1+window[(head-i) & (W-1)];
            return (int) opcodes.readU32(ip);
        }
        return 0;
	}
	
	void rewind(int i)
	{
		int to = (head-i) & (W-1);
		int ip = window[to];
		int end = opcodes.size();
		opcodes.delete(end-ip);
		head = to;
        window_size -= i;
	}
	
	public void target(int oldPos)
	{
		if (opcodePass == 1)
		{
			opcodes.mapOffsets(oldPos);
			clearWindow();
		}
	}

	public void OP_returnvoid()
	{
		if (opcodePass == 1)
		{
			/*
			if (opat(2) == OP_getlocal0 && opat(1) == OP_pushscope)
				rewind(2);
			
			if (opat(1) == OP_returnvalue)
				return;
			*/
			beginop(OP_returnvoid);
		}
	}

	public void OP_returnvalue()
	{
		if (opcodePass == 1)
		{
			
			if (opat(1) == OP_coerce_a)
			{
				rewind(1);
			}
			
			if (opat(1) == OP_pushundefined)
			{
				rewind(1);						
				OP_returnvoid();
				return;
			}
			
			// eliminate dead code... maybe do this higher up?
			/*
			for (int i=1; i < W; i++)
			{
				if (opat(i) == OP_returnvalue) 
				{
					rewind(i);
					break;
				}
			}
			
			if (	opat(4) == OP_pushundefined &&
					opat(3) == OP_coerce_a &&
					opat(2) == OP_setlocal1 &&
					opat(1) == OP_getlocal1)
			{
				rewind(4);
				OP_returnvoid();
				return;
			}
			*/
			
			beginop(OP_returnvalue);
		}
	}

	public void OP_nop()
	{
		if (opcodePass == 1)
		{
			beginop(OP_nop);
		}
	}

	public void OP_bkpt()
	{
		if (opcodePass == 1)
		{
			beginop(OP_bkpt);
		}
	}

	public void OP_timestamp()
	{
		if (opcodePass == 1)
		{
			beginop(OP_timestamp);
		}
	}

	public void OP_debugline(int linenum)
	{
		if (opcodePass == 1)
		{
			if (!disableDebugging)
			{
				beginop(OP_debugline);
				opcodes.writeU32(linenum);
			}
		}
	}

	public void OP_bkptline()
	{
		if (opcodePass == 1)
		{
			beginop(OP_bkptline);
		}
	}

	public void OP_debug(int di_local, int index, int slot, int linenum)
	{
		if (opcodePass == 1)
		{
			if (!disableDebugging)
			{
				beginop(OP_debug);
				opcodes.writeU8(di_local);
				// FIX: is this a constant pool index? if so, we need to know the constant type...
				// opcodes.writeU32(index);
				opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index));
				opcodes.writeU8(slot);
				opcodes.writeU32(linenum);
			}
		}
	}

	public void OP_debugfile(int index)
	{
		if (opcodePass == 1)
		{
			if (!disableDebugging)
			{
				beginop(OP_debugfile);
				opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index));
			}
		}
	}

	public void OP_jump(int offset, int pos)
	{
		if (opcodePass == 1)
        {
			/*
			if (opat(1) == OP_jump)
			{
				// unreachable
				return;
			}
			*/

			beginop(OP_jump);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_pushnull()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushnull);
		}
	}

	public void OP_pushundefined()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushundefined);
		}
	}

    public void OP_pushstring(int index)
    {
	    if (opcodePass == 1)
	    {
	    	beginop(OP_pushstring);
	    	opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index));
	    }
    }

    public void OP_pushnamespace(int index)
    {
	    if (opcodePass == 1)
	    {
	    	beginop(OP_pushnamespace);
	    	opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_ns, index));
	    }
    }

    public void OP_pushint(int index)
    {
	    if (opcodePass == 1)
	    {
	    	beginop(OP_pushint);
		    opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_int, index));
	    }
    }

    public void OP_pushuint(int index)
    {
	    if (opcodePass == 1)
	    {
	    	beginop(OP_pushuint);
		    opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_uint, index));
	    }
    }

    public void OP_pushdouble(int index)
    {
	    if (opcodePass == 1)
	    {
	    	beginop(OP_pushdouble);
		    opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_double, index));
	    }
    }

    public void OP_pushdecimal(int index)
    {
	    if (opcodePass == 1)
	    {
	    	beginop(OP_pushdecimal);
		    opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_decimal, index));
	    }
    }

	public void OP_getlocal(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_getlocal);
			opcodes.writeU32(index);
		}
	}

	public void OP_pushtrue()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushtrue);
		}
	}

	public void OP_pushfalse()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushfalse);
		}
	}

	public void OP_pushnan()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushnan);
		}
	}

	public void OP_pushdnan()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushdnan);
		}
	}

	public void OP_pop()
	{
		if (opcodePass == 1)
		{
			switch (opat(1))
			{
			case OP_callproperty:
				setOpcodeAt(1, OP_callpropvoid);
				return;
			case OP_callsuper:
				setOpcodeAt(1, OP_callsupervoid);
				return;
			}

			beginop(OP_pop);
		}
	}

	public void OP_dup()
	{
		if (opcodePass == 1)
		{
			beginop(OP_dup);
		}
	}

	public void OP_swap()
	{
		if (opcodePass == 1)
		{
			beginop(OP_swap);
		}
	}

	public void OP_convert_s()
	{
		if (opcodePass == 1)
		{
	        if (opat(1) == OP_coerce_a)
				rewind(1);
	        
			switch (opat(1))
			{
			case OP_coerce_s:
			case OP_convert_s:
			case OP_pushstring:
			case OP_typeof:
				// result is already string
				return;
			}
			
			if (opat(2) == OP_pushstring && opat(1) == OP_add)
			{
				// result must be string, so dont coerce after
				return;
			}

			beginop(OP_convert_s);
		}
	}

	public void OP_esc_xelem()
	{
		if (opcodePass == 1)
		{
			beginop(OP_esc_xelem);
		}
	}

    public void OP_esc_xattr()
    {
        if (opcodePass == 1)
        {
            beginop(OP_esc_xattr);
        }
    }

    public void OP_checkfilter()
    {
        if (opcodePass == 1)
        {
            beginop(OP_checkfilter);
        }
    }

	public void OP_convert_d()
	{
		if (opcodePass == 1)
		{
			beginop(OP_convert_d);
		}
	}

	public void OP_convert_m()
	{
		if (opcodePass == 1)
		{
			beginop(OP_convert_m);
		}
	}

	public void OP_convert_m_p(int param)
	{
		if (opcodePass == 1)
		{
			beginop(OP_convert_m);
			opcodes.writeU32(param);
		}
	}


	public void OP_convert_b()
	{
		if (opcodePass == 1)
		{
			switch(opat(1))
			{
			case OP_equals:
			case OP_strictequals:
			case OP_not:
			case OP_greaterthan:
			case OP_lessthan:
			case OP_greaterequals:
			case OP_lessequals:
			case OP_istype:
			case OP_istypelate:
			case OP_instanceof:
			case OP_deleteproperty:
			case OP_in:
            case OP_convert_b:
            case OP_pushtrue:
            case OP_pushfalse:
				// dont need convert
				return;
			}

			beginop(OP_convert_b);
		}
	}

	public void OP_convert_o()
	{
		if (opcodePass == 1)
		{
			beginop(OP_convert_o);
		}
	}

	public void OP_negate()
	{
		if (opcodePass == 1)
		{
			beginop(OP_negate);
		}
	}

	public void OP_negate_p(int param)
	{
		if (opcodePass == 1)
		{
			beginop(OP_negate_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_negate_i()
	{
		if (opcodePass == 1)
		{
			beginop(OP_negate_i);
		}
	}

	public void OP_increment()
	{
		if (opcodePass == 1)
		{
			beginop(OP_increment);
		}
	}

	public void OP_increment_p(int param)
	{
		if (opcodePass == 1)
		{
			beginop(OP_increment_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_increment_i()
	{
		if (opcodePass == 1)
		{
			beginop(OP_increment_i);
		}
	}

	public void OP_inclocal(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_inclocal);
			opcodes.writeU32(index);
		}
	}

	public void OP_inclocal_p(int param, int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_inclocal_p);
			opcodes.writeU32(param);
			opcodes.writeU32(index);
		}
	}

	public void OP_kill(int index)
	{
		if (opcodePass == 1)
		{
			switch(opat(1))
			{
			case OP_returnvalue:
			case OP_returnvoid:
				// unreachable
				return;
			}

			beginop(OP_kill);
			opcodes.writeU32(index);
		}
	}

	public void OP_inclocal_i(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_inclocal_i);
			opcodes.writeU32(index);
		}
	}

	public void OP_decrement()
	{
		if (opcodePass == 1)
		{
			beginop(OP_decrement);
		}
	}

	public void OP_decrement_p(int param)
	{
		if (opcodePass == 1)
		{
			beginop(OP_decrement_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_decrement_i()
	{
		if (opcodePass == 1)
		{
			beginop(OP_decrement_i);
		}
	}

	public void OP_declocal(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_declocal);
			opcodes.writeU32(index);
		}
	}

	public void OP_declocal_p(int param, int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_declocal_p);
			opcodes.writeU32(param);
			opcodes.writeU32(index);
		}
	}

	public void OP_declocal_i(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_declocal_i);
			opcodes.writeU32(index);
		}
	}

	public void OP_typeof()
	{
		if (opcodePass == 1)
		{
			beginop(OP_typeof);
		}
	}

	public void OP_not()
	{
		if (opcodePass == 1)
		{
			beginop(OP_not);
		}
	}

	public void OP_bitnot()
	{
		if (opcodePass == 1)
		{
			beginop(OP_bitnot);
		}
	}

	public void OP_setlocal(int index)
	{
		if (opcodePass == 1)
		{
			if (opat(2) == OP_getlocal && readIntAt(2) == index &&
				opat(1) == OP_increment_i)
			{
				rewind(2);
				OP_inclocal_i(index);
				return;
			}
			
			if (opat(2) == OP_getlocal && readIntAt(2) == index &&
				opat(1) == OP_increment)
			{
				rewind(2);
				OP_inclocal(index);
				return;
			}
			
			beginop(OP_setlocal);
			opcodes.writeU32(index);
		}
	}

	public void OP_add()
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_coerce_a)
				rewind(1);
			beginop(OP_add);
		}
	}

	public void OP_add_p(int param)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_coerce_a)
				rewind(1);
			beginop(OP_add_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_add_i()
	{
		if (opcodePass == 1)
		{
			beginop(OP_add_i);
		}
	}

	public void OP_subtract()
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_pushbyte && readByteAt(1) == 1)
			{
				rewind(1);
				OP_decrement();
				return;
			}
			beginop(OP_subtract);
		}
	}

	public void OP_subtract_p(int param)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_pushbyte && readByteAt(1) == 1)
			{
				rewind(1);
				OP_decrement_p(param);
				return;
			}
			beginop(OP_subtract_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_subtract_i()
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_pushbyte && readIntAt(1) == 1)
			{
				rewind(1);
				OP_decrement_i();
				return;
			}
			beginop(OP_subtract_i);
		}
	}

	public void OP_multiply()
	{
		if (opcodePass == 1)
		{
			beginop(OP_multiply);
		}
	}

	public void OP_multiply_p(int param)
	{
		if (opcodePass == 1)
		{
			beginop(OP_multiply_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_multiply_i()
	{
		if (opcodePass == 1)
		{
			beginop(OP_multiply_i);
		}
	}

	public void OP_divide()
	{
		if (opcodePass == 1)
		{
			beginop(OP_divide);
		}
	}

	public void OP_divide_p(int param)
	{
		if (opcodePass == 1)
		{
			beginop(OP_divide_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_modulo()
	{
		if (opcodePass == 1)
		{
			beginop(OP_modulo);
		}
	}

	public void OP_modulo_p(int param)
	{
		if (opcodePass == 1)
		{
			beginop(OP_modulo_p);
			opcodes.writeU32(param);
		}
	}

	public void OP_lshift()
	{
		if (opcodePass == 1)
		{
			beginop(OP_lshift);
		}
	}

	public void OP_rshift()
	{
		if (opcodePass == 1)
		{
			beginop(OP_rshift);
		}
	}

	public void OP_urshift()
	{
		if (opcodePass == 1)
		{
			beginop(OP_urshift);
		}
	}

	public void OP_bitand()
	{
		if (opcodePass == 1)
		{
			beginop(OP_bitand);
		}
	}

	public void OP_bitor()
	{
		if (opcodePass == 1)
		{
			beginop(OP_bitor);
		}
	}

	public void OP_bitxor()
	{
		if (opcodePass == 1)
		{
			beginop(OP_bitxor);
		}
	}

	public void OP_equals()
	{
		if (opcodePass == 1)
		{
			beginop(OP_equals);
		}
	}

	public void OP_strictequals()
	{
		if (opcodePass == 1)
		{
			beginop(OP_strictequals);
		}
	}

	public void OP_lookupswitch(int defaultPos, int[] casePos, int oldPos, int oldTablePos)
	{
		if (opcodePass == 1)
		{
			opcodes.mapOffsets(oldPos);
			beginop(OP_lookupswitch);
			opcodes.mapOffsets(oldPos+1);
			opcodes.writeS24(defaultPos);
			opcodes.writeU32((casePos == null || casePos.length == 0) ? 0 : casePos.length - 1);
			for (int i = 0, size = casePos.length; i < size; i++)
			{
				opcodes.mapOffsets(oldTablePos+3*i);
				opcodes.writeS24(casePos[i]);
			}
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(oldPos + 1, oldPos, oldPos + defaultPos);
			for (int i = 0, size = casePos.length; i < size; i++)
			{
				opcodes.updateOffset(oldTablePos + (3 * i), oldPos, oldPos + casePos[i]);
			}
		}
	}

	public void OP_iftrue(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_convert_b)
				rewind(1);

			if (opat(1) == OP_pushtrue)
			{
				rewind(1);
				OP_jump(offset,pos);
				return;
			}
			
			beginop(OP_iftrue);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_iffalse(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_convert_b)
			{
				rewind(1);
			}

			if (opat(2) == OP_strictequals && opat(1) == OP_not)
			{
				rewind(2);
				OP_ifstricteq(offset, pos);
				return;
			}
			
			if (opat(2) == OP_equals && opat(1) == OP_not)
			{
				rewind(2);
				OP_ifeq(offset, pos);
				return;
			}
			
			if (opat(1) == OP_not)
			{
				rewind(1);
				OP_iftrue(offset, pos);
				return;
			}
			
			if (opat(1) == OP_pushfalse)
			{
				rewind(1);
				OP_jump(offset, pos);
				return;
			}
			
			beginop(OP_iffalse);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifeq(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifeq);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifne(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifne);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifstricteq(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifstricteq);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifstrictne(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifstrictne);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_iflt(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_iflt);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifle(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifle);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifgt(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifgt);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifge(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifge);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_lessthan()
	{
		if (opcodePass == 1)
		{
			beginop(OP_lessthan);
		}
	}

	public void OP_lessequals()
	{
		if (opcodePass == 1)
		{
			beginop(OP_lessequals);
		}
	}

	public void OP_greaterthan()
	{
		if (opcodePass == 1)
		{
			beginop(OP_greaterthan);
		}
	}

	public void OP_greaterequals()
	{
		if (opcodePass == 1)
		{
			beginop(OP_greaterequals);
		}
	}

	public void OP_newobject(int size)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_coerce_a && size >= 1)
				rewind(1);

			beginop(OP_newobject);
			opcodes.writeU32(size);
		}
	}

	public void OP_newarray(int size)
	{
		if (opcodePass == 1)
		{
			beginop(OP_newarray);
			opcodes.writeU32(size);
		}
	}

	public void OP_getproperty(int index)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_findpropstrict && readIntAt(1) == pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index))
			{
				rewind(1);
				OP_getlex(index);
				return;
			}

			beginop(OP_getproperty);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

    public void OP_setproperty(int index)
    {
        if (opcodePass == 1)
        {
            if (opat(1) == OP_coerce_a)
                rewind(1);

            beginop(OP_setproperty);
            opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
        }
    }

    public void OP_initproperty(int index)
    {
        if (opcodePass == 1)
        {
            if (opat(1) == OP_coerce_a)
                rewind(1);

            beginop(OP_initproperty);
            opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
        }
    }

	public void OP_getdescendants(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_getdescendants);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_findpropstrict(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_findpropstrict);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_findproperty(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_findproperty);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_finddef(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_finddef);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}
	
	public void OP_getlex(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_getlex);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_nextname()
	{
		if (opcodePass == 1)
		{
			beginop(OP_nextname);
		}
	}

	public void OP_nextvalue()
	{
		if (opcodePass == 1)
		{
			beginop(OP_nextvalue);
		}
	}

	public void OP_hasnext()
	{
		if (opcodePass == 1)
		{
			beginop(OP_hasnext);
		}
	}

	public void OP_hasnext2(int objectRegister, int indexRegister)
	{
		if (opcodePass == 1)
		{
			beginop(OP_hasnext2);
			opcodes.writeU32(objectRegister);
			opcodes.writeU32(indexRegister);			
		}
	}
	
	public void OP_deleteproperty(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_deleteproperty);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_setslot(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_setslot);
			opcodes.writeU32(index);
		}
	}

	public void OP_getslot(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_getslot);
			opcodes.writeU32(index);
		}
	}

	public void OP_setglobalslot(int index)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_coerce_a)
				rewind(1);

			beginop(OP_setglobalslot);
			opcodes.writeU32(index);
		}
	}

	public void OP_getglobalslot(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_getglobalslot);
			opcodes.writeU32(index);
		}
	}

	public void OP_call(int size)
	{
		if (opcodePass == 1)
		{
			beginop(OP_call);
			opcodes.writeU32(size);
		}
	}

	public void OP_construct(int size)
	{
		if (opcodePass == 1)
		{
			beginop(OP_construct);
			opcodes.writeU32(size);
		}
	}

    public void OP_applytype(int size)
    {
        if (opcodePass == 1)
        {
            beginop(OP_applytype);
            opcodes.writeU32(size);
        }
    }

	public void OP_newfunction(int id)
	{
		if (opcodePass == 1)
		{
			beginop(OP_newfunction);
			opcodes.writeU32(methodInfo.getIndex(poolIndex, id));
		}
	}

	public void OP_newclass(int id)
	{
		if (opcodePass == 1)
		{
			beginop(OP_newclass);
			opcodes.writeU32(classInfo.getIndex(poolIndex, id));
		}
	}

	public void OP_callstatic(int id, int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_callstatic);
			opcodes.writeU32(methodInfo.getIndex(poolIndex, id));
			opcodes.writeU32(argc);
		}
	}

	public void OP_callmethod(int id, int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_callmethod);
			opcodes.writeU32(methodInfo.getIndex(poolIndex, id));
			opcodes.writeU32(argc);
		}
	}

	public void OP_callproperty(int index, int argc)
	{
		if (opcodePass == 1)
		{
	        if (opat(1) == OP_coerce_a)
	        	rewind(1);
			
			beginop(OP_callproperty);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
			opcodes.writeU32(argc);
		}
	}

	public void OP_callproplex(int index, int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_callproplex);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
			opcodes.writeU32(argc);
		}
	}

	public void OP_constructprop(int index, int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_constructprop);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
			opcodes.writeU32(argc);
		}
	}

	public void OP_callsuper(int index, int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_callsuper);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
			opcodes.writeU32(argc);
		}
	}

	public void OP_getsuper(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_getsuper);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_setsuper(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_setsuper);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_constructsuper(int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_constructsuper);
			opcodes.writeU32(argc);
		}
	}

	public void OP_pushshort(int n)
	{
		if (opcodePass == 1)
		{
			if (peepHole && n >= -128 && n <= 127)
			{
				OP_pushbyte(n);
				return;
			}
			beginop(OP_pushshort);
			opcodes.writeU32(n);
		}
	}

	public void OP_astype(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_astype);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_astypelate()
	{
		if (opcodePass == 1)
		{
			beginop(OP_astypelate);
		}
	}

	public void OP_coerce(int index)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_coerce && readIntAt(1) == pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index))
			{
				// second coerce to same type is redundant
				return;
			}

			beginop(OP_coerce);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_coerce_b()
	{
		if (opcodePass == 1)
		{
			beginop(OP_coerce_b);
		}
	}

	public void OP_coerce_o()
	{
		if (opcodePass == 1)
		{
			beginop(OP_coerce_o);
		}
	}

	public void OP_coerce_a()
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_coerce_a)
				return;
			beginop(OP_coerce_a);
		}
	}

	public void OP_coerce_i()
	{
		if (opcodePass == 1)
		{
			switch (opat(1))
			{
				case OP_coerce_i :
				case OP_convert_i :
				case OP_increment_i :
				case OP_decrement_i :
				case OP_pushbyte :
				case OP_pushshort :
				case OP_pushint :
				case OP_bitand:
				case OP_bitor:
				case OP_bitxor:
				case OP_lshift:
				case OP_rshift:
				case OP_add_i:
				case OP_subtract_i:
				case OP_multiply_i:
				case OP_bitnot:
					// coerce is redundant
					return;
			}
			beginop(OP_coerce_i);
		}
	}

	public void OP_coerce_u()
	{
		if (opcodePass == 1)
		{
			switch (opat(1))
			{
			case OP_coerce_u:
			case OP_convert_u:
			case OP_urshift:
				// redundant coerce
				return;
			}
			beginop(OP_coerce_u);
		}
	}

	public void OP_coerce_d()
	{
		if (opcodePass == 1)
		{
			switch (opat(1))
			{
				case OP_subtract :
				case OP_multiply :
				case OP_divide :
				case OP_modulo :
				case OP_increment :
				case OP_decrement :
				case OP_inclocal :
				case OP_declocal :
				case OP_coerce_d :
				case OP_convert_d :
					// coerce is redundant
					return;
			}
			beginop(OP_coerce_d);
		}
	}

	public void OP_coerce_s()
	{
		if (opcodePass == 1)
		{
			switch (opat(1))
			{
			case OP_coerce_s:
			case OP_convert_s:
			case OP_pushstring:
			case OP_typeof:
				// result is already string
				return;
			}
			
			if (opat(2) == OP_pushstring && opat(1) == OP_add)
			{
				// result must be string, so dont coerce after
				return;
			}

			beginop(OP_coerce_s);
		}
	}

	public void OP_istype(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_istype);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
		}
	}

	public void OP_istypelate()
	{
		if (opcodePass == 1)
		{
			beginop(OP_istypelate);
		}
	}

	public void OP_pushbyte(int n)
	{
		if (opcodePass == 1)
		{
			if (opat(1) == OP_pushbyte && readByteAt(1) == n ||
				opat(1) == OP_dup && opat(2) == OP_pushbyte && readByteAt(2) == n )
			{
				OP_dup();
				return;
			}
			beginop(OP_pushbyte);
			opcodes.writeU8(n);
		}
	}

	public void OP_getscopeobject(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_getscopeobject);
			opcodes.writeU8(index);
		}
	}

	public void OP_pushscope()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushscope);
		}
	}

	public void OP_popscope()
	{
		if (opcodePass == 1)
		{
			beginop(OP_popscope);
		}
	}

	public void OP_convert_i()
	{
		if (opcodePass == 1)
		{
			switch (opat(1))
			{
			case OP_convert_i:
			case OP_coerce_i:
			case OP_bitand:
			case OP_bitor:
			case OP_bitxor:
			case OP_lshift:
			case OP_rshift:
			case OP_add_i:
			case OP_subtract_i:
			case OP_increment_i:
			case OP_decrement_i:
			case OP_multiply_i:
			case OP_pushbyte:
			case OP_pushshort:
			case OP_pushint:
				return;
			}
			
			beginop(OP_convert_i);
		}
	}

	public void OP_convert_u()
	{
		if (opcodePass == 1)
		{
			beginop(OP_convert_u);
		}
	}

	public void OP_throw()
	{
		if (opcodePass == 1)
		{
			beginop(OP_throw);
		}
	}

	public void OP_instanceof()
	{
		if (opcodePass == 1)
		{
			beginop(OP_instanceof);
		}
	}

	public void OP_in()
	{
		if (opcodePass == 1)
		{
			beginop(OP_in);
		}
	}

	public void OP_dxns(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_dxns);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index));
		}
	}

	public void OP_dxnslate()
	{
		if (opcodePass == 1)
		{
			beginop(OP_dxnslate);
		}
	}

	public void OP_ifnlt(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifnlt);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifnle(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifnle);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifngt(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifngt);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_ifnge(int offset, int pos)
	{
		if (opcodePass == 1)
		{
			beginop(OP_ifnge);
			opcodes.writeS24(offset);
			opcodes.mapOffsets(pos);
		}
		else if (opcodePass == 2)
		{
			opcodes.updateOffset(pos + offset);
		}
	}

	public void OP_pushwith()
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushwith);
		}
	}

	public void OP_newactivation()
	{
		if (opcodePass == 1)
		{
			beginop(OP_newactivation);
		}
	}

	public void OP_newcatch(int index)
	{
		if (opcodePass == 1)
		{
			beginop(OP_newcatch);
			opcodes.writeU32(index);			
		}
	}

	public void OP_deldescendants()
	{
		if (opcodePass == 1)
		{
			beginop(OP_deldescendants);
		}
	}

	public void OP_getglobalscope()
	{
		if (opcodePass == 1)
		{
			beginop(OP_getglobalscope);
		}
	}

	public void OP_getlocal0()
	{
		if (opcodePass == 1)
		{
			beginop(OP_getlocal0);
		}
	}

	public void OP_getlocal1()
	{
		if (opcodePass == 1)
		{
			beginop(OP_getlocal1);
		}
	}

	public void OP_getlocal2()
	{
		if (opcodePass == 1)
		{
			beginop(OP_getlocal2);
		}
	}

	public void OP_getlocal3()
	{
		if (opcodePass == 1)
		{
			beginop(OP_getlocal3);
		}
	}

	public void OP_setlocal0()
	{
		if (opcodePass == 1)
		{
			beginop(OP_setlocal0);
		}
	}

	public void OP_setlocal1()
	{
		if (opcodePass == 1)
		{
			if (opat(2) == OP_getlocal1 && opat(1) == OP_increment_i)
			{
				rewind(2);
				OP_inclocal_i(1);
				return;
			}
			if (opat(2) == OP_getlocal1 && opat(1) == OP_increment)
			{
				rewind(2);
				OP_inclocal(1);
				return;
			}
			beginop(OP_setlocal1);
		}
	}

	public void OP_setlocal2()
	{
		if (opcodePass == 1)
		{
			if (opat(2) == OP_getlocal2 && opat(1) == OP_increment_i)
			{
				rewind(2);
				OP_inclocal_i(2);
				return;
			}
			if (opat(2) == OP_getlocal2 && opat(1) == OP_increment)
			{
				rewind(2);
				OP_inclocal(2);
				return;
			}
			beginop(OP_setlocal2);
		}
	}

	public void OP_setlocal3()
	{
		if (opcodePass == 1)
		{
			if (opat(2) == OP_getlocal3 && opat(1) == OP_increment_i)
			{
				rewind(2);
				OP_inclocal_i(3);
				return;
			}
			if (opat(2) == OP_getlocal3 && opat(1) == OP_increment)
			{
				rewind(2);
				OP_inclocal(3);
				return;
			}
			beginop(OP_setlocal3);
		}
	}
	
	public void OP_label()
	{
		if (opcodePass == 1)
		{
			beginop(OP_label);
		}
	}

	public void OP_pushconstant(int id)
	{
		if (opcodePass == 1)
		{
			beginop(OP_pushuninitialized);
			opcodes.writeU32(id);
		}
	}

	public void OP_callsupervoid(int index, int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_callsupervoid);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
			opcodes.writeU32(argc);
		}
	}

	public void OP_callpropvoid(int index, int argc)
	{
		if (opcodePass == 1)
		{
			beginop(OP_callpropvoid);
			opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index));
			opcodes.writeU32(argc);
		}
	}

    public void OP_li8()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_li8);
        }
    }

    public void OP_li16()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_li16);
        }
    }

    public void OP_li32()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_li32);
        }
    }

    public void OP_lf32()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_lf32);
        }
    }

    public void OP_lf64()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_lf64);
        }
    }

    public void OP_si8()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_si8);
        }
    }

    public void OP_si16()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_si16);
        }
    }

    public void OP_si32()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_si32);
        }
    }

    public void OP_sf32()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_sf32);
        }
    }

    public void OP_sf64()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_sf64);
        }
    }

    public void OP_sxi1()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_sxi1);
        }
    }

    public void OP_sxi8()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_sxi8);
        }
    }

    public void OP_sxi16()
    {
        if( opcodePass == 1 )
        {
            beginop(OP_sxi16);
        }
    }

    class ByteArrayPool2 extends ByteArrayPool
    {
        ByteArrayPool2(int[] sizes)
        {
            this.sizes = sizes;
            indexes = new HashMap<Integer, Integer>();
        }

        int size = 0;

        private int[] sizes;

        private Map<Integer, Integer> indexes;

        int addByteArray(int poolIndex, int oldIndex, BytecodeBuffer ba)
        {
            int index = this.contains(ba, 0, ba.size());
            if( index == -1 )
            {
                index = this.store(ba, 0, ba.size());
                size += ba.size();
            }
            // ByteArrayPool is 1 based, we want zero based for metadataInfos
            indexes.put(IntegerPool.getNumber(calcIndex(poolIndex, oldIndex)), IntegerPool.getNumber(index-1));
            return index;
        }

        private int calcIndex(int poolIndex, int oldIndex)
        {
            int newIndex = 0;
            for (int i = 0; i < poolIndex; i++)
            {
                newIndex += sizes[i];
            }
            newIndex += oldIndex;

            return newIndex;
        }

        int getIndex(int poolIndex, int oldIndex)
        {
            int newIndex = calcIndex(poolIndex, oldIndex);
            Integer i = indexes.get(IntegerPool.getNumber(newIndex));
            return i != null ? i.intValue() : -1;
        }

        int size()
        {
            return size;
        }

        void writeTo(BytecodeBuffer b)
        {
            Map sortedMap = new TreeMap();

            for (Iterator i = map.keySet().iterator(); i.hasNext();)
            {
                Object key = i.next(); // ByteArray
                Object value = map.get(key); // Integer
                sortedMap.put(value, key);
            }

            b.writeU32((sortedMap.size() == 0) ? 0 : sortedMap.size() );

            for (Iterator i = sortedMap.keySet().iterator(); i.hasNext();)
            {
                Integer index = (Integer) i.next();
                ByteArray a = (ByteArray) sortedMap.get(index);
                b.writeBytes(a.b, a.start, a.end);
            }
        }

        void writeTo(OutputStream os) throws java.io.IOException
        {
            BytecodeBuffer b = new BytecodeBuffer(size());
            writeTo(b);
            b.writeTo(os);
        }
    }

	class BytecodeBuffer2 extends BytecodeBuffer
	{
		BytecodeBuffer2(int estimatedSize, int[] sizes)
		{
			super(estimatedSize);
			this.sizes = sizes;
			this.estimatedSize = estimatedSize;
		}

		private int[] sizes;
		int estimatedSize;

		int getIndex(int poolIndex, int oldIndex)
		{
			int newIndex = 0;
			for (int i = 0; i < poolIndex; i++)
			{
				newIndex += sizes[i];
			}
			newIndex += oldIndex;

			return newIndex;
		}
	}

	class BytecodeBuffer3 extends BytecodeBuffer
	{
		BytecodeBuffer3(Decoder[] decoders, int estimatedSize)
		{
			super(estimatedSize);
			offsets = new HashMap<Integer, Integer>();
			this.decoders = decoders;
		}

		Map<Integer, Integer> offsets;
		Decoder[] decoders;

		void mapOffsets(long offset)
		{
			Integer oldPos = IntegerPool.getNumber((int) offset);
			Integer newPos = IntegerPool.getNumber(size());

			offsets.put(IntegerPool.getNumber(oldPos), IntegerPool.getNumber(newPos));
		}

		long getOffset(long offset)
		{
			Integer i = offsets.get(IntegerPool.getNumber((int) offset));
			if (i != null)
			{
				return i.intValue();
			}
			else
			{
				System.out.println("getOffset: can't match " + offset + " with a new offset ");
				System.out.println(offsets);
				return 0;
			}
		}

		void updateOffset(long offset)
		{
			Integer i = offsets.get(IntegerPool.getNumber((int) offset));
			Integer p = offsets.get(IntegerPool.getNumber(decoders[poolIndex].pos()));

			if (i != null && p != null)
			{
				writeS24(p-3, i-p);
			}
			else
			{
				/* cn: temporarily disable this warning.  The warnings that are being generated are
				 *     for jumps which are part of unreachable code, but I haven't found where those
				 *     unecessary jumps are being genreated within codeGenerator yet.  Disabling to redeuce
				 *     annoyance in the short term, 
				 *     bug #149141 remains open until the root cause is found and removed
				if (i == null)
					System.out.println("updateOffset1: can't match i " + offset + " with a new offset");
				if (p == null)
					System.out.println("updateOffset1: can't match p " + decoders[poolIndex].pos() + " with a new offset");
				System.out.println(offsets);
				*/
			}
		}

		void updateOffset(long oldOffsetPos, long oldPos, long oldTarget)
		{
			Integer i = offsets.get(IntegerPool.getNumber((int) oldTarget));
			Integer p = offsets.get(IntegerPool.getNumber((int) oldPos));
			Integer s = offsets.get(IntegerPool.getNumber((int) oldOffsetPos));

			if (i != null && p != null && s != null)
			{
				writeS24(s, i-p);
			}
			else
			{
				if (i == null)
					System.out.println("updateOffset2: can't match i " + oldTarget + " with a new offset");
				if (p == null)
					System.out.println("updateOffset2: can't match p " + oldPos + " with a new offset");
				if (s == null)
					System.out.println("updateOffset2: can't match s " + oldOffsetPos + " with a new offset");
				System.out.println(offsets);
			}
		}

		public void clear()
		{
			super.clear();
			offsets.clear();
		}
	}
}

