/*
 *
 *  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 adobe.abc;

import java.io.*;

//  Note: java.util imports must be explicitly called out because
//  "import java.util.*" conflicts with adobe.abc.Algorithms.Deque
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;


import macromedia.asc.embedding.ConfigVar;
import macromedia.asc.util.ObjectList;

import static macromedia.asc.embedding.avmplus.ActionBlockConstants.*;
import static adobe.abc.Algorithms.*;
import static adobe.abc.OptimizerConstants.*;
import static adobe.abc.TypeAnalysis.*;
import static java.lang.Boolean.TRUE;
import static java.lang.Boolean.FALSE;

/*
 * TODO
 * 
 * (done) merge phi nodes
 * (done) pretty print dags
 * (done) scope capture
 * (done) type tracking
 * (done) constness
 * (done) null tracking
 * (done) emitter
 * (done) convert lvn into dominator based dvn
 * (done) sort cpool entries by frequency of use
 * (done) eliminate unused cpool entries
 * (done) split dag nodes to tree nodes
 * (done) recalc local_count
 * (done) recalc max_stack
 * (done) recalc scope_depth
 * (done) allow nonempty stack between blocks - stk_sched2 
 * (done) give every slot a default value even if not from abc (vm-defined defaults)
 * (done) model exception edges, remove PURE
 * (done) flesh out branch simplifications in sccp
 * (done) respect try/catch regions
 * (done) don't assign local to OP_arg in catch.  use arg & xarg
 * (done) if N handlers specify the same catch block, ensure phi's merge args correctly.
 * (done) strip unnecessary slot default values on export
 * (done) preserve metadata
 * (done) expand getlex to expose redundant findproperty 
 * (done) add null-ness to sccp lattice, remove NOTNULL flag
 * (done) handle lt/gt correctly for strings
 * (done) hasnext2 codegen
 * (done) combine findpropstrict+getproperty into getlex when find's only use is get in same block.
 * (done) normalize inc/declocal/_i into inc/decrement/_i
 * 
 * force stkout contents for xarg blocks rather than clearing stack at xarg definition.
 * don't allow xarg block to be combined with other blocks.
 * handle OP_equals for all const types
 * istype optimizations
 * model external data dependencies, remove EFFECT
 * treat pushwith & pushscope appropriately in findprop
 * expand implicit conversions to expose them to optimizations
 * fold implicit conversions to reduce code size
 * use locals for activation slots that dont escape (need array ssa?)
 * algebraic identities
 * combine sccp values & types into single lattice
 * add final-ness to Typeref
 * interprocedural analysis to determine effect of functions
 * check (prove?) correctness of SKIPTEST
 * insert kills & coerces to appease AVM verifier
 * add a no-catch edge to an EXIT block for any block with a PX expr.
 * if we have catch blocks, any PX should end its block.  (FCFG notation is premature)
 * preds should include all edges, not just normal edges
 * script loading dependencies.  remove EFFECT from findprop/finddef if script is already loaded.
 * convert chain of ifstricne<int> into switch if ints are dense
 * write a verifier (easier than testing with actual avm)
 * merge scripts based on init dependencies.
 * in scheduler, propagate live & stk across exception edges
 * get smarter about removing phi(coerce) without losing verifiability
 * scope stack scheduling
 * turn add into increment/_i when possible
 * turn increment/decrement/_i into inc/declocal/_i if in/out assigned to same local in sched.
 * inline method if target is known and body is smaller than call (eg isNaN, trivial getters)
 * 
 * TODO algorithms
 * 
 * partial redundancy elimination
 * alias analysis
 * tail merging
 * loop inversion
 * remove redundant path expressions
 *
 * TODO file format changes
 * 
 * remove/shorten version number
 * short branch offsets
 * optional init methods
 * every reference is a relative offset (eliminate lookup tables)
 * remove empty activation traits
 * optional trait names
 * OP_add_d
 * OP_concat
 */


public class GlobalOptimizer
{
	// default configuration flags
	final boolean USE_CALLMETHOD = false;
	final boolean SHOW_CODE = true;
	final boolean SHOW_DOMINATORS=false;
	
	//  Configuration flags settable by options
	boolean OUTPUT_DOT = false;
	boolean SHOW_DFG =  false;
	boolean STRIP_DEBUG_INFO = true;
	boolean ALLOW_NATIVE_CTORS = false;
	boolean PRESERVE_METHOD_NAMES = false;
	
	boolean verbose_mode=false;
	boolean legacy_verifier=false;  
	
	//  TODO: Needs more work to get right --
	//  reading everything in-line means we're
	//  never really sure if something's an
	//  import or not b/c $GLOBALABC is processed
	//  as a target in its own right during 
	//  the tamarin build.
	//  Have to organize the files list ahead
	//  of the read phase, would also help 
	//  integration with the ASC entry point.
	boolean reading_imports = true;
	
	/**
	 *   The number of input files being linked together.
	 *   @warn used to work around some linking bugs.
	 */
	int num_linked_files = 0;
	
	static TraceManager tm = new TraceManager();

	public static void main(String[] args) throws IOException
	{
		GlobalOptimizer go = new GlobalOptimizer();
		
 		List<InputAbc> a = new ArrayList<InputAbc>();
 		List<Integer> lengths = new ArrayList<Integer>();
		String filename = null;
		byte[] before = null;
		//  Index of first export in the file list.
		int first_exported_file = 0;
 		boolean obscure_natives = false; 
 		boolean no_c_gen = false; 
		boolean quiet_mode = false;

		for (int i = 0; i < args.length; ++i)
		{
 			if(args[i].equals("-obscure_natives")) {
				obscure_natives = true;
 				continue;
 			}
 			if(args[i].equals("-no_c_gen")) {
				no_c_gen = true;
 				continue;
 			}
			if(args[i].equals("-d")) {
				go.STRIP_DEBUG_INFO=false;
				continue;
			}
			if(args[i].equals("-verbose")) {
				go.verbose_mode = true;
				quiet_mode = false;
				continue;
			}
			if ( args[i].equals("-quiet"))
			{
				quiet_mode = true;
				go.verbose_mode = false;
				continue;
			}
			if ( args[i].equals("-legacy_verifier"))
			{
				go.legacy_verifier = !go.legacy_verifier;
				addTraceAttr("legacy_verifier", go.legacy_verifier);
				go.verboseStatus("legacy_verifier set to " + go.legacy_verifier);
				continue;
			}
			if ( args[i].equals("-allow_native_ctors"))
			{
				go.ALLOW_NATIVE_CTORS = true;
				continue;
			}
			if ( args[i].equals("-trace") && i+1 < args.length )
			{
				i++;
				tm.enable(new PrintWriter(new FileWriter(args[i])));

				addTraceAttr("timestamp", new Date());
				continue;
			}
			if ( args[i].equals("-dot") )
			{
				go.OUTPUT_DOT = true;
				continue;
			}
			if ( args[i].equals("-dfg"))
			{
				go.SHOW_DFG = go.OUTPUT_DOT =  true;
				continue;
			}
			if ( args[i].equals("-preserve_method_names"))
			{
				go.PRESERVE_METHOD_NAMES = true;
				continue;
			}
			if ( args[i].equals("-plugin") && i+1 < args.length)
			{
				i++;
				go.loadPlugin(args[i]);
				continue;
			}
			if ( args[i].startsWith("-") && args[i].contains(":"))
			{
				int delim_pos = args[i].indexOf(':');
				String plugin_name   = args[i].substring(1, delim_pos);
				String plugin_option = args[i].substring(delim_pos+1);
				
				PluginData plugin_data = go.analysis_phase_plugins.get(plugin_name);
				
				if ( null == plugin_data )
				{
					//  Iterate over the plugins and find a short
					//  name that matches this monster.
					
					for ( PluginData search_plugin: go.analysis_phase_plugins.values() )
					{
						if ( search_plugin.plugin.getClass().getSimpleName().equals(plugin_name))
						{
							plugin_data = search_plugin;
							break;
						}
					}
				}
				
				if ( null != plugin_data )
				{
					plugin_data.options.add(plugin_option);
				}
				else
				{
					throw new IllegalArgumentException("No plugin named " + plugin_name + " is loaded.");		
				}
				
				continue;
			}

			if(args[i].equals("--")) 
			{
				go.reading_imports = false;
				first_exported_file = a.size();
				continue;
            }

			filename = args[i];

			addTraceAttr("filename", filename);
			
			InputAbc ia = go.new InputAbc();
			lengths.add(ia.readAbc(filename));
			a.add(ia);
			if(obscure_natives) {
				ia.obscure_natives();
				obscure_natives = false;
			}
			

		}

		if ( 0 == args.length || first_exported_file >= a.size() )
		{
			System.err.println("usage: GlobalOptimizer [-obscure_natives] [-no_c_gen] [-verbose] [-quiet] [imports] -- [exports]");
			return;
		}
		
		go.initializePlugins();
		
		// merge exports together
		// TODO this is not right, it only works for builtin ABCs and only under TT...
		// we really need to construct a new script (that calls all the scripts in the initScripts list)
		// and append it to the end as the new initscript.
		List<Integer> initScripts = new ArrayList<Integer>();
		InputAbc first = a.get(first_exported_file);
 		int before_length = lengths.get(first_exported_file);
		initScripts.add(first.scripts.length - 1);

		//  Combine other exported files.
		for(int i=first_exported_file+1; i < a.size(); i++) 
		{
			first.combine(a.get(i));
			initScripts.add(first.scripts.length - 1);
			before_length += lengths.get(i);
			go.num_linked_files++;
		}
		
		// Optimize the combined ABC file and emit.
		byte[] after = null;

		go.optimize(first);
		after = go.emit(first, filename, initScripts, no_c_gen);
		


		
		//  Print summary statistics.
		if ( ! quiet_mode )
		{
			System.out.println();
			System.out.println("Before optimization: "+before_length);
			System.out.println("After optimization:  "+after.length);
			int delta = before_length - after.length;
			long percent = Math.round(delta/(double)before_length*100);
			System.out.println("Difference:  "+delta+ " "+percent+"%");
		}
	}

	static byte[] load(String filename) throws IOException
	{
		InputStream in = new FileInputStream(filename);
		try
		{
			byte[] before = new byte[in.available()];
			in.read(before);
			return before;
		}
		finally
		{
			in.close();
		}
	}
	
	class PluginData
	{
		OptimizerPlugin plugin;
		Vector<String>  options;
		
		PluginData(OptimizerPlugin plugin)
		{
			this.plugin  = plugin;
			this.options = new Vector<String>();
		}
	}
	private Map<String, PluginData> analysis_phase_plugins = new HashMap<String, PluginData>();
	
	private void loadPlugin(String plugin_class_fqn)
	{
		try
		{
			Class clazz = Class.forName(plugin_class_fqn);
			
			OptimizerPlugin plugin = (OptimizerPlugin)clazz.newInstance();
			analysis_phase_plugins.put(plugin_class_fqn, new PluginData(plugin));
		}
		catch ( Throwable plugin_trouble)
		{
			System.err.println("Unable to initialize plugin " + plugin_class_fqn + " due to: " + plugin_trouble);
		}
	}
	
	private void initializePlugins()
	{
		for ( String plugin_name: analysis_phase_plugins.keySet())
		{
			PluginData p = analysis_phase_plugins.get(plugin_name);
			p.plugin.initializePlugin(this, p.options);
		}
	}
	
	private void runPlugins()
	{
	}

	public class InputAbc
	{
		String strings[];
		int ints[];
		long uints[];
		double doubles[];
		Namespace namespaces[];
		Nsset nssets[];
		Name names[];
		Method methods[];
		Metadata metadata[];
		Type classes[];
		Type scripts[];
		boolean containsObject = false;
		
		Set<Type> toResolve;
		List<InputAbc> mergedAbcs = new ArrayList<InputAbc>();
		public String src_filename;
		
		InputAbc()
		{
			mergedAbcs.add(this);
		}
		
		Type lookup(int id)
		{
			if (0 == id)
				return ANY();
			else
				return TypeCache.instance().lookup(names[id], OBJECT());
		}

		int readAbc(String src_file) throws IOException
		{
			byte[] file_buffer = load(src_file);
			readAbc(file_buffer);

			return file_buffer.length;
		}

		void readAbc(byte[] abc) throws IOException
		{
			Reader p = new Reader(0, abc);
			if (p.readU16() != 16 || p.readU16() != 46)
				throw new RuntimeException("not an abc file");
		
			ints = new int[p.readU30() + 1];
			for (int i = 1, n = ints.length - 1; i < n; i++)
				ints[i] = p.readU30();
		
			uints = new long[p.readU30() + 1];
			for (int i = 1, n = uints.length - 1; i < n; i++)
				uints[i] = 0xffffffffL & p.readU30();
		
			doubles = new double[p.readU30() + 1];
			for (int i = 1, n = doubles.length - 1; i < n; i++)
				doubles[i] = p.readDouble();
		
			strings = new String[p.readU30() + 1];
			strings[0] = "";
			for (int i = 1, n = strings.length - 1; i < n; i++)
			{
				int len = p.readU30();
				strings[i] = new String(abc, p.pos, len, "UTF-8");
				p.pos += len;
			}
		
			namespaces = new Namespace[p.readU30() + 1];
			// TODO this should be AnyNamespace, not PUBLIC
			namespaces[0] = Name.PUBLIC;
			for (int i = 1, n = namespaces.length - 1; i < n; i++)
				namespaces[i] = new Namespace(p.readU8(), strings[p.readU30()]);
		
			nssets = new Nsset[p.readU30() + 1];
			for (int i = 1, n = nssets.length-1; i < n; i++)
			{
				nssets[i] = new Nsset(new Namespace[p.readU30()]);
				for (int j = 0, m = nssets[i].length; j < m; j++)
					nssets[i].nsset[j] = namespaces[p.readU30()]; // ns_index
			}
		
			names = new Name[p.readU30() + 1];
			for (int i = 1, n = names.length-1; i < n; i++)
			{
				names[i] = readName(p);
			}
		
			methods = new Method[p.readU30()];
			int[] methodpos = new int[methods.length];
			for (int i = 0, n = methods.length; i < n; i++)
				methods[i] = readMethod(p, methodpos, i);
		
			metadata = new Metadata[p.readU30()];
			for (int i = 0, n = metadata.length; i < n; i++)
				metadata[i] = readMetadata(p);
		
			toResolve = new HashSet<Type>();
		
			Type[] instances = new Type[p.readU30()];
			for (int i = 0, n = instances.length; i < n; i++)
				instances[i] = readInstance(p);
			
			if ( containsObject )
				TypeCache.instance().setupBuiltins();
				
			// finish resolving methods using mp we saved earlier
			for (int i=0, n = methods.length; i < n; i++)
				resolveSignatureType(new Reader(methodpos[i], p.abc), i, methods[i]);
			
			classes = new Type[instances.length];
			for (int i = 0, n = classes.length; i < n; i++)
				classes[i] = readClass(p, instances[i]);
			
			scripts = new Type[p.readU30()];
			for (int i = 0, n = scripts.length; i < n; i++)
				scripts[i] = readScript(p, i);

			for (int i = 0, n = p.readU30(); i < n; i++)
				readBody(p);
			
			// lazy resolve slot type names
			for (Type t: toResolve)
				resolveType(t);
			
			toResolve = null;
		}
		
		void obscure_natives()
		{
			for(Type t: classes) {
				t.obscure_natives = true;
				if (t.itype != null)
					t.itype.obscure_natives = true;
			}
			for(Type t: scripts) {
				t.obscure_natives = true;
				if (t.itype != null)
					t.itype.obscure_natives = true;
			}
		}
		
		void combine(InputAbc abc)
		{
			int[] newInts = new int[ints.length + abc.ints.length];
			System.arraycopy(ints, 0, newInts, 0, ints.length);
			System.arraycopy(abc.ints, 0, newInts, ints.length, abc.ints.length);
			ints = newInts;

			long[] newUints = new long[uints.length + abc.uints.length];
			System.arraycopy(uints, 0, newUints, 0, uints.length);
			System.arraycopy(abc.uints, 0, newUints, uints.length, abc.uints.length);
			uints = newUints;

			double[] newDoubles = new double[doubles.length + abc.doubles.length];
			System.arraycopy(doubles, 0, newDoubles, 0, doubles.length);
			System.arraycopy(abc.doubles, 0, newDoubles, doubles.length, abc.doubles.length);
			doubles = newDoubles;		
			
			String[] newStrings = new String[strings.length + abc.strings.length];
			System.arraycopy(strings, 0, newStrings, 0, strings.length);
			System.arraycopy(abc.strings, 0, newStrings, strings.length, abc.strings.length);
			strings = newStrings;
			
			Namespace[] newNamespaces = new Namespace[namespaces.length + abc.namespaces.length];
			System.arraycopy(namespaces, 0, newNamespaces, 0, namespaces.length);
			System.arraycopy(abc.namespaces, 0, newNamespaces, namespaces.length, abc.namespaces.length);
			namespaces = newNamespaces;
			
			Nsset[] newNssets = new Nsset[nssets.length + abc.nssets.length];
			System.arraycopy(nssets, 0, newNssets, 0, nssets.length);
			System.arraycopy(abc.nssets, 0, newNssets, nssets.length, abc.nssets.length);
			nssets = newNssets;
			
			Name[] newNames = new Name[names.length + abc.names.length];
			System.arraycopy(names, 0, newNames, 0, names.length);
			System.arraycopy(abc.names, 0, newNames, names.length, abc.names.length);
			names = newNames;
			
			Method[] newMethods = new Method[methods.length + abc.methods.length];
			System.arraycopy(methods, 0, newMethods, 0, methods.length);
			System.arraycopy(abc.methods, 0, newMethods, methods.length, abc.methods.length);
			methods = newMethods;
			
			// we change the .abc property for Methods but not Bindings, canEarlyBind* 
			// deals with this by checking that Binding.abc is in the Method.abc.mergedAbcs set
			for(Method m: abc.methods) {
				m.abc = this;
			}

			Metadata[] newMetadata = new Metadata[metadata.length + abc.metadata.length];
			System.arraycopy(metadata, 0, newMetadata, 0, metadata.length);
			System.arraycopy(abc.metadata, 0, newMetadata, metadata.length, abc.metadata.length);
			metadata = newMetadata;

			Type[] newClasses = new Type[classes.length + abc.classes.length];
			System.arraycopy(classes, 0, newClasses, 0, classes.length);
			System.arraycopy(abc.classes, 0, newClasses, classes.length, abc.classes.length);
			classes = newClasses;
			
			Type[] newScripts = new Type[scripts.length + abc.scripts.length];
			System.arraycopy(scripts, 0, newScripts, 0, scripts.length);
			System.arraycopy(abc.scripts, 0, newScripts, scripts.length, abc.scripts.length);
			scripts = newScripts;
			
			mergedAbcs.add(abc);
		}
		
		void resolveType(Type t)
		{
			if (t.size != 0)
				return;
			int size = 0;
			if (t.base != null)
			{
				resolveType(t.base);
				size = t.base.size;
			}
			int hole = -1;
			for (Binding b: t.defs.values())
			{
				if (isSlot(b))
				{
					if (!isClass(b))
						resolveSlotType(b);
					// NOTE NOTE NOTE NOTE NOTE
					// NOTE NOTE NOTE NOTE NOTE
					// NOTE NOTE NOTE NOTE NOTE
					// NOTE NOTE NOTE NOTE NOTE
					//
					// the logic here is replicated in QVM and GlobalOptimizer.java and is assumed by the slot offsets
					// that it generates for native classes. If you change this here you must also change it there.
					//
					// NOTE NOTE NOTE NOTE NOTE
					// NOTE NOTE NOTE NOTE NOTE
					// NOTE NOTE NOTE NOTE NOTE
					// NOTE NOTE NOTE NOTE NOTE
					// NOTE NOTE NOTE NOTE NOTE
					//
					// @todo, this generates slots that are correct for 32-bit but not 64 bit builds
					//
					if (b.type.t == NUMBER())
					{
						if (size%8 != 0)
						{
							hole = size;
							size += 4;
						}
						b.offset = size;
						size += 8;
					}
					else
					{
						if (hole != -1)
						{
							b.offset = hole;
							hole = -1;
						}
						else
						{
							b.offset = size;
							size += 4;
						}
					}
				}
			}
			if (size > 0)
				verboseStatus("sizeof "+t+" "+size);
			t.size = size;
		}

		Metadata readMetadata(Reader p)
		{
			Metadata md = new Metadata();
			md.name = strings[p.readU30()];
			Attr[] attrs = md.attrs = new Attr[p.readU30()];
			for (int j = 0, n=attrs.length; j < n; j++)
				attrs[j] = new Attr(strings[p.readU30()]);
			for (int j = 0, n=attrs.length; j < n; j++)
				attrs[j].value = strings[p.readU30()];
			return md;
		}
		
		void resolveSignatureType(Reader p, int i, Method m)
		{
			m.returns = lookup(p.readU30()).ref; // return type
			
			//  Parameter types must be nullable
			//  to satisfy the AVM verifier.
			for (int j = 1; j < m.getParams().length; j++)
			{
				int idx = p.readU30();
				Type ptype = lookup(idx);
				assert(ptype != null);
				m.getParams()[j] = ptype.ref.nullable();
			}

			p.readU30(); // debug name
			p.readU8(); // flags
			
			if (m.hasOptional())
			{
				m.optional_count = p.readU30();
				
				m.values = new Object[m.getParams().length];
				
				int first_optional_param = m.getParams().length - m.optional_count;
				
				for (int j = first_optional_param; j < m.getParams().length; j++)
				{
					m.values[j] = readArgDefault(p);
					assert(m.values[j] != null);
				}
			}
		}

		void readBody(Reader p)
		{
			Method m = methods[p.readU30()];

			addTraceAttr("method", m);
			m.max_stack = p.readU30();
			m.local_count = p.readU30();
			m.max_scope = -(p.readU30()-p.readU30());
			m.code_len = p.readU30();
			Reader pcode = new Reader(p);
			p.pos += m.code_len;
			readCode(m, pcode, p);
			Type act = new Type();
			m.activation = act.ref.nonnull();
			act.base = ANY();
			if (m.getName() != null)
				act.name = (m.getName().append(" activation"));
			readTraits(p, act);

		}


		Method readMethod(Reader p, int[] methodpos, int i)
		{
			Method m = new Method(i, this);
			int param_count = p.readU30();
			m.params = new Typeref[param_count+1];
			m.getParams()[0] = ANY().ref;
			methodpos[i] = p.pos;
			p.readU30(); // return type
			for (int j = 1; j <= param_count; j++)
				p.readU30(); // param type
			
			//  debugName is specified as a bare index into the string pool.
			m.debugName = strings[p.readU30()]; 
			m.name = new Name(m.debugName);
			
			m.flags = p.readU8();

			if (m.hasOptional())
			{
				//  Skip past optional parameters; they're re-read
				//  and recorded in resolveSignatureType().
				int optional_count = p.readU30();
				assert(optional_count > 0);

				for (int j = 0; j < optional_count; j++)
				{
					readArgDefault(p);
				}
			}
			if (m.hasParamNames())
			{
				m.paramNames = new Name[param_count+1];
				for (int j = 1; j <= param_count; j++)
					m.paramNames[j] = new Name(strings[p.readU30()]);
			}
			return m;
		}
		
		Name readName(Reader p)
		{
			int kind = p.readU8();
			switch (kind)
			{
			default:
				throw new RuntimeException("Unknown name kind: "+kind);
			case CONSTANT_TypeName:
			{
				int index = p.readU30();	// Index to the Multiname type, i.e. Vector
				int count = p.readU30();	// number of type parameter names
				assert(count == 1);			// all we support for now
				int typeparm = p.readU30();	// Multinames for the type parameters, i.e. String for a Vector.<String>
				Name mn = this.names[index];
				Name type_param = this.names[typeparm];
				return new Name(kind, mn.name, mn.nsset, type_param.name);
			}
			case CONSTANT_Qname:
			case CONSTANT_QnameA:
				return new Name(kind, namespaces[p.readU30()], strings[p.readU30()]);
			case CONSTANT_Multiname:
			case CONSTANT_MultinameA:
				return new Name(kind, strings[p.readU30()], nssets[p.readU30()]);
			case CONSTANT_RTQname:
			case CONSTANT_RTQnameA:
				return new Name(kind, uniqueNs(), strings[p.readU30()]);
			case CONSTANT_MultinameL:
			case CONSTANT_MultinameLA:
				return new Name(kind, unique(), nssets[p.readU30()]);
			case CONSTANT_RTQnameL:
			case CONSTANT_RTQnameLA:
				return new Name(kind);
			}
		}
		
		void readTraits(Reader p, Type t)
		{
			toResolve.add(t);
			t.defs = new Symtab<Binding>();
			
			//  Start counting slots either from
			//  the base type's last-used slot 
			//  or from zero if there's no base.
			int slot_id = (t.base != null)? t.base.slotCount: 0;

			//  Slots used by this type.
			int count = p.readU30();
			
			for (int i = 0; i < count; i++)
			{
				Name name = names[p.readU30()];
				Binding b = new Binding(p.readU8(), name, this);
				Binding old = t.defs.get(name);
				
				while (old != null && old.peer != null)
					old = old.peer;
				if (old != null)
					old.peer = b;

				t.defs.put(name, b);
				int slot = p.readU30(); // slot_id | disp_id
				b.id = p.readU30(); // typename | class_id | method_id
				switch (b.kind())
				{
				case TRAIT_Var:
				case TRAIT_Const:
				case TRAIT_Class:
					if (isClass(b))
					{
						// TODO this is a bit tenuous
						b.type = classes[b.id].ref.nonnull();
						b.value = NULL();
					}
					else
					{
						b.value = readSlotDefault(p);
						b.type = ANY().ref;
						if (b.value instanceof Namespace)
							TypeCache.instance().namespaceNames.put((Namespace)b.value, name);
					}

					// TODO add vm's logic to accept or ignore compiler-assigned slot_id
					if (slot == 0)
						slot = ++slot_id;
					else if (slot > slot_id)
						slot_id = slot;
					b.slot = slot;
					break;
				case TRAIT_Method:
				case TRAIT_Getter:
				case TRAIT_Setter:
					b.slot = 0;
					Method m = b.method = methods[b.id];
					m.cx = t;
					m.getParams()[0] = t.ref.nonnull();
					m.kind = isMethod(b) ? "function" : isGetter(b) ? "get" : "set";
					m.name = name;
					// ignore compiler-assigned disp_id's
					// if (!slot) slot = ++disp_id;
					// else if (slot > disp_id) disp_id = slot;
					break;
				default:
					System.err.println("illegal trait kind " + b.kind() + " at offset " + p.pos);
					assert (false);
				}

				if (b.hasMetadata())
				{
					b.md = new Metadata[p.readU30()];
					for (int j=0, m=b.md.length; j < m; j++)
						b.md[j] = metadata[p.readU30()];
				}
			}
			t.slotCount = slot_id;
		}
		
		Object readSlotDefault(Reader p)
		{
			int i = p.readU30();
			if (i != 0)
			{
				int kind = p.readU8();
				return defaultValue(kind,i);
			}
			return null;
		}
		
		Object readArgDefault(Reader p)
		{
			int i = p.readU30();
			int kind = p.readU8();
			Object v = defaultValue(kind, i);
			return v;
		}
		
		Object defaultValue(int kind, int i)
		{
			switch (kind)
			{
			case CONSTANT_False:
				return FALSE;
			case CONSTANT_True:
				return TRUE;
			case CONSTANT_Null:
				return NULL();
			case CONSTANT_Void:
				return UNDEFINED;
			case CONSTANT_Utf8:
				return strings[i];
			case CONSTANT_Integer:
				return ints[i];
			case CONSTANT_UInteger:
				return uints[i];
			case CONSTANT_Double:
				return doubles[i];
			case CONSTANT_Namespace:
			case CONSTANT_PackageNamespace:
			case CONSTANT_ProtectedNamespace:
			case CONSTANT_PackageInternalNs:
			case CONSTANT_ExplicitNamespace:
			case CONSTANT_StaticProtectedNs:
			case CONSTANT_PrivateNamespace:
				return namespaces[i];
			}
			assert(false);
			return null;
		}

		void resolveSlotType(Binding b)
		{
			b.type = lookup(b.id).ref;
			if (b.value == null)
				b.value = b.type.t.defaultValue;
		}

		Type readScript(Reader p, int i)
		{
			Type s = new Type();
			assert(OBJECT() != null);
			s.base = OBJECT();
			s.name = new Name("global"+i);
			Method init = s.init = methods[p.readU30()]; // init_id
			init.cx = s;
			Typeref sref = s.ref.nonnull();
			init.getParams()[0] = sref;
			init.name = s.getName();
			init.kind = "init";
			readTraits(p, s);
			for (Binding b : s.defs.values())
				TypeCache.instance().globals.put(b.getName(), sref);
			s.setFinal();
			return s;
		}

		Type readClass(Reader p, Type it)
		{
			Type c = new Type();
			assert(CLASS() != null);
			c.base = CLASS();
			c.itype = it;
			c.name = it.getName().append("$");
			Method init = c.init = methods[p.readU30()]; // init_id
			init.cx = c;
			init.getParams()[0] = c.ref.nonnull();
			init.name = c.getName();
			init.kind = "init";
			readTraits(p, c);
			c.setFinal();
			return c;
		}

		Type readInstance(Reader p)
		{
			Type t = new Type();

			//  Qualified name of the type.
			t.name = names[p.readU30()];
			//  Base name of the type is in the ABC;
			//  resolve it, and note that the base type
			//  has been used as a base, so it won't be
			//  emitted as *.
			t.base = lookup(p.readU30());
			TypeCache.instance().baseTypes.add(t.base);
			
			t.flags = p.readU8();
			if (t.hasProtectedNs())
				t.protectedNs = namespaces[p.readU30()];
			t.interfaces = new Type[p.readU30()];
			for (int j = 0, n = t.interfaces.length; j < n; j++)
			{
				t.interfaces[j] = lookup(p.readU30());
			}
			t.init = methods[p.readU30()]; // init_id
			if(t.init.isNative() && !ALLOW_NATIVE_CTORS)
				throw new RuntimeException("Constructors can't be native: "+t);
			t.init.cx = t;
			t.init.getParams()[0] = t.ref.nonnull();
			t.init.kind = "init";
			t.init.name = t.getName();
			readTraits(p, t);
			TypeCache.instance().namedTypes.put(t.getName(), t);
			
			if (t.getName().equals(new Name(Name.PKG_PUBLIC,"Object")))
			{
				containsObject = true;
			}
			return t;
		}

		void readCode(Method m, Reader p, Reader ptry)
		{
			

			addTraceAttr("Method", m);
			addTraceAttr("code_start", p.pos);

			int local_count = m.local_count;
			int end_pos = p.pos + m.code_len;
			
			// initial state of frame
			
			Expr[] frame = new Expr[local_count + m.max_scope + m.max_stack];
			Map<Integer,Block> blocks = new TreeMap<Integer,Block>();
			Map<Block,FrameState> states = new TreeMap<Block,FrameState>();
			int scopep = local_count;
			int sp = local_count+m.max_scope;
			traceEntry("InitialFrame");
			addTraceAttr("length", frame.length);
			addTraceAttr("sp", sp);
			addTraceAttr("scopep", scopep);
			
			m.entry = new Edge(m,null,0);
			Block b = createBlock(m, m.entry, states, frame, sp, scopep);
			Expr e;
			
			{
				int i;

				for (i=0; i < m.getParams().length; i++)
				{
					// argument i
					b.add(e = frame[i] = new Expr(m, OP_arg, i));
					if (i==0)
						e.ref = new Name("this");
					else if (m.paramNames != null)
						e.ref = m.paramNames[i];
					else 
						e.ref = new Name("arg"+i);
				}
				
				if (m.needsArguments() || m.needsRest())
				{
					b.add(e = frame[i] = new Expr(m, OP_arg, i));
					e.ref = new Name(m.needsArguments() ? "arguments" : "rest");
					i++;
				}
				
				for (; i < local_count; i++)
				{
					// remaining locals are undefined, but we use OP_arg
					// to suppress any codegen.  sccp_eval knows what to do.
					b.add(e = frame[i] = new Expr(m, OP_arg, i));
					e.ref = new Name("local"+i);
				}
			}
			
			BitSet trylabels = new BitSet();
			BitSet catchlabels = new BitSet();
			
			//  Remember start position of the code reader to compute
			//  relative offsets vs. absolute positions.
			int code_start = p.pos;
			int try_start = ptry.pos;  //  FIXME: use m.handlers-based processing, remove this
			
			Handler[] handlers = m.handlers = new Handler[ptry.readU30()];
			
			if ( handlers.length > 0 )
			{
				//  TODO arg 0 only needs to be fixed if
				//  this is an instance method.
				m.fixedLocals.put(frame[0], -1);
				for (int j = 0, n=handlers.length; j < n; j++)
				{
					Handler h = handlers[j] = new Handler();
					
					int from = ptry.readU30();
					int to = ptry.readU30();
					int target = ptry.readU30();
					h.type = lookup(ptry.readU30()).ref.nonnull();
					int name_idx = ptry.readU30();
					Name name = h.name = names[name_idx];

					//  The name may be null if the catch variable
					//  did not have a name.
					//  NOTE: Also see the emitCode write logic.
					if ( name != null )
					{
						Type a = new Type(name,ANY());
						h.activation = a.ref.nonnull();
						Binding bind = new Binding(TRAIT_Var, name, this);
						bind.type = h.type;
						a.defs.put(name, bind);
					}
					else
					{
						h.activation = ANY().ref.nonnull();
					}

					trylabels.set(from);
					trylabels.set(to);
					catchlabels.set(target);
				}
			}
		
			boolean reachable = true;
			boolean in_catch_block = false;
			
			while (p.pos < end_pos)
			{
				int pos = p.pos;
				int op = p.readU8();

				if (
					OP_label == op || 
					blocks.containsKey(pos) ||
					trylabels.get(pos-code_start) || 
					catchlabels.get(pos-code_start) 
					)
				{	
					if ( catchlabels.get(pos-code_start) )
					{
						in_catch_block = true;
					}
					else
					{
						in_catch_block = false;
					}

					Edge edge = null;
					
					if (reachable)
					{
						assert(!in_catch_block);
						
						Edge succ[] = b.succ();
						if (0 == succ.length)
						{
							b.add(e = new Expr(m,OP_jump));
							e.succ = new Edge[] { edge = new Edge(m,b,0,blocks.get(pos)) };
						}
						else
						{
							edge = succ[0];
						}
						traceEntry("Successor");
						addTraceAttr("Edge", edge);
					}
					
					//  For non-catch blocks, the block's saved stack frame
					//  needs to be updated with the current stack frame --
					//  this may create that saved stack frame as a 
					//  side effect.  For a catch block, the stack frame
					//  set up by the catch handler is already present
					//  and is known to be the correct starting state
					//  of the block.
					if (! in_catch_block)
					{
						merge(m,edge, blocks, states, pos, frame, sp, scopep);
					}

					b = blocks.get(pos);
					assert(b != null);
					FrameState state = states.get(b);
					assert(state != null);
					System.arraycopy(state.frame, 0, frame, 0, frame.length);
					sp = state.sp;
					scopep = state.scopep;
										
					reachable = true;	
				}
				// now we know what block we're in and pos is where it starts.
				
				//  Do we need to set up exception handlers?
				if (handlers.length > 0 && b.xsucc == noedges)
				{
					// start of new block, add handlers.
					

					addTraceAttr("offset", pos - code_start);
					
					List<Edge> xsucc = new ArrayList<Edge>();
					ptry.pos = try_start;
					int n=ptry.readU30();
					addTraceAttr("NumHandlers", n);
					
					for (int j=0; j < n; j++)
					{
						int from = code_start + ptry.readU30();
						int to = code_start + ptry.readU30();
						int target = code_start + ptry.readU30();

						traceEntry("Handler");
						addTraceAttr("from", from - code_start);
						addTraceAttr("to", to - code_start);
						addTraceAttr("target", target - code_start);
						
						if (pos >= from && pos < to)
						{
							addTraceAttr("activeHandler");
							Edge edge = new Edge(m, b, j, handlers[j]);
							xmerge(m, edge, blocks, states, target, frame, sp, scopep);
							xsucc.add(edge);
						}
						ptry.readU30(); // type
						ptry.readU30(); // name
					}
					
					b.xsucc = xsucc.toArray(new Edge[xsucc.size()]);

				}
				

				addTraceAttr("offset", pos-code_start);
				addTraceAttr("op", op);
				addTraceAttr("opName", opNames[op]);
				
				switch (op)
				{
				case OP_label:
					// already handled above
					break;

				case OP_throw:
				case OP_returnvalue:
					b.add(e = new Expr(m,op, frame, sp--, 1));
					e.succ = noedges;
					reachable = false;
					merge(m,null, blocks, states, p.pos, frame, sp, scopep);
					break;
					
				case OP_dxnslate:
					b.add(new Expr(m,op,frame, sp--, 1));
					break;

				case OP_pushwith:
				case OP_pushscope:
				{
					// includes a null pointer check and moves value to scope stack, so this isn't just a copy
					b.add(frame[scopep++] = e = new Expr(m, op, frame, sp--, 1));
					
					//  The activation record saved for catch blocks' use
					//  is live across regions of code that the optimizer
					//  and verifier don't agree on, so it gets fixed into
					//  a local and "conflicts" with everything.
					if ( in_catch_block  && OP_phi == e.args[0].op  )
					{
						Expr activ = e.args[0];
						while ( OP_phi == activ.op && activ.args != null && activ.args.length > 0)
						{
							activ = activ.args[0];
						}
						
						if ( OP_newactivation == activ.op)
						{
							m.fixedLocals.put(activ, -1);
						}
							
					}
					break;
				}

				case OP_popscope:
					b.add(e = new Expr(m, op));
					e.scopes = new Expr[] { frame[--scopep] };
					frame[scopep] = null;
					break;
					
				case OP_nextname:
				case OP_hasnext:
				case OP_nextvalue:
					b.add(e = new Expr(m,op, frame, sp, 2));
					sp -= 2;
					frame[sp++] = e;
					break;
					
				case OP_pushnull:
					b.add(frame[sp++] = new Expr(m,op,NULL()));
					break;
				case OP_pushundefined:
					b.add(frame[sp++] = new Expr(m,op,UNDEFINED));
					break;
				case OP_pushtrue:
					b.add(frame[sp++] = new Expr(m,op,TRUE));
					break;
				case OP_pushfalse:
					b.add(frame[sp++] = new Expr(m,op,FALSE));
					break;
				case OP_pushnan:
					b.add(frame[sp++] = new Expr(m,op,Double.NaN));
					break;
					
				case OP_newactivation:
					b.add(frame[sp++] = new Expr(m,op));
					break;

				case OP_getglobalscope:
					b.add(e = frame[sp++] = new Expr(m, op));
					e.scopes = capture(frame, scopep, scopep-local_count);
					traceEntry("scopep", scopep);
					break;
					
				case OP_getscopeobject:
					b.add(e = frame[sp++] = new Expr(m, op));
					e.scopes = capture(frame, local_count+p.readU8()+1, 1);
					break;
					
				case OP_pop:
					sp--;
					break;

				case OP_dup:
					frame[sp] = frame[sp-1];
					sp++;
					break;
					
				case OP_swap:
				{
					e = frame[sp-1];
					frame[sp-1] = frame[sp-2];
					frame[sp-2] = e;
					break;
				}
				
				case OP_returnvoid:
					b.add(e = new Expr(m,op));
					e.succ = noedges;
					reachable = false;
					merge(m,null, blocks, states, p.pos, frame, sp, scopep);
					break;

				case OP_convert_s:
				case OP_esc_xelem:
				case OP_esc_xattr:
				case OP_convert_i:
				case OP_convert_u:
				case OP_convert_d:
				case OP_coerce_s:
				case OP_negate:
				case OP_increment:
				case OP_decrement:
				case OP_not:
				case OP_bitnot:
				case OP_increment_i:
				case OP_decrement_i:
				case OP_negate_i:
				case OP_coerce_o:
				case OP_convert_o:
				case OP_typeof:
				case OP_convert_b:
				case OP_coerce_a:
					// unary w/ possible side effect
					b.add(frame[sp-1] = new Expr(m,op, frame, sp, 1));
					break;

				case OP_checkfilter:
					// possible exception
					b.add(new Expr(m,op, frame, sp, 1));
					break;

				case OP_astypelate:
				case OP_add:
				case OP_subtract:
				case OP_multiply:
				case OP_divide:
				case OP_modulo:
				case OP_lshift:
				case OP_rshift:
				case OP_urshift:
				case OP_bitand:
				case OP_bitor:
				case OP_bitxor:
				case OP_equals:
				case OP_lessthan:
				case OP_lessequals:
				case OP_greaterthan:
				case OP_greaterequals:
				case OP_instanceof:
				case OP_in:
				case OP_add_i:
				case OP_subtract_i:
				case OP_multiply_i:
				case OP_istypelate:
				case OP_strictequals:
					b.add(frame[sp-2] = new Expr(m,op, frame, sp, 2));
					sp--;
					break;
					
				case OP_getlocal0:
				case OP_getlocal1:
				case OP_getlocal2:
				case OP_getlocal3:
					frame[sp++] = frame[op-OP_getlocal0];
					break;

				case OP_setlocal0:
				case OP_setlocal1:
				case OP_setlocal2:
				case OP_setlocal3:
					frame[op-OP_setlocal0] = frame[--sp];
					break;

				case OP_kill:
					b.add(frame[p.readU30()] = new Expr(m,OP_pushundefined,UNDEFINED)); 
					break;
					
				case OP_pushshort:
					b.add(frame[sp++] = new Expr(m,op, new Integer((short)p.readU30())));
					break;
				case OP_pushstring:
					b.add(frame[sp++] = new Expr(m,op, strings[p.readU30()]));
					break;
				case OP_pushint:
					b.add(frame[sp++] = new Expr(m,op, new Integer(ints[p.readU30()])));
					break;
				case OP_pushuint:
					b.add(frame[sp++] = new Expr(m,op, new Long(uints[p.readU30()])));
					break;
				case OP_pushdouble:
					b.add(frame[sp++] = new Expr(m,op, new Double(doubles[p.readU30()])));
					break;
				case OP_pushnamespace:
					b.add(frame[sp++] = new Expr(m,op, namespaces[p.readU30()]));
					break;

				case OP_getlocal:
					frame[sp++] = frame[p.readU30()];
					break;
					
				case OP_setlocal:
					frame[p.readU30()] = frame[--sp];
					break;
					
				case OP_coerce:
				case OP_astype:
				case OP_istype:
				{
					b.add(e = frame[sp-1] = new Expr(m, op, names[p.readU30()], frame, sp, 1));
					break;
				}
					
				case OP_dxns:
					b.add(new Expr(m,op, strings[p.readU30()]));
					break;
				
				case OP_inclocal_i:
				case OP_declocal_i:
				case OP_inclocal:
				case OP_declocal:
				{
					// turn these into increment/decrement, forget which local was used.
					int i = p.readU30();
					op = op == OP_inclocal_i ? OP_increment_i :
						 op == OP_inclocal   ? OP_increment   :
						 op == OP_declocal_i ? OP_decrement_i : 
					 	                       OP_decrement;
					b.add(e = frame[i] = new Expr(m, op, i, frame, i+1, 1));
					break;
				}

				case OP_newfunction:
				{
					e = new Expr(m,op);
					e.m = methods[p.readU30()];
					e.scopes = capture(frame, scopep, scopep-local_count);
					traceEntry("scopep", scopep);
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_newclass:
				{
					e = new Expr(m, op, frame, sp, 1);
					e.scopes = capture(frame, scopep, scopep-local_count);
					traceEntry("scopep", scopep);
					e.c = classes[p.readU30()];
					b.add(frame[sp-1] = e);
					break;
				}
				
				case OP_newobject:
				{
					int argc = 2*p.readU30();
					e = new Expr(m,op, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_newarray:
				{
					int argc = p.readU30();
					e = new Expr(m,op, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}

				case OP_newcatch:
				{
					e = new Expr(m, op, p.readU30());
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_getsuper:
				{
					Name ref = names[p.readU30()];
					int argc = 1 + refArgc[ref.kind];
					e = new Expr(m,op, ref, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_setsuper:
				{
					Name ref = names[p.readU30()];
					int argc = 2 + refArgc[ref.kind];
					b.add(e = new Expr(m,op, ref, frame, sp, argc));
					sp -= argc;
					break;
				}
				
				case OP_call:
				{
					int argc = 2+p.readU30();
					e = new Expr(m, op, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}

				case OP_construct:
				{
					int argc = 1+p.readU30();
					e = new Expr(m,op, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}

				case OP_getdescendants:
				case OP_deldescendants:
				case OP_deleteproperty:
				case OP_getproperty:
				{
					Name ref = names[p.readU30()];
					int argc = 1 + refArgc[ref.kind];
					e = new Expr(m, op, ref, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_getlex:
				{
					Name ref = names[p.readU30()];
					assert(refArgc[ref.kind] == 0);
					e = new Expr(m, OP_findpropstrict, ref, frame, sp, 0);
					e.scopes = capture(frame, scopep, scopep-local_count);
					b.add(e);
					e = new Expr(m, OP_getproperty, ref, new Expr[] { e }, 1, 1);
					b.add(frame[sp++] = e);
					break;
				}

				case OP_findpropstrict:
				case OP_findproperty:
				{
					Name ref = names[p.readU30()];
					int argc = refArgc[ref.kind];
					e = new Expr(m,op, ref, frame, sp, argc);
					e.scopes = capture(frame, scopep, scopep-local_count);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}

				case OP_finddef:
				{
					Name ref = names[p.readU30()];
					int argc = refArgc[ref.kind];
					e = new Expr(m,op, ref, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
					
				case OP_setproperty:
				case OP_initproperty:
				{
					Name ref = names[p.readU30()];
					int argc = 2 + refArgc[ref.kind];
					e = new Expr(m,op, ref, frame, sp, argc);
					sp -= argc;
					b.add(e);
					break;
				}
				
				case OP_getslot:
				{
					e = new Expr(m,op, p.readU30(), frame, sp, 1);
					b.add(e);
					frame[sp-1] = e;
					break;
				}
				
				case OP_setslot:
				{
					e = new Expr(m,op, p.readU30(), frame, sp, 2);
					b.add(e);
					sp -= 2;
					break;
				}
				
				case OP_jump:
				{
					int offset = p.readS24();
					if (reachable)
					{
						b.add(e = new Expr(m,op));
						e.succ = new Edge[] { new Edge(m,b, 0, blocks.get(p.pos+offset)) };
						merge(m, null, blocks, states, p.pos, frame, sp, scopep);
						merge(m,e.succ[0], blocks, states, p.pos+offset, frame, sp, scopep);
						reachable = false;
					}
					break;
				}

				case OP_iftrue:
				case OP_iffalse:
				{
					b.add(e = new Expr(m, op, frame, sp--, 1));
					int offset = p.readS24();
					e.succ = new Edge[] { 
							new Edge(m,b,0,blocks.get(p.pos)), 
							new Edge(m,b,1,blocks.get(p.pos+offset)) };
					merge(m,null, blocks, states, p.pos, frame, sp, scopep);
					merge(m,e.succ[1], blocks, states, p.pos+offset, frame, sp, scopep);
					break;
				}
				
				case OP_ifnlt:
				case OP_ifnle:
				case OP_ifngt:
				case OP_ifnge:
				case OP_ifne:
				case OP_ifstrictne:
				{
					b.add(e = new Expr(m, ifoper(op), frame, sp, 2));
					traceEntry("ConditionalBranch");
					addTraceAttr(e);
					b.add(e = new Expr(m, OP_iffalse, new Expr[] { e }, 1, 1));
					int offset = p.readS24();
					sp-=2;
					e.succ = new Edge[] { 
							new Edge(m,b,0,blocks.get(p.pos)),
							new Edge(m,b,1,blocks.get(p.pos+offset)) };
					merge(m,null, blocks, states, p.pos, frame, sp, scopep);
					merge(m,e.succ[1], blocks, states, p.pos+offset, frame, sp, scopep);
					break;
				}

				case OP_ifeq:
				case OP_iflt:
				case OP_ifle:
				case OP_ifgt:
				case OP_ifge:
				case OP_ifstricteq:
				{
					b.add(e = new Expr(m, ifoper(op), frame, sp, 2));
					traceEntry("ConditionalBranch");
					addTraceAttr(e);
					b.add(e = new Expr(m, OP_iftrue, new Expr[] { e }, 1, 1));
					int offset = p.readS24();
					sp-=2;
					e.succ = new Edge[] { 
							new Edge(m,b,0,blocks.get(p.pos)),
							new Edge(m,b,1,blocks.get(p.pos+offset)) };
					merge(m,null, blocks, states, p.pos, frame, sp, scopep);
					merge(m,e.succ[1], blocks, states, p.pos+offset, frame, sp, scopep);
					break;
				}
					
				case OP_lookupswitch:
				{
					b.add(e = new Expr(m,op, frame,sp--,1));
					//  Default target
					int target = pos+p.readS24();
					// "There are case_count+1 case offsets."
					int case_count = 1+p.readU30();
					e.succ = new Edge[case_count+1];
					//  Default case goes last.
					e.succ[case_count] = new Edge(m,b, case_count, blocks.get(target));
					merge(m,e.succ[case_count], blocks, states, target, frame, sp, scopep);
					for (int i=0; i < case_count; i++)
					{
						target = pos+p.readS24();
						e.succ[i] = new Edge(m,b, i, blocks.get(target));
						merge(m,e.succ[i], blocks, states, target, frame, sp, scopep);
					}
					
					// no fall-through for switch
					reachable = false;
					break;
				}

				case OP_pushbyte:
				{
					e = frame[sp++] = new Expr(m,op, new Integer((byte)p.readU8()));
					b.add(e);
					break;
				}
				
				case OP_hasnext2:
				{

					int oloc = p.readU30();
					int iloc = p.readU30();
					Expr index = frame[iloc];
					Expr obj = frame[oloc];
					addTraceAttr("index", index);
					addTraceAttr("obj", obj);
					b.add(e = frame[sp] = new Expr(m,op));
					e.locals = new Expr[] { obj, index };
					b.add(e = frame[oloc] = new Expr(m, OP_hasnext2_o));
					e.locals = new Expr[] { obj };
					b.add(e = frame[iloc] = new Expr(m, OP_hasnext2_i));
					e.locals = new Expr[] { index };
					sp++;
					b.must_isolate_block = true;

					break;
				}
				
				case OP_callmethod:
				{
					int id = p.readU30();
					int argc = 1+p.readU30();
					e = new Expr(m,op, id, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_callstatic:
				{
					int id = p.readU30();
					int argc = 1+p.readU30();
					e = new Expr(m,op, frame, sp, argc);
					e.m = methods[id];
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_applytype:
				{
					int argc = 1+p.readU30();
					e = new Expr(m,op, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_constructsuper:
				{
					int argc = 1+p.readU30();
					e = new Expr(m,op, frame, sp, argc);
					sp -= argc;
					b.add(e);
					break;
				}
				
				case OP_callsuper:
				case OP_callproperty:
				case OP_constructprop:
				case OP_callproplex:
				{
					Name ref = names[p.readU30()];
					int argc = 1 + p.readU30() + refArgc[ref.kind];
					e = new Expr(m,op, ref, frame, sp, argc);
					sp -= argc;
					b.add(frame[sp++] = e);
					break;
				}
				
				case OP_callsupervoid:
				case OP_callpropvoid:
				{
					Name ref = names[p.readU30()];
					int argc = 1 + p.readU30() + refArgc[ref.kind];
					e = new Expr(m,op, ref, frame, sp, argc);
					sp -= argc;
					b.add(e);
					break;
				}
				
				case OP_debugfile:
				{
					int ii = p.readU30();
					if (!STRIP_DEBUG_INFO)
						b.add(e = new Expr(m,op, strings[ii]));
					addTraceAttr("file", strings[ii]);
					break;
				}	

				case OP_debugline:
				case OP_bkptline:
				{
					int ii = p.readU30();
					if (!STRIP_DEBUG_INFO)
						b.add(e = new Expr(m,op, ii));
					addTraceAttr("line", ii);
					break;
				}
				case OP_debug:
				{
					int i1 = p.readU8();
					int i2 = p.readU30();
					int i3 = p.readU8();
					int i4 = p.readU30();
					if (!STRIP_DEBUG_INFO)
					{
						e = new Expr(m,op);
						e.imm = new int[] { i1, i2, i3, i4 };
						b.add(e);
					}
					break;
				}

				case OP_bkpt:
					if (!STRIP_DEBUG_INFO)
					{
						// no args but position matters
						b.add(new Expr(m,op));
					}
					break;

				case OP_timestamp:
					// no args but position matters
					b.add(new Expr(m,op));
					break;
					
				case OP_nop:
					break;
					
				default:
					System.err.println("Unknown ABC bytecode "+op);
					assert (false);
				}
				

			}			

			dce(m);
			

		}
		
		public int nameIndex(Name n)
		{
			int idx = 0;
			for (Name x: names)
			{
				if ( x != null && ( x == n || x.equals(n) ) )
					return idx;
				idx++;
			}
			
			return -1;
		}
	}
	
		
	static int rtcounter;
	static String unique()
	{
		return unique("[]");
	}
	static String unique(String prefix)
	{
		return prefix+(rtcounter++);
	}
	static Namespace uniqueNs()
	{
		return new Namespace(unique("ns"));
	}
	
	Type OBJECT()    { return TypeCache.instance().OBJECT;}
	Type FUNCTION()  { return TypeCache.instance().FUNCTION;}
	Type CLASS()     { return TypeCache.instance().CLASS;}
	Type ARRAY()     { return TypeCache.instance().ARRAY;}
	Type INT()       { return TypeCache.instance().INT;}
	Type UINT()      { return TypeCache.instance().UINT;}
	Type NUMBER()    { return TypeCache.instance().NUMBER;}
	Type BOOLEAN()   { return TypeCache.instance().BOOLEAN;}
	Type STRING()    { return TypeCache.instance().STRING;}
	Type NAMESPACE() { return TypeCache.instance().NAMESPACE;}
	Type XML()       { return TypeCache.instance().XML;}
	Type XMLLIST()   { return TypeCache.instance().XMLLIST;}
	Type QNAME()     { return TypeCache.instance().QNAME;}
	Type NULL()      { return TypeCache.instance().NULL;}
	Type VOID()      { return TypeCache.instance().VOID;}
	Type ANY()       { return TypeCache.instance().ANY();}
	
	
	static class Metadata implements Comparable
	{
		String name;
		Attr[] attrs;
		
		public int compareTo(Object o)
		{
			Metadata md = (Metadata)o;
			if (this == md) return 0;
			int d = md.name.compareTo(name);
			if (d != 0) return d;
			if ((d = attrs.length - md.attrs.length) != 0) return d;
			for (int i=0, n=attrs.length; i < n; i++)
				if ((d = attrs[i].compareTo(md.attrs[i])) != 0)
					return d;
			return 0;
		}
	}

	static class Attr implements Comparable
	{
		String name;
		String value;
		Attr(String name)
		{
			this.name = name;
		}
		
		public int compareTo(Object o)
		{
			Attr a = (Attr)o;
			if (this == a) return 0;
			int d = name.compareTo(a.name);
			if (d != 0) return d;
			if ((d = value.compareTo(a.value)) != 0) return d;
			return 0;
		}
	}

	/**
	 * Methods ready for optimization.
	 * Populated by readyMethod(), called from readyType()
	 * and by initial processing of the OP_newfunction Expr.
	 */
	List<Method> ready = new ArrayList<Method>();

	/** 
	 * Track already-processed methods so they never go on the ready list twice.
	 * @warn Methods are tracked by hashCode() b/c Method defines a compare function 
	 * that can compare different Methods as equal (if they're in different types).
	 * If Method.hashCode() is modified, then Method will need a unique ID to 
	 * make this set work.
	 */
	Set<Method> already_processed = new HashSet<Method>();
	
	
	void readyType(Type t)
	{
		readyMethod(t.init);

		for (Binding b1: t.defs.values())
			if (b1.method != null)
				readyMethod(b1.method);
	}
	
	void readyMethod(Method m)
	{
		traceEntry("readyMethod");
		addTraceAttr(m);
		if (m.entry != null && ! already_processed.contains(m) )
		{
			addTraceAttr("process", true);
			ready.add(m);
			already_processed.add(m);
		}
	}
	
	void optimize(InputAbc a)
	{
		
		for ( PluginData plugin: this.analysis_phase_plugins.values())
		{
			CallGraph cg = new CallGraph(a);
			plugin.plugin.runPlugin(a.src_filename, cg);
		}
		
 		for (Type t: a.scripts)
			readyType(t);
		
		while (!ready.isEmpty())
			optimize(getMethod(ready));
	}
	
	/**
	 * organize the pools so the most commonly referenced elements
	 * have the lowest indexes.
	 * 
	 * TODO - remove dup namespaces from nssets & remove dup nssets
	 */
	class Abc
	{
		Pool<Integer> intPool = new Pool<Integer>(1);
		Pool<Long> uintPool = new Pool<Long>(1);
		Pool<Double> doublePool = new Pool<Double>(1);
		Pool<String> stringPool = new Pool<String>(1);
		Pool<Namespace> nsPool = new Pool<Namespace>(1);
		Pool<Nsset> nssetPool = new Pool<Nsset>(1);
		Pool<Name> namePool = new Pool<Name>(1);
		Pool<Method> methodPool1 = new Pool<Method>(0);
		Pool<Method> methodPool2 = new Pool<Method>(0);
		Pool<Metadata> metaPool = new Pool<Metadata>(0);
		int bodyCount;
		boolean haveNatives;

		List<Type> scripts = new ArrayList<Type>();
		List<Type> classes = new ArrayList<Type>();
		
		int typeRef(Typeref tref)
		{
			return typeRef(tref.t);
		}
		
		int typeRef(Type t)
		{
			if (t == ANY())
				return 0;
			else if(t.emitAsAny()) {
				verboseStatus("Emitting: " + t + " as any");
				return 0;
			} else
				return namePool.id(t.getName());
		}
		
		Pool<Method> poolFor(Method m)
		{
			// put abc methods first, native methods second.
			return m.isNative() ? methodPool2 : methodPool1;
		}
		
		int methodId(Method m)
		{
			return poolFor(m).id(m);
		}

		void addScript(Type s)
		{
			// global object type
			addMethod(s.init);
			addTraits(s.defs);
			scripts.add(s);
		}
		
		void addClass(Type c)
		{
			// instance type
			Type t = c.itype;
			addName(t.getName());
			if (t.base != NULL())
				addTypeRef(t.base);
			if (t.hasProtectedNs())
				addNamespace(t.protectedNs);
			for (Type i: t.interfaces)
				addInterfaceRef(i);
			addMethod(t.init);
			addTraits(t.defs);

			// class type
			addMethod(c.init);
			addTraits(c.defs);
			classes.add(c);
		}

		int classId(Type c)
		{
			return classes.indexOf(c);
		}
		
		int scriptId(Type c)
		{
			return scripts.indexOf(c);
		}
				
		void addTraits(Symtab<Binding> defs)
		{
			for (Binding b: defs.values())
			{
				addName(b.getName());
				switch (b.kind())
				{
				case TRAIT_Class:
					addClass(b.type.t);
					break;
				case TRAIT_Var:
				case TRAIT_Const:
					addTypeRef(b.type);
					if (b.value != null)
					{
						addConst(b.value);
					}
					break;
				case TRAIT_Method:
				case TRAIT_Getter:
				case TRAIT_Setter:
					addMethod(b.method);
					break;
				}
				
				/*if (b.hasMetadata())
					for (Metadata md : b.md)
						addMetadata(md);*/
			}
		}
		
		void addMetadata(Metadata md)
		{
			if (metaPool.add(md) == 1)
			{
				stringPool.add(md.name);
				for (Attr a: md.attrs)
				{
					stringPool.add(a.name);
					stringPool.add(a.value);
				}
			}
		}
		
		void addConst(Object value)
		{
			if (value instanceof Integer)
				intPool.add(intValue(value));
			else if (value instanceof Long)
				uintPool.add(uintValue(value));
			else if (value instanceof Double)
				doublePool.add(doubleValue(value));
			else if (value instanceof String)
				stringPool.add((String)value);
			else if (value instanceof Namespace)
				addNamespace((Namespace) value);
		}
		
		int constId(int kind, Object value)
		{
			switch (kind)
			{
			case CONSTANT_Integer:
				return intPool.id(intValue(value));
			case CONSTANT_UInteger:
				return uintPool.id(uintValue(value));
			case CONSTANT_Utf8:
				return stringPool.id((String)value);
			case CONSTANT_Double:
				return doublePool.id(doubleValue(value));
			case CONSTANT_Namespace:
				return nsPool.id((Namespace)value);
			case CONSTANT_True:
				return CONSTANT_True;
			case CONSTANT_False:
				return CONSTANT_False;
			case CONSTANT_Null:
				return CONSTANT_Null;
			}
			return 0;
		}
		
		int constKind(Object value)
		{
			if (value instanceof Integer)
				return CONSTANT_Integer;
			if (value instanceof Long)
				return CONSTANT_UInteger;
			if (value instanceof Double)
				return CONSTANT_Double;
			if (value instanceof String)
				return CONSTANT_Utf8;
			if (value instanceof Namespace)
				return ((Namespace)value).kind;
			if (value == TRUE)
				return CONSTANT_True;
			if (value == FALSE)
				return CONSTANT_False;
			if (value == UNDEFINED)
				return CONSTANT_Void;
			if (value == NULL())
				return CONSTANT_Null;
			return 0;
		}
		
		void addNamespace(Namespace ns)
		{
			if (nsPool.add(ns) == 1)
			{
				if (!ns.isPrivateOrInternal())
					stringPool.add(ns.uri);
			}
		}
		
		void addNsset(Nsset nsset)
		{
			if (nssetPool.add(nsset) == 1)
				for (Namespace ns: nsset)
					addNamespace(ns);
		}
		
		void addName(Name n)
		{
			if (namePool.add(n) == 1)
				switch (n.kind)
				{
				case CONSTANT_Multiname:
				case CONSTANT_MultinameA:
					addNsset(n.nsset);
					stringPool.add(n.name);
					break;
				case CONSTANT_Qname:
				case CONSTANT_QnameA:
					addNamespace(n.nsset(0));
					stringPool.add(n.name);
					break;
				case CONSTANT_RTQname:
				case CONSTANT_RTQnameA:
					stringPool.add(n.name);
					break;
				case CONSTANT_MultinameL:
				case CONSTANT_MultinameLA:
					addNsset(n.nsset);
					break;
				}
		}
		
		void addTypeRef(Typeref tref)
		{
			addTypeRef(tref.t);
		}
		
		void addTypeRef(Type t)
		{
			if (t != ANY() && !t.emitAsAny())
				addName(t.getName());
		}
		
		void addInterfaceRef(Type t) 
		{
			addName(t.getName());
		}
		
		void addMethod(Method m)
		{
			if (poolFor(m).add(m) > 1) 
				return;
			
			if (m.entry != null)
				bodyCount++;
			
			addTypeRef(m.returns.t);
			for (int i=1, n=m.getParams().length; i < n; i++)
				addTypeRef(m.getParams()[i]);
			
			if (m.hasOptional())
				for (Object v: m.values)
					if (v != null)
						addConst(v);
			
			if (!STRIP_DEBUG_INFO)
			{
				if (m.hasParamNames())
					for (int i=1; i < m.paramNames.length; i++)
						addName(m.paramNames[i]);
			}
			
			if ( PRESERVE_METHOD_NAMES )
			{
				addConst(m.debugName);
			}
			
			for (Handler t: m.handlers)
			{
				if ( t.name != null )
					addName(t.name);
				addTypeRef(t.type);
			}

			// native and interface methods don't have a body
			haveNatives |= m.isNative();
			if (m.entry == null)
				return;

			for (Block b: dfs(m.entry.to))
			{
				for (Expr e: b)
				{
					switch (e.op)
					{
					case OP_debugfile:
						if (!STRIP_DEBUG_INFO)
							addConst(e.value);
						break;
					case OP_pushint:
					case OP_pushuint:
					case OP_pushstring:
					case OP_pushnamespace:
					case OP_pushdouble:
					case OP_dxns:
						addConst(e.value);
						break;
					case OP_istype:
					case OP_astype:
					case OP_findproperty:
					case OP_findpropstrict:
					case OP_callproperty:
					case OP_callproplex:
					case OP_callsuper:
					case OP_callsupervoid:
					case OP_constructprop:
					case OP_getproperty:
					case OP_setproperty:
					case OP_deleteproperty:
					case OP_getdescendants:
					case OP_coerce:
					case OP_getlex:
					case OP_finddef:
					case OP_callpropvoid:
					case OP_initproperty:
						addName(e.ref);
						break;
					case OP_newfunction:
					case OP_callstatic:
						addMethod(e.m);
						break;
					}
				}
			}
			addTraits(m.activation.t.defs);
		}
		
		void sort()
		{
			verboseStatus("NAMES RANK " + namePool.refs);
			intPool.sort();
			uintPool.sort();
			doublePool.sort();
			stringPool.sort();
			nsPool.sort();
			nssetPool.sort();
			namePool.sort();
			metaPool.sort();
			methodPool1.sort();
			methodPool2.countFrom = methodPool1.size();
			methodPool2.sort();
			verboseStatus("NAMES " + namePool.values);
			
			// topological sort of the classes, base classes come first
			if ( legacy_verifier )
			{
				if ( num_linked_files > 1 )
				{
					classes = new Algorithms.TopologicalSort<Type>().toplogicalSort(
							classes, 
							new Algorithms.TopologicalSort.DependencyChecker<Type>()
							{
								public boolean depends(Type dep, Type parent)
								{
									return (dep.itype.isDerivedFrom(parent.itype));
								}
							}
						);
				}
			}
			else
			{
				//  HACK ALERT: This sort is incorrect, but the topological
				//  sort causes tamarin-tracing builds to fail in shell.abc.
				TreeSet<Type> cs = new TreeSet<Type>(new Comparator<Type>()
				{
					public int compare(Type a, Type b)
					{
						if (a == b) return 0;
// no, this is subtly wrong: we might be comparing two classes that have no parent-child relationship
// (eg SyntaxError and EvalError). this logic will push UP subclasses and push DOWN no-rel-classes and superclasses.
// it's more reliable to push DOWN superclasses and UP subclasses and no-rel-classes. (we can't just return 0
// for no-rel because TreeSet will assume they are identical and eliminate one...)
//					else if (istype(a.itype, b.itype)) return 1;
//					else return -1;
						else if (b.itype.extendsOrIsBase(a.itype)) return -1;
						else return 1;
					}
				});
				cs.addAll(classes);
				classes.clear();
				classes.addAll(cs);
			}
		}

		public int interfaceRef(Type t) 
		{
			return namePool.id(t.getName());
		}
	}
	
	int argc(Expr e)
	{
		switch (e.op)
		{
		case OP_callproperty:
		case OP_callproplex:
		case OP_callpropvoid:
		case OP_callsuper:
		case OP_callsupervoid:
		case OP_constructprop:
			return e.args.length - refArgc[e.ref.kind] - 1;
		case OP_applytype:
		case OP_callstatic:
		case OP_callmethod:
		case OP_constructsuper:
		case OP_construct:
			return e.args.length-1;
		case OP_call:
			return e.args.length-2;
		case OP_newarray:
			return e.args.length;
		case OP_newobject:
			assert(e.args.length % 2 == 0);
			return e.args.length/2;
		default:
			assert(false);
		}
		return 0;
	}
	
	static class IndentingPrintWriter extends PrintWriter
	{
		int indent;
		IndentingPrintWriter(Writer w)
		{
			super(w);
		}
		public void println()
		{
			super.println();
			for (int i=0; i < indent; i++)
				print("    ");
		}
	}
	
	byte[] emit(InputAbc a, String filename, List<Integer> initScripts, boolean no_c_gen) throws IOException
	{
		// schedule everything that is reachable.  this will assign new id's to
		// stuff, then we can write it all out in the right order.
		Abc abc = new Abc();
		for (Type s: a.scripts)
			abc.addScript(s);
		
		abc.sort();
		
		String scriptname = filename.substring(0,filename.lastIndexOf('.'));
		byte[] data = emitAbc(abc);
		OutputStream out = new FileOutputStream(scriptname+".abc2");
		try
		{
			out.write(data);
		}
		finally
		{
			out.close();
		}
		
		if (abc.haveNatives && !no_c_gen)
		{
			PrintWriter out_h = new PrintWriter(new FileWriter(scriptname+".h2"));
			IndentingPrintWriter out_c = new IndentingPrintWriter(new FileWriter(scriptname+".cpp2"));
			try
			{
				emitSource(abc, scriptname, data, initScripts, out_h, out_c);
			}
			finally
			{
				out_c.close();
				out_h.close();
			}
		}
		return data;
	}
	
	void emitSource(Abc abc, String name, byte[] data, List<Integer> initScripts,
			PrintWriter out_h, IndentingPrintWriter out_c)
	{
		// header file - definitions & native method decls
		out_h.println("/* machine generated file -- do not edit */");
 		out_h.println("namespace avmplus {");

 		out_h.println("AVMPLUS_NATIVEMAP_DECLARE("+name+", "+ abc.methodPool1.size()+")");

		out_c.println("/* machine generated file -- do not edit */");
 		out_c.println("namespace avmplus {");
		
		// output vm creation init method
 		out_h.println("extern AvmInstance "+name+"_init(GC* gc, const AvmConfiguration& c, const uint8_t* abc_data=NULL, size_t length=0);");
		
		// data buf decl only visible to init method
		out_c.println("extern const uint8_t "+name+"_abc_data["+data.length+"];");
 		out_c.println("AvmInstance "+name+"_init(GC* gc, const AvmConfiguration& c, const uint8_t* abc_data/*=NULL*/, size_t length/*=0*/)");
 		out_c.printf("{\n\tif (abc_data==NULL) { abc_data = %s_abc_data; length = %s; }\n", name, data.length);
 		out_c.printf("\tAvmInstance _vm = AvmInit(gc, c, abc_data, length, %s_natives, %s_offset);\n", name, name);
		
		for(int i: initScripts) {
 			out_c.printf("\tAvmInitScript(_vm, %d);\n", i);
		}
		
		out_c.printf("\treturn _vm;\n}\n");
		
		StringWriter b = new StringWriter();
		PrintWriter out_t = new PrintWriter(b);
		Map<Integer,String> impls = new TreeMap<Integer,String>();

		for (Type s: abc.scripts)
			emitSourceTraits("", abc, s, out_h, impls, out_t, out_c);
		
		out_c.print("AVMPLUS_NATIVEMAP_BEGIN("+name+")");
		out_c.indent++;
		out_c.println();
		for (int id: impls.keySet())
		{
			String s = impls.get(id);
			if (s.charAt(0) == 'f')
				out_c.println("AVMPLUS_NATIVEMAP_FORTHMETHOD("+s.substring(1)+")");
			else
				out_c.println("AVMPLUS_NATIVEMAP_CMETHOD("+s.substring(1)+")");
		}
		out_c.indent--;
		out_c.println("AVMPLUS_NATIVEMAP_END()");
		out_c.println();
		
		// put thunks in cpp file
		out_t.flush();
		out_c.println(b);
		out_c.println();
		
		// cpp file - abc data, thunks
		out_c.print("const uint8_t "+name+"_abc_data["+data.length+"] = {");
		out_c.indent++;
		out_c.println();
		for (int i=0, n=data.length; i < n; i++)
		{
			int x = data[i] & 255;
			if (x < 10) out_c.print("  ");
			else if (x < 100) out_c.print(' ');
			out_c.print(x);
			if (i+1 < n) out_c.print(", ");
			if (i%16 == 15) out_c.println();
		}
		out_c.indent--;
		out_c.println("};");
		out_c.println("} /* namespace avmplus */");

		out_h.println("} /* namespace avmplus */");
	}

	void emitSourceTraits(String prefix, Abc abc, Type s, 
			PrintWriter out_h, Map<Integer,String> impls, PrintWriter out_t, PrintWriter out_c)
	{
		out_h.println();

		assert(!s.init.isNative());
		for (Binding b: s.defs.values())
		{
			Namespace ns = b.getName().nsset(0);
			String id = prefix + propLabel(b, ns);
			boolean isNative = false;
			String ctype = null;
			if (b.md.length > 0)
				for (Metadata md : b.md)
					if (md.name.equals("native"))
					{
						isNative = true;
						for (Attr a: md.attrs)
							if (a.name.equals("type"))
								ctype = a.value;
					}

			if (b.method != null) {
				if(b.method.isNative())
					emitSourceMethod(prefix, abc, b, ns, out_h, impls, out_t, s.obscure_natives);
				else if(isNative && !s.obscure_natives) {
					int scriptId = abc.scriptId(s);
					if(scriptId == -1)
						throw new RuntimeException("Only scripts can have native callins");
					emitCallinMethod(b, ns, abc.scriptId(s), out_h, out_c);
				}
			} else if (isClass(b))
				emitSourceClass(abc, out_h, out_c, impls, out_t, b, ns, s.obscure_natives);
			else if (isSlot(b) && isNative)
				emitSourceSlot(prefix, abc, b, ns, id, ctype, out_h, out_t, s.obscure_natives);
		}
	}
	
	void emitSourceSlot(String prefix, Abc abc, Binding b, Namespace ns, String id, String ctype, PrintWriter out_h, PrintWriter out_t, boolean obscure_natives)
	{
		if (obscure_natives)
			return;
			
		if (b.type.t.isAtom())
		{
			if (ctype != null)
			{
				// native GCObject's must be stored as atoms, field type must be *.
				if (b.type.t != ANY() || !ns.isPrivateOrInternal())
					throw new RuntimeException("native field "+id+" must be private or internal and type *");
				out_h.println("AVMPLUS_NATIVE_SLOT_DECL_GC("+ctype+","+b.offset+","+id+")");
			}
			else
			{
				out_h.println("AVMPLUS_NATIVE_SLOT_DECL_ATOM("+b.offset+","+id+")");
			}
		}
		else if (b.type.t.emitAsAny())
		{
			ctype = ctype(b.type);
			out_h.println("AVMPLUS_NATIVE_SLOT_DECL_GC("+ctype+","+b.offset+","+id+")");
		}
		else if (b.type.t.numeric)
		{
			ctype = ctype(b.type);
			out_h.println("AVMPLUS_NATIVE_SLOT_DECL_PRIM("+ctype+","+b.offset+","+id+")");
		}
		else
		{
			ctype = ctype(b.type);
			out_h.println("AVMPLUS_NATIVE_SLOT_DECL_RC("+ctype+","+b.offset+","+id+")");
		}
	}
	
	void emitSourceClass(Abc abc, PrintWriter out_h, PrintWriter out_c, Map<Integer,String>impls, PrintWriter out_t,
			Binding b, Namespace ns, boolean obscure_natives)
	{
		String label = (ns.isPublic()||ns.isInternal()) ? b.getName().name : 
			ns.isProtected() ? "protected_"+b.getName().name :
			TypeCache.instance().namespaceNames.containsKey(ns) ? TypeCache.instance().namespaceNames.get(ns)+"_"+b.getName().name : 
			(ns.uri.replace(' ', '_').replace('.','_').replace('$','_')+'_'+b.getName().name);

		Type c = b.type.t;

		if (!obscure_natives)
		{
			out_h.println("const int abcclass_"+ label + " = " + abc.classId(c) + ";");
		}

		emitSourceTraits(label+"_", abc, c, out_h, impls, out_t, out_c);
		emitSourceTraits(label+"_", abc, c.itype, out_h, impls, out_t, out_c);
	}
	
	String ctype(Typeref tref)
	{
		Type t = tref.t;
		if (t == VOID()) return "void";
		if (t.isAtom()) return "AvmBox";
		if (t == INT()) return "int32_t";
		if (t == BOOLEAN()) return "bool";	// no, this would be bad.
		if (t == UINT()) return "uint32_t";
		if (t == STRING()) return "AvmString";
		if (t == NAMESPACE()) return "AvmNamespace";
		if (t == NUMBER()) return "double";
		if (t.base == null) return tref.nonnull().toString() + "*";
		else return "AvmObject /*"+tref.toString()+"*/";
	}

	void emitSourceMethod(String prefix, Abc abc, 
			Binding b, Namespace ns, PrintWriter out_h,
			Map<Integer,String> impls, PrintWriter out_t, boolean obscure_natives)
	{
		Method m = b.method;

		String impl = prefix + propLabel(b, ns);
		if (isGetter(b))
			impl += "_get";
		else if (isSetter(b))
			impl += "_set";
		
		String forthword = null;
		if (b.md.length > 0)
		{
			for (Metadata md : b.md)
			{
				if (md.name.equals("forth"))
				{
					for (Attr a: md.attrs)
					{
						if (a.name.equals("word"))
						{
							forthword = a.value;
							break;
						}
					}
					if (forthword == null)
						throw new RuntimeException("the forth metadata must specify the word attribute");
					break;
				}
			}
		}

		if (forthword != null)
		{
			// note that forth methods are allowed to have optional parameters, but
			// the default values will be ignored! it is up to the forth implementation
			// to check and fill them in properly (that is, the optional args are allowed
			// only to satisfy signature requirements).
			
			out_h.printf("AVMPLUS_FORTH_METHOD_DECL(%s, %s)\n", forthword, impl);

			impls.put(abc.methodId(m), "f" + forthword);
		}
		else
		{
			if (m.hasOptional())
			{
				throw new RuntimeException("native methods may not have optional parameters: "+impl);
			}

			if (m.needsRest())
			{
				throw new RuntimeException("native methods may not have rest args: "+impl);
			}

			// create a C++ declaration for the native thunk.
			createThunkArgs(out_h, impl, m, obscure_natives);
			if(m.returns.t != VOID() && m.returns.t.base == null && !m.returns.t.isAtom())
				out_h.printf("AVMPLUS_NATIVE_METHOD_DECL_GCOBJ(%s, %s)\n", ctype(m.returns), impl);
			else 
				out_h.printf("AVMPLUS_NATIVE_METHOD_DECL(%s, %s)\n", ctype(m.returns), impl);

			impls.put(abc.methodId(m), "n" + impl);
		}

	}

	String propLabel(Binding b, Namespace ns)
	{
		return (ns.isPublic()||ns.isInternal()) ? b.getName().name : 
			ns.isPrivate() ? "private_"+b.getName().name : 
			ns.isProtected() ? "protected_"+b.getName().name :
				TypeCache.instance().namespaceNames.get(ns)+"_"+b.getName().name;
	}

	/**
	 * create C++ code for a struct for the argtypes for this method
	 * 
	 * @param out_t
	 * @param id
	 * @param m
	 */
	void createThunkArgs(PrintWriter out_h, String id, Method m, boolean obscure_natives)
	{

		if (!m.hasParamNames() && m.getParams().length > 1)
		{
			throw new RuntimeException("native method " + id + " must be generated with debug info (have no fear, it will be stripped)");
		}

		out_h.println();
		if (obscure_natives)
		{
			out_h.println("struct " + id + "_args;");
			return;
		}
		
		out_h.println("struct " + id + "_args");
		out_h.println("{");

		// args
		int i=0;
		for (int n=m.getParams().length; i < n; i++)
		{
			String argname = (i == 0) ? 
								((m.getParams()[i].toString().indexOf("$") >= 0) ? "classself" : "self") : 
								m.paramNames[i].name;
			if (m.getParams()[i].t==NUMBER())
			{
				out_h.printf("    public: double %s;\n", argname);
			}
			else if (m.getParams()[i].t==BOOLEAN())
			{
				out_h.printf("    public: int32_t %s_b; private: int32_t %s_pad; public: inline bool %s() const { return %s_b != 0; }\n", argname, argname, argname, argname);
			}
			else if (m.getParams()[i].t==OBJECT() || m.getParams()[i].t==ANY())
			{
				out_h.printf("    public: AvmBoxArg %s;\n", argname);
			}
			else
			{
				out_h.printf("    public: %s %s; private: int32_t %s_pad; \n", ctype(m.getParams()[i]), argname, argname);
			}
		}

		out_h.printf("    public: AvmStatusOut status_out;\n");

		out_h.println("};");
	}

	void emitCallinMethod(Binding b, Namespace ns, int class_id, 
			PrintWriter out_h, PrintWriter out_c)
	{
		Method m = b.method;
		String impl = ns.uri.replace('.', '_') + "_" + b.getName().name;
		writeCallin(m, class_id, impl, out_h, out_c);
	}	

	String boxSetter(Type t)
	{
		if(t == INT())
			return "Int";
		else if(t == UINT())
			return "Uint";
		else if(t == BOOLEAN())
			return "Bool";
		else if(t == STRING())
			return "String";
		else if(t == NAMESPACE())
			return "Namespace";
		else if(t == NUMBER())
			return "Double";		
		else if(t.base == null) // same test use to emit ANY for native slots, valid?
			return "GCObject";
		return "Object";
	}
	
	void writeCallin(Method m, int script_id, String impl, PrintWriter out_h, PrintWriter out_c)
	{
		StringWriter bodySW = new StringWriter();
		StringWriter declSW = new StringWriter();
		PrintWriter decl = new PrintWriter(declSW);
		PrintWriter body = new PrintWriter(bodySW);
		
		decl.printf("%s %s(AvmInstance vm", ctype(m.returns), impl);
		body.print("\n{\n");
		if(m.getParams().length > 1)
			body.printf("\tAvmBox _args[%d];\n", m.getParams().length - 1);
		// args
		int i=1;
		for (int n=m.getParams().length; i < n; i++)
		{
			Typeref t = m.getParams()[i];
			decl.printf(", %s %s", ctype(t), m.paramNames[i]);
			body.printf("\t_args[%d] = AvmBox%s(%s);\n", i-1, boxSetter(t.t), m.paramNames[i]);
		}
		decl.print(")"); 
 		body.print("\t");
		if(m.returns.t != VOID())
			body.print("const AvmBox _returnBox = ");
		
		body.printf("\tAvmInvokeCallin(vm, %d, %d, %d, %s);\n", 
				script_id, m.emit_id, m.getParams().length - 1, m.getParams().length > 1 ? "(AvmBox*)&_args" : "NULL");
		
		if(m.returns.t != VOID())			
			body.printf("\treturn AvmUnBox%s(_returnBox);\n", boxSetter(m.returns.t));
		else 
			body.print(";\n");
		body.print("}\n");
		
		out_h.printf("%s;\n", declSW.getBuffer());
		out_c.print(declSW.getBuffer());
		out_c.print(bodySW.getBuffer());
	}
	
	byte[] emitAbc(Abc abc) throws IOException
	{
		AbcWriter w = new AbcWriter();
		w.writeU16(16);
		w.writeU16(46);

		int pos = w.size();
		w.writeU30(abc.intPool.size());
		for (int x: abc.intPool.values)
			w.writeU30(x);
		
		verboseStatus("ints count "+abc.intPool.size()+ " size " + (w.size()-pos));
		pos = w.size();
		
		w.writeU30(abc.uintPool.size());
		for (long x: abc.uintPool.values)
			w.writeU30((int)x);

		verboseStatus("uints count "+abc.uintPool.size()+ " size " + (w.size()-pos));
		pos = w.size();
		
		verboseStatus("doubles "+abc.doublePool.size());
		w.writeU30(abc.doublePool.size());
		for (double x: abc.doublePool.values)
			w.write64(Double.doubleToLongBits(x));
		
		verboseStatus("double count "+abc.doublePool.size()+ " size " + (w.size()-pos));
		pos = w.size();

		w.writeU30(abc.stringPool.size());
		for (String s: abc.stringPool.values)
		{
			w.writeU30(s.length());
			w.write(s.getBytes("UTF-8"));
		}
		verboseStatus("strings count "+abc.stringPool.size()+ " size " + (w.size()-pos));
		pos = w.size();
		
		w.writeU30(abc.nsPool.size());
		for (Namespace ns: abc.nsPool.values)
			emitNamespace(abc, w, ns);
		verboseStatus("ns count "+abc.nsPool.size()+ " size " + (w.size()-pos));
		pos = w.size();
		
		w.writeU30(abc.nssetPool.size());
		for (Nsset nsset: abc.nssetPool.values)
		{
			w.writeU30(nsset.length);
			for (Namespace ns: nsset)
				w.writeU30(abc.nsPool.id(ns));
		}
		verboseStatus("nsset count "+abc.nssetPool.size()+ " size " + (w.size()-pos));
		pos = w.size();
		
		w.writeU30(abc.namePool.size());
		for (Name n: abc.namePool.values)
		{
			w.write(n.kind);
			switch (n.kind)
			{
			case CONSTANT_TypeName:
				/*
				 * TODO:  this code is correct in isolation,
				 * but until the rest of the type plumbing
				 * supports parameterized types, the resulting
				 * bytecode fails.  So fail fast instead.
				w.writeU30(abc.stringPool.id(n.name));
				//  TODO: replace with the parameter count
				//  when we begin supporting it.
				w.writeU30(1);
				w.writeU30(abc.stringPool.id(n.type_param));
				break;
				*/
				throw new IllegalArgumentException("CONSTANT_TypeName is only allowed in an import file.");
			case CONSTANT_Qname:
			case CONSTANT_QnameA:
				w.writeU30(abc.nsPool.id(n.nsset(0)));
				w.writeU30(abc.stringPool.id(n.name));
				break;
			case CONSTANT_Multiname:
			case CONSTANT_MultinameA:
				w.writeU30(abc.stringPool.id(n.name));
				w.writeU30(abc.nssetPool.id(n.nsset));
				break;
			case CONSTANT_RTQname:
			case CONSTANT_RTQnameA:
				w.writeU30(abc.stringPool.id(n.name));
				break;
			case CONSTANT_MultinameL:
			case CONSTANT_MultinameLA:
				w.writeU30(abc.nssetPool.id(n.nsset));
				break;
			case CONSTANT_RTQnameL:
			case CONSTANT_RTQnameLA:
				break;
			default:
				assert (false);
			}
		}
		verboseStatus("name count "+abc.namePool.size()+ " size " + (w.size()-pos));
		pos = w.size();
			
		w.writeU30(abc.methodPool2.size());
		int method_id=0;
		for (Method m: abc.methodPool1.values)
			emitMethod(abc, w, method_id++, m);
		for (Method m: abc.methodPool2.values)
			emitMethod(abc, w, method_id++, m);
		
		w.writeU30(abc.metaPool.size());
		for (Metadata md: abc.metaPool.values)
		{
			w.writeU30(abc.stringPool.id(md.name));
			w.writeU30(md.attrs.length);
			for (Attr a: md.attrs)
				w.writeU30(abc.stringPool.id(a.name));
			for (Attr a: md.attrs)
				w.writeU30(abc.stringPool.id(a.value));
		}
		
		w.writeU30(abc.classes.size());
		for (Type c: abc.classes)
		{
			Type t = c.itype;
			w.writeU30(abc.namePool.id(t.getName()));
			w.writeU30(abc.typeRef(t.base));
			w.write(t.flags);
			if (t.hasProtectedNs())
				w.writeU30(abc.nsPool.id(t.protectedNs));
			w.writeU30(t.interfaces.length);
			for (Type i: t.interfaces)
				w.writeU30(abc.interfaceRef(i));
			w.writeU30(abc.methodId(t.init));
			emitTraits(w, abc, t);
		}
		
		for (Type c: abc.classes)
		{
			w.writeU30(abc.methodId(c.init));
			emitTraits(w, abc, c);
		}
		
		w.writeU30(abc.scripts.size());
		for (Type s: abc.scripts)
		{
			w.writeU30(abc.methodId(s.init));
			emitTraits(w, abc, s);
		}
		
		w.writeU30(abc.bodyCount);
		emitBodies(abc, w, abc.methodPool1);
		emitBodies(abc, w, abc.methodPool2);
	
		return w.toByteArray();
	}

	void emitNamespace(Abc emitNamespace, AbcWriter w, Namespace ns)
	{
		if (ns.isPrivateOrInternal())
		{
			// internal -> private == sealed packages!
			w.write(CONSTANT_PrivateNamespace);
			w.writeU30(0);
		}
		else
		{
			w.write(ns.kind);
			w.writeU30(emitNamespace.stringPool.id(ns.uri));
		}
	}

	void emitBodies(Abc abc, AbcWriter w, Pool<Method> pool) throws IOException
	{
		for (Method m: pool.values)
		{
			if (m.entry == null)
				continue;
			w.writeU30(m.emit_id);
			w.writeU30(m.max_stack);
			w.writeU30(m.local_count);
			if (m.cx != null && m.cx.scopes != null)
			{
				w.writeU30(m.cx.scopes.length); // init_scope_depth
				w.writeU30(m.cx.scopes.length+m.max_scope); // max_scope_depth
			}
			else
			{
				w.writeU30(0); // init_scope_depth
				w.writeU30(m.max_scope); // max_scope_depth
			}
			
			emitCode(w, abc, m);
			
			emitTraits(w, abc, m.activation.t);
		}
	}

	void emitMethod(Abc abc, AbcWriter w, int method_id, Method m)
	{
		m.emit_id = method_id;
		verboseStatus("METHOD " + method_id + " was " + m.id);
		w.writeU30(m.getParams().length-1);
		w.writeU30(abc.typeRef(m.returns));
		for (int i=1, n=m.getParams().length; i < n; i++)
			w.writeU30(abc.typeRef(m.getParams()[i]));
		
		if (PRESERVE_METHOD_NAMES)
			w.writeU30(abc.stringPool.id(m.debugName));
		else
			w.writeU30(0);
		
		int flags = m.flags;
		if (STRIP_DEBUG_INFO)
			flags &= ~METHOD_HasParamNames;
		w.write(flags);
		if (m.hasOptional())
		{
			w.writeU30(m.optional_count);
			for (int j = m.getParams().length - m.optional_count; j < m.getParams().length; j++)
			{
				int kind = abc.constKind(m.values[j]);
				w.writeU30(abc.constId(kind, m.values[j])); // index
				w.write(kind);
			}
		}
		if ((flags & METHOD_HasParamNames) != 0)
		{
			for (int i=1; i < m.paramNames.length; i++)
				w.writeU30(abc.stringPool.id(m.paramNames[i].name));
		}
	}

	void emitBlock(AbcWriter out, Block b, Abc abc)
	{

		addTraceAttr("Block", b);
		
		// emit all but the last instruction of each block.
		for (Expr e: b)
		{
			//  Don't emit control-flow insns here;
			//  they're handled by intrablock
			//  processing.
			if (e.succ != null)
				break;
			
			traceEntry("Expr", "Expr", e);
			addTraceAttr("op", opNames[e.op]);
			addTraceAttr("pos", out.size());

			out.write(e.op);
			switch (e.op)
			{
			case OP_hasnext2:
				out.writeU30(e.imm[0]);
				out.writeU30(e.imm[1]);
				break;
			case OP_findproperty:
			case OP_findpropstrict:
			case OP_getlex:
			case OP_getsuper: case OP_setsuper:
			case OP_getproperty: case OP_setproperty:
			case OP_deleteproperty: case OP_getdescendants:
			case OP_initproperty:
			case OP_istype:
			case OP_coerce:
			case OP_astype:
			case OP_finddef:
					out.writeU30(abc.namePool.id(e.ref));
				break;
			case OP_callproperty:
			case OP_callproplex:
			case OP_callpropvoid:
			case OP_callsuper:
			case OP_callsupervoid:
			case OP_constructprop:
				out.writeU30(abc.namePool.id(e.ref));
				out.writeU30(argc(e));
				break;
			case OP_constructsuper:
			case OP_call:
			case OP_construct:
			case OP_newarray:
			case OP_newobject:
				out.writeU30(argc(e));
				break;
			case OP_getlocal:
			case OP_setlocal:
				if (e.imm[0] < 4)
				{
					out.rewind(1);
					out.write((e.op == OP_getlocal ? OP_getlocal0 : OP_setlocal0)+e.imm[0]);
					break;
				}
				// else fall through
			case OP_getslot:
			case OP_setslot:
			case OP_kill:
			case OP_inclocal:
			case OP_declocal:
			case OP_inclocal_i:
			case OP_declocal_i:
			case OP_newcatch:
			//case OP_getglobalslot:
			//case OP_setglobalslot:
				out.writeU30(e.imm[0]);
				break;
			case OP_newclass:
				out.writeU30(abc.classId(e.c));
				break;
			case OP_newfunction:
				out.writeU30(abc.methodId(e.m));
				break;
			case OP_applytype:
				out.writeU30(argc(e));
				break;
			case OP_callstatic:
			//case OP_callmethod:
				out.writeU30(abc.methodId(e.m));
				out.writeU30(argc(e));
				break;
			case OP_pushshort:
				out.writeU30(intValue(e.value));
				break;
			case OP_pushbyte:
				out.write(intValue(e.value));
				break;
			case OP_getscopeobject:
				out.write(e.imm[0]);
				break;
			case OP_pushstring:
			case OP_dxns:
				out.writeU30(abc.stringPool.id((String)e.value));
				break;
			case OP_debugfile:
				if (STRIP_DEBUG_INFO)
					throw new RuntimeException("impossible");
				out.writeU30(abc.stringPool.id((String)e.value));
				break;
			case OP_pushnamespace:
				out.writeU30(abc.nsPool.id((Namespace)e.value));
				break;
			case OP_pushint:
				out.writeU30(abc.intPool.id(intValue(e.value)));
				break;
			case OP_pushuint:
				out.writeU30(abc.uintPool.id(uintValue(e.value)));
				break;
			case OP_pushdouble:
				out.writeU30(abc.doublePool.id(doubleValue(e.value)));
				break;
			case OP_debugline:
			case OP_bkptline:
				if (STRIP_DEBUG_INFO)
					throw new RuntimeException("impossible");
				out.writeU30(e.imm[0]);
				break;
			case OP_debug:
				if (STRIP_DEBUG_INFO)
					throw new RuntimeException("impossible");
				out.write(e.imm[0]);
				out.writeU30(e.imm[1]);
				out.write(e.imm[2]);
				out.writeU30(e.imm[3]);
				break;
			}
		}
		

	}
	
	void emitCode(AbcWriter out, Abc abc, Method m) throws IOException
	{

		addTraceAttr("Method", m);
		
		Map<Block,Integer> padding = new HashMap<Block,Integer>();
		Deque<Block> code = schedule(m.entry.to);
		Map<Block,AbcWriter> writers = new HashMap<Block,AbcWriter>();
		
		//  Find back edges to see where we need labels
		//  Note: can't use isBackedge() here b/c schedule
		//  may not lay out blocks in the same order.
		BitSet labels = new BitSet();
		BitSet done = new BitSet();
		
		for (Block b: code)
		{
			done.set(b.id);
			for (Edge e: b.succ())
				if ( done.get(e.to.id) )
				{
					labels.set(e.to.id);
				}
		}

		// emit the code and leave room for the branch offsets,
		// and compute the final position of each block.
		Map<Block,Integer> pos = new HashMap<Block,Integer>();
		Map<Block,Integer> blockends = new HashMap<Block,Integer>();
		int code_len = 0;
		Deque<Block> work = new ArrayDeque<Block>(code);
		while (!work.isEmpty())
		{
			Block b = work.removeFirst();

			addTraceAttr("Block", b);
			addTraceAttr("pos", code_len);
			pos.put(b,code_len);
			AbcWriter w = new AbcWriter();
			writers.put(b, w);
			if (labels.get(b.id))
			{
				addTraceAttr("hasLabel");
				w.write(OP_label);
			}
			emitBlock(w, b, abc);
			
			code_len += w.size();
			Expr last = b.last();
	
			if (last.succ.length == 0)
			{
				 // returnvoid, returnvalue, or throw
				w.write(last.op);
				code_len++;
				traceEntry("TransferOut", "op", opNames[last.op]);
			}
			else if (isJump(last))
			{
				traceEntry("Jump", "target", last.succ[0].to);
				if (work.isEmpty() || last.succ[0].to != work.peekFirst())
				{
					// target is not fall through block so we'll emit a jump.
					code_len += 4;
					padding.put(b, 4);
					addTraceAttr("fallThrough", false);
				}
				else
					addTraceAttr("fallThrough", true);
			}
			else if (isBranch(last))
			{
				if (work.isEmpty() || last.succ[0].to != work.peekFirst())
				{
					code_len += 8;
					padding.put(b, 8);
				}
				else
				{
					code_len += 4;
					padding.put(b, 4);
				}
			}
			else
			{
				assert(last.op == OP_lookupswitch);
				//  Switch table contains a U30 case count and S24 offsets.
				int switch_size = 1 + out.sizeOfU30(last.succ.length) + 3*last.succ.length;
				code_len += switch_size;
				padding.put(b, switch_size);
			}
			blockends.put(b,code_len);

		}

		out.writeU30(code_len);
		int code_start = out.size();
		traceEntry("WriteCode", "Start", code_start);
		for (Block b: code)
		{

			addTraceAttr("Block", b);
			addTraceAttr("postorder", b.postorder);
			addTraceAttr("startPos", out.size());
			addTraceAttr("offset", out.size() - code_start);
			writers.get(b).writeTo(out);
			if (padding.containsKey(b))
			{
				Expr last = b.last();
				

				addTraceAttr(last);
				addTraceAttr("op", opNames[last.op]);
				addTraceAttr("padding", padding.get(b));

				if (isBranch(last))
				{
					addTraceAttr("isBranch");
					emitBranch(out, last.op, last.succ[1].to, code_start, pos);
					padding.put(b, padding.get(b)-4);
				}
				if (padding.get(b) == 4)
				{
					traceEntry("ImpliedJump");
					addTraceAttr("EdgeId", last.succ[0].id);
					emitBranch(out, OP_jump, last.succ[0].to, code_start, pos);
				}
				if ( last.op == OP_lookupswitch )
				{
					emitLookupswitch(out, last, code_start, pos);
				}

			}
			

		}

		//  Input code occasionally contains
		//  an empty (or non-effecting, and 
		//  thus effectively empty) try block.
		//  Elide these.
		
		int valid_handlers_count = 0;
		for (Handler h: m.handlers)
		{
			if ( h.entry != null )
				valid_handlers_count++;
		}
		
		out.writeU30(valid_handlers_count);
		for (Handler h: m.handlers)
		{
			if ( null == h.entry )
				continue;
			
			int from = code_len;
			int to = 0;
			for (Block b: code)
			{
				for (Edge x: b.xsucc)
				{
					if (x.to == h.entry)
					{
						if (pos.get(b) < from)
							from = pos.get(b);
						if (blockends.get(b) > to)
							to = blockends.get(b);
					}
				}
			}
			out.writeU30(from);
			out.writeU30(to);
			
			int off = pos.get(h.entry);
	
			verboseStatus("handler "+h.entry+ " ["+from+","+to+")->"+off);
			out.writeU30(off);
			out.writeU30(abc.typeRef(h.type));
			//  See corresponding logic
			//  in readCode() where the 
			//  handler's read in.
			if ( h.name != null )
				out.writeU30(abc.namePool.id(h.name));
			else
				out.writeU30(0);
		}


	}
	

	void emitBranch(AbcWriter out, int op, Block target, int code_start, Map<Block,Integer>pos)
	{
		traceEntry("emitBranch");
		addTraceAttr("op", opNames[op]);
		addTraceAttr("target", target);
		out.write(op);
		int to = code_start + pos.get(target);
		int from = out.size()+3;
		addTraceAttr("to", to);
		addTraceAttr("from", from);
		addTraceAttr("offset", to-from);
		out.writeS24(to-from);
	}
	
	void emitLookupswitch(AbcWriter out, Expr insn_switch, int code_start, Map<Block, Integer> pos)
	{

		
		//  "The base location is the address of the lookupswitch instruction itself." - AVM2 
		int base_loc = out.size();
		addTraceAttr("baseLoc", base_loc);
		
		out.write(OP_lookupswitch);
		int case_size = insn_switch.succ.length - 2;
		addTraceAttr("case_size", case_size);
		
		int default_target = code_start + pos.get(insn_switch.succ[case_size + 1].to) - base_loc;
		traceEntry("default", "target", default_target);
		addTraceAttr("Block", insn_switch.succ[case_size + 1].to);
		out.writeS24(default_target);
		out.writeU30(case_size);
		for ( int i = 0; i <= case_size; i++ )
		{
			int case_target = code_start + pos.get(insn_switch.succ[i].to) - base_loc;
			traceEntry("case", "target", case_target);
			addTraceAttr("Block", insn_switch.succ[i].to);
			out.writeS24(case_target);
		}

	}
	
	void emitTraits(AbcWriter out, Abc abc, Type t)
	{
		Symtab<Binding> defs = t.defs;
		out.writeU30(defs.size());
		for (Binding b: defs.values())
		{
			out.writeU30(abc.namePool.id(b.getName()));
			out.write(b.flags_kind & ~(TRAIT_FLAG_metadata<<4));
			switch (b.kind())
			{
			case TRAIT_Var:
			case TRAIT_Const:
				if ( t.base == null || 0 == t.base.slotCount )
					out.writeU30(b.slot);
				else
					out.write(0);
				out.writeU30(abc.typeRef(b.type));
				if (!b.defaultValueChanged())
				{
					// vm fills in default value based on type
					out.writeU30(0);
				}
				else
				{
					// non-default default value
					int kind = abc.constKind(b.value);
					int id = abc.constId(kind, b.value);
					out.writeU30(id);
					if (id != 0)
						out.write(kind);
				}
				break;
			case TRAIT_Class:
				out.writeU30(b.slot);
				out.writeU30(abc.classId(b.type.t));
				break;
			case TRAIT_Method:
			case TRAIT_Getter:
			case TRAIT_Setter:
				out.writeU30(b.slot);
				out.writeU30(abc.methodId(b.method));
				break;
			default:
				assert(false);
			}
		}
	}

	void optimize(Method m)
	{
		verboseStatus("OPTIMIZE "+m.id + " "+ m.getName());

		if(m.entry == null)
			return;
		

		addTraceAttr("Method", m);
		printMethod(m, "BEFORE OPT");
		
		if (OUTPUT_DOT)
			dot("-before",m);
		
		sccp(m);
		dvn(m);
		
		if (cfgopt(m))
		{
			printMethod(m, "AFTER CFGOPT");

			sccp(m);
			dvn(m);
		}
	
		// find operations to fold together.
		fold(m);

		printMethod(m, "AFTER FOLD");

		insert_casts(m);
		remove_phi(m);
		
		if (OUTPUT_DOT)
			dot("-after",m);
		
		if ( legacy_verifier )
		{
			appeaseLegacyVerifier(m);
			if (OUTPUT_DOT)
				dot("-appeased",m);
		}
		
		computeFrameCounts(m);
		
		if ( verbose_mode )
		{
			printabc(schedule(m.entry.to));
		}
		

	}
	
	public static byte[] optimize( byte[] raw_abc, String filename, ObjectList<ConfigVar> optimizer_configs, ObjectList<String> import_filespecs )
	throws java.io.IOException
	{
		GlobalOptimizer go = new GlobalOptimizer();
		go.legacy_verifier = true;
		
		boolean quiet_mode = false;
	
		for ( ConfigVar config_var: optimizer_configs )
		{
			if (config_var.name.equalsIgnoreCase("-IMPORT"))
			{
				go.new InputAbc().readAbc(load(config_var.value));
			}
			else if ( config_var.name.equalsIgnoreCase("-LEGACY_VERIFIER"))
			{
				go.legacy_verifier = !go.legacy_verifier;
			}
			else if ( config_var.name.equalsIgnoreCase("-PRESERVE_METHOD_NAMES"))
			{
				go.PRESERVE_METHOD_NAMES = true;
			}
			else if ( config_var.name.equalsIgnoreCase("-QUIET"))
			{
				quiet_mode = true;
			}
			else if ( config_var.name.equalsIgnoreCase("-ALLOW_NATIVE_CTORS"))
			{
				go.ALLOW_NATIVE_CTORS = true;
			}
			if ( config_var.name.equalsIgnoreCase("-plugin") )
			{
				go.loadPlugin(config_var.value);
				continue;
			}
			if ( config_var.name.startsWith("-") && config_var.name.contains(":"))
			{
				int delim_pos = config_var.name.indexOf(':');
				String plugin_name   = config_var.name.substring(1, delim_pos);
				String plugin_option = config_var.name.substring(delim_pos+1);
				
				PluginData plugin_data = go.analysis_phase_plugins.get(plugin_name);
				
				if ( null == plugin_data )
				{
					//  Iterate over the plugins and find a short
					//  name that matches this monster.
					
					for ( PluginData search_plugin: go.analysis_phase_plugins.values() )
					{
						if ( search_plugin.plugin.getClass().getSimpleName().equals(plugin_name))
						{
							plugin_data = search_plugin;
							break;
						}
					}
				}
				
				if ( null != plugin_data )
				{
					plugin_data.options.add(plugin_option);
				}
				else
				{
					throw new IllegalArgumentException("No plugin named " + plugin_name + " is loaded.");		
				}
				
				continue;
			}
			else
			{
				throw new IllegalArgumentException("Unknown -o2:configuration_value " + config_var.name);
			}
		}
		
		//  TODO: ASC and GO data structures need to interoperate.
		//  For now, just redo the imports.
		for ( String import_filespec: import_filespecs)
		{
			go.new InputAbc().readAbc(import_filespec);
		}
	
		InputAbc input_abc = go.new InputAbc();
		input_abc.src_filename = filename;
		
		input_abc.readAbc(raw_abc);
	
		go.initializePlugins();
		go.optimize(input_abc);
	
		Abc abc = go.new Abc();
	
		for (Type s: input_abc.scripts)
		{
			abc.addScript(s);
		}
		
		abc.sort();
		
		byte[] optimized_abc = go.emitAbc(abc);
		
		if ( !quiet_mode )
		{
			System.out.println("Original  ABC size: " + raw_abc.length);
			System.out.println("Optimized ABC size: " + optimized_abc.length);
		}
		
		return optimized_abc;
		
	}
	
	void fold(Method m)
	{
		Deque<Block> code = dfs(m.entry.to);
		EdgeMap<Expr> uses = findUses(code);
		for (Block b: code)
		{
			for (Expr e: b)
			{
				switch (e.op)
				{
				case OP_iftrue:
				case OP_iffalse:
				{
					Expr a0 = e.args[0];
					if (containsOnly(uses.get(a0),e))
					{
						if (false)
							;
						else if (a0.op == OP_not)
							subsume_arg(e, (e.op == OP_iftrue ? OP_iffalse : OP_iftrue), uses);

						else if (a0.op == OP_convert_b)
							subsume_arg(e, e.op, uses);

						else if (a0.op == OP_greaterequals)
							subsume_arg(e, (e.op == OP_iftrue ? OP_ifge : OP_ifnge), uses);

						else if (a0.op == OP_greaterthan)
							subsume_arg(e, (e.op == OP_iftrue ? OP_ifgt : OP_ifngt), uses);

						else if (a0.op == OP_lessthan)
							subsume_arg(e, (e.op == OP_iftrue ? OP_iflt : OP_ifnlt), uses);

						else if (a0.op == OP_lessequals)
							subsume_arg(e, (e.op == OP_iftrue ? OP_ifle : OP_ifnle), uses);

						// too aggressive, breaks (at least) zlib
						//else if (a0.op == OP_equals)
						//	subsume_arg(e, (e.op == OP_iftrue ? OP_ifeq : OP_ifne), uses);

						else if (a0.op == OP_strictequals)
							subsume_arg(e, (e.op == OP_iftrue ? OP_ifstricteq : OP_ifstrictne), uses);
					}
					break;
				}
				
				case OP_getproperty:
				{
					Expr a0 = e.args[0];
					if (containsOnly(uses.get(a0),e) &&
						a0.op == OP_findpropstrict &&
						a0.args.length == 0 &&
						e.args.length == 1)
						{
							e.op = OP_getlex;
							e.args = noexprs;
							e.scopes = a0.scopes;
							a0.setPure();
							e.flags |= a0.flags&PX | a0.flags&EFFECT;
						}
				}
				break;
				}
			}
		}
		dce(m);
	}
	
	
	
	int findPhiArg(Expr phi, Edge e)
	{
		for (int i=0, n=phi.pred.length; i < n; i++)
			if (phi.pred[i].equals(e))
				return i;
		assert(false);
		return -1;
	}
	
	/**
	 * determine if the two blocks have the same exception scope.
	 * @param b1
	 * @param b2
	 * @return
	 */
	boolean sameExScope(Block b1, Block b2)
	{
		if (b1 == b2) return true;
		Edge[] xs1 = b1.xsucc;
		Edge[] xs2 = b2.xsucc;
		if (xs1.length != xs2.length)
			return false;

		for (int i=0, n=xs1.length; i < n; i++)
		{
			Edge e1 = xs1[i];
			Edge e2 = xs2[i];
			if (e1.to != e2.to || e1.handler != e2.handler)
				return false;
		}
		return true;
	}

	/**
	 * control flow optimizations.  
	 * 
	 * turn B1->B2 into B1B2 as long as B1's only successor is B2 and B2's only predecessor is B1.
	 * 
	 * any branch to a jump can branch to the jump's target
	 * 
	 * jump to a return can be replaced by the return
	 * 
	 * ISSUE phi's represent copies on an edge.  Need to validate that removing
	 * edges doesn't remove a required phi-copy.  Any critical edges that have
	 * been split by previous operations may be removed by this pass.
	 * 
	 * Should we only do this pass on non-ssa form?
	 */
	boolean cfgopt(Method m)
	{
		Deque<Block> code = dfs(m.entry.to);
		SetMap<Block,Edge> pred = allpreds(code);

		boolean changedout=false;
		boolean changed;
		do
		{
			changed = false;
			blocks: for (Block b: code)
			{
				Expr last = b.last();
				Block taken;
				if (isJump(last) && sameExScope(b, taken=last.succ[0].to))
				{
					Edge s = last.succ[0];
					if (containsOnly(pred.get(taken), s) && !taken.must_isolate_block)
					{
						// phi nodes can only occur in nodes with more than one predecessor
						assert(taken.first().op != OP_phi);
						verboseStatus("STRAIGHTEN "+s);
						b.remove(last);
						b.addAll(taken);
						for (Edge edge: taken.succ())
							edge.from = b;
						changed = true;
						printabc(b, new PrintWriter(System.out));
						break blocks;
					}
					Expr first = taken.first();
					if (first.op == OP_returnvalue || first.op == OP_returnvoid)
					{
						verboseStatus("PRUNE "+b+"->"+s);
						last.op = first.op;
						last.args = first.op == OP_returnvoid ? noexprs : new Expr[] { first.args[0] };
						last.succ = noedges;
						changed = true;
						break blocks;
					}
					Expr r;
					if (first.op == OP_phi && taken.size()==2 && (r=taken.last()).op == OP_returnvalue &&
							r.args[0] == first)
					{
						// successor block is returnvalue(phi)
						verboseStatus("PRUNE "+b+"->"+s);
						int i = findPhiArg(first, last.succ[0]);
						last.op = r.op;
						last.args = new Expr[] { first.args[i] };
						last.succ = noedges;
						first.removePhiInput(i);
						changed = true;
						break blocks;
					}
				}

				if (isBranch(last))
				{
					Edge out = last.succ[1];
					Expr cond = last.args[0];
					taken = out.to;
					Expr phi, br;
					if (last.args.length == 1 && taken.size()==2 && (phi=taken.first()).op==OP_phi && 
							((br=taken.last()).op == OP_iftrue || br.op == OP_iffalse))
					{
						int i = findPhiArg(phi,out);
						if (phi.args[i]==cond)
						{
							// cond is in phi contributed by this edge.  so we have a redundant test.
							// we want to retarget the branch: and adjust any phi nodes that are affected.
							Edge before = br.op == last.op ? br.succ[1] : br.succ[0];
							verboseStatus("SKIPTEST old "+out+" new "+before);
							phi.removePhiInput(i);
							copyTargetPhi(phi, cond, before, out);
							changed = true;
							break blocks;
						}
					}
					
					if (pred.get(last.succ[0].to).size() > 1 && pred.get(taken).size() == 1)
					{
						// fall through has multiple preds, taken has only one.  reverse the sense
						// of the test and reverse the edges.  Note that this doesn't change the
						// flow so we don't need to recompute preds, etc.
						invert(last);
						changed = true;
						break blocks;
					}
				}

				for (Edge edge : last.succ)
				{
					if (skip(edge))
					{
						changed = true;
						break blocks;
					}
				}
			}
			
			if (changed)
			{
				dce(m);
				code = dfs(m.entry.to);
				pred = allpreds(code);
				changedout = true;
			}
		}
		while (changed);
		return changedout;
	}
	
	boolean skip(Edge edge)
	{
		Block to = edge.to;
		Expr j = to.last();
		if (to.size()==1 && isJump(j))
		{
			// any edge targeting a jump can target the jump's target.
			verboseStatus("SKIP " + j.succ[0]);
			copyTarget(j.succ[0], edge);
			return true;
		}
		return false;
	}
	
	/**
	 * reverse the sense of a conditional test and swap the outgoing edges.
	 * @param br
	 */
	void invert(Expr br)
	{
		verboseStatus("INVERT "+br);

		switch (br.op)
		{
		case OP_iftrue:		br.op = OP_iffalse; break;
		case OP_iffalse:	br.op = OP_iftrue; break;
		case OP_ifnlt:		br.op = OP_iflt; break;
		case OP_ifnle:		br.op = OP_ifle; break;
		case OP_ifngt:		br.op = OP_ifgt; break;
		case OP_ifnge:		br.op = OP_ifge; break;
		case OP_ifeq:		br.op = OP_ifne; break;
		case OP_ifne:		br.op = OP_ifeq; break;
		case OP_iflt:		br.op = OP_ifnlt; break;
		case OP_ifle:		br.op = OP_ifnle; break;
		case OP_ifgt:		br.op = OP_ifngt; break;
		case OP_ifge:		br.op = OP_ifnge; break;
		case OP_ifstricteq:	br.op = OP_ifstrictne; break;
		case OP_ifstrictne:br.op = OP_ifstricteq; break;
		}
		
		Edge e0 = br.succ[0];
		Edge e1 = br.succ[1];
		e0.label = 1;
		e1.label = 0;
		br.succ[0] = e1;
		br.succ[1] = e0;
	}
	
	int ifoper(int op)
	{
		switch (op)
		{
		default: assert(false); return 0;
		case OP_iflt:
		case OP_ifnlt:		return OP_lessthan;
		case OP_ifle:
		case OP_ifnle:		return OP_lessequals;
		case OP_ifgt:
		case OP_ifngt:		return OP_greaterthan;
		case OP_ifge:
		case OP_ifnge:		return OP_greaterequals;
		case OP_ifne:
		case OP_ifeq:		return OP_equals;
		case OP_ifstricteq:
		case OP_ifstrictne:	return OP_strictequals;
		}
	}
	
	/**
	 * for each phi in the target block, add a new phi arg for the new edge,
	 * contributing the same variable that the old edge contributed. 
	 * @param succ
	 * @param oldpred
	 * @param newpred
	 */
	void copyTarget(Edge before, Edge after)
	{
		after.to = before.to;
		for (Expr e: before.to)
			if (e.op == OP_phi)
				e.append(e.args[findPhiArg(e,before)], after);
	}
	
	void copyTargetPhi(Expr phi, Expr a, Edge before, Edge after)
	{
		after.to = before.to;
		for (Expr e: before.to)
		{
			if (e.op == OP_phi)
			{
				Expr phiArg = e.args[findPhiArg(e,before)];
				e.append(phiArg==phi ? a : phiArg, after);
			}
			else
				break;
		}
	}
	
	boolean containsOnly(Collection c, Object elem)
	{
		return c.size() == 1 && c.contains(elem);
	}
	
	boolean equiv(Name a, Name b)
	{
		return a.match(b) == 0;
	}
	
	boolean equiv(Expr[] a, Expr[] b)
	{
		if (a == null || b == null) return false;
		if (a.length != b.length) return false;
		for (int i=0; i < a.length; i++)
			if (!equiv(a[i],b[i]))
				return false;
		return true;
	}
	
	boolean equiv(Expr a, Expr b)
	{
		if (a == b)
			return true;
		
		if (a != null && b != null && a.op == b.op)
		{
			switch (a.op)
			{
			case OP_pushtrue:
			case OP_pushfalse:
			case OP_pushnan:
			case OP_pushnull:
			case OP_pushundefined:
			case OP_getlocal0:
			case OP_getlocal1:
			case OP_getlocal2:
			case OP_getlocal3:
				return true;
			case OP_pushbyte:
			case OP_pushshort:
			case OP_pushint:
			case OP_pushuint:
			case OP_pushdouble:
			case OP_pushnamespace:
			case OP_pushstring:
				return a.value.equals(b.value);
			case OP_getlocal:
			case OP_arg:
				return a.imm[0] == b.imm[0];
			case OP_getglobalscope:
				return a.scopes.length == 0 && b.scopes.length == 0 ||
					a.scopes.length > 0 && b.scopes.length > 0 && equiv(a.scopes[0], b.scopes[0]);
			/*case OP_getslot:
				// TODO unsafe, don't know about intervening stores
				return a.imm[0] == b.imm[0] && equiv(a.args[0],b.args[0]);
			case OP_getproperty:
				// TODO unsafe -- ignores intervening stores & side effects
				return equiv(a.ref, b.ref) && equiv(a.args,b.args);*/
			case OP_finddef:
				return 0 == a.ref.match(b.ref);
			}
		}
		return false;
	}
	
	void makeCopy(Expr e, Expr a)
	{
		// make e be a copy of a
		assert(e != a);
		e.op = OP_dup;
		e.locals = new Expr[] { a };
		e.scopes = e.args = noexprs;
		e.setPure();
	}
	
	void makeNop(Expr e)
	{
		e.op = OP_nop;
		e.args = e.locals = e.scopes = noexprs;
		e.setPure();
	}
	
	Expr dvn_find(Expr e, Block b, Map<Block,Block>idom)
	{
		do
		{
			for (Expr a: b)
			{
				if (a == e) break;
				if (equiv(a,e))
					return a;
			}
			b = idom.get(b);
		}
		while (b != null);
		return null;
	}
	
	/**
	 * dominator based value numbering.  This is just LVN plus a search up the
	 * dominator tree.  When a matching expression is found turn the
	 * instruction into a copy of the found expression.
	 * @param code
	 */
	void dvn(Method m)
	{
		Deque<Block> code = dfs(m.entry.to);
		Map<Block,Block> idom = idoms(code, preds(code));
		boolean changed;
		do
		{
			changed = false;
			for (Block b: code)
			{
				for (Expr e: b)
				{
					Expr a = dvn_find(e, b, idom);
					if (a != null)
					{
						makeCopy(e,a);
						changed = true;
					}
				}
			}
			if (changed)
				dce(m);
		}
		while (changed);
	}
	
	boolean constify(Expr e, Object v)
	{
		if (v != null && v != BOTTOM && e.value == null && !hasSideEffect(e))
		{
			// expr is const
			if (v instanceof Integer)
			{
				int i = intValue(v);
				e.op = (i == (byte)i) ? OP_pushbyte :
					   (i == (short)i) ? OP_pushshort :
						   OP_pushint;
			}
			else if (v instanceof Long)
			{
				e.op = OP_pushuint;
			}
			else if (v instanceof Number)
			{
				double d = doubleValue(v);
				e.op = Double.isNaN(d) ? OP_pushnan : OP_pushdouble;
			}
			else if (v instanceof Boolean)
			{
				e.op = v == TRUE ? OP_pushtrue : OP_pushfalse;
			}
			else if (v instanceof Namespace)
			{
				e.op = OP_pushnamespace;
			}
			else if (v == UNDEFINED)
			{
				e.op = OP_pushundefined;
			}
			else if (v == NULL())
			{
				assert(!e.onScope());
				e.op = OP_pushnull;
			}
			else
			{
				assert(v instanceof String);
				e.op = OP_pushstring;
			}
			e.pred = noedges;
			e.args = e.scopes = e.locals = noexprs;
			e.value = v;
			return true;
		}
		return false;
	}
	
	boolean jumpify(Expr e, Set<Edge> reached)
	{
		Edge taken = null;
		for (Edge s: e.succ)
		{
			if (reached.contains(s))
			{
				if (taken == null)
					taken = s;
				else if (s != taken)
				{
					taken = null;
					break;
				}
			}
		}
		if (taken != null)
		{
			e.op = OP_jump;
			e.args = noexprs;
			e.succ = new Edge[] { taken };
			return true;
		}
		return false;
	}
	
	boolean makeConvert(Expr e, Type t, int op, Map<Expr,Typeref> types)
	{
		e.op = op;
		e.args = new Expr[] { e.args[1] };
		e.flags = flagTable[op];
		if (type(types,e.args[0]).isPrimitive()) 
			e.setPure();
		return true;
	}
	
	boolean convertify(Expr e, Binding b0, Map<Expr,Typeref>types)
	{
		if (b0.type != null && e.args.length == 2)
		{
			if (b0.type.t.itype == NUMBER()) 
				return makeConvert(e,NUMBER(),OP_convert_d,types);
			if (b0.type.t.itype == INT()) 
				return makeConvert(e,INT(),OP_convert_i,types);
			if (b0.type.t.itype == UINT()) 
				return makeConvert(e,UINT(),OP_convert_u,types);
			if (b0.type.t.itype == STRING()) 
				return makeConvert(e,STRING(),OP_convert_s,types);
			if (b0.type.t.itype == BOOLEAN())
				return makeConvert(e,BOOLEAN(),OP_convert_b,types);
		}
		return false;
	}
	
	Expr unwrapScope(Expr e, int i)
	{
		//  Phi pseudo-Exprs may appear in the scope stack
		//  if the block immediately follows a try/catch,
		//  or if the block is the fall-through alternative
		//  of a conditional jump.  In either of these cases,
		//  the compiler set up all phi inputs to refer back
		//  to the same underlying object, so just traverse
		//  back along the first dataflow edge.
		while ( e.scopes[i].op == OP_phi )
		{
			assert(e.scopes[i].args != null && e.scopes[i].args[0] != null);
			e.scopes[i] = e.scopes[i].args[0];
		}
		
		assert(e.scopes[i].onScope());
		return e.scopes[i].args[0];
	}
	
	static Type[] copyOf(Type[] in, int newlen)
	{
		Type[] out = new Type[newlen];
		if (newlen > in.length)
			newlen = in.length;
		System.arraycopy(in, 0, out, 0, newlen);
		return out;
	}

	static Typeref[] copyOf(Typeref[] in, int newlen)
	{
		Typeref[] out = new Typeref[newlen];
		if (newlen > in.length)
			newlen = in.length;
		System.arraycopy(in, 0, out, 0, newlen);
		return out;
	}
	
	static Expr[] copyOf(Expr[] in, int newlen)
	{
		Expr[] out = new Expr[newlen];
		if (newlen > in.length)
			newlen = in.length;
		System.arraycopy(in, 0, out, 0, newlen);
		return out;
	}
	
	static Edge[] copyOf(Edge[] in, int newlen)
	{
		Edge[] out = new Edge[newlen];
		if (newlen > in.length)
			newlen = in.length;
		System.arraycopy(in, 0, out, 0, newlen);
		return out;
	}
	
	/**
	 * sparse conditional constant propagation
	 * @param code
	 */
	void sccp(Method m)
	{

		addTraceAttr("Method", m);
		
		// first build the SSA Edges.
		Deque<Block> code = dfs(m.entry.to);
		EdgeMap<Expr> uses = findUses(code);

		Map<Expr,Object> values = new TreeMap<Expr,Object>();
		Map<Expr,Typeref> types = new TreeMap<Expr,Typeref>();
		Set<Edge> reached = new TreeSet<Edge>();
		
		sccp_analyze(m, uses, values, types, reached);

		verboseStatus("REACHED " + reached);
		verboseStatus("TYPES " + types);
	
		sccp_cfgopt(values, types, reached);
		
		// now the CFG is cleaned up
		dce(m);
		
		// now do type/value based peephole work on each expr in DFS order
		code = dfs(m.entry.to);
		uses = findUses(code);
		
		// modify the code based on analysis:
		// * capture scope types for OP_newclass & OP_newfunction
		// * turn expressions into constants
		
		TreeSet<Expr> work = new TreeSet<Expr>();
		for (Block b: code)
			for (Expr e: b)
				work.add(e);

		while (!work.isEmpty())
		{
			Expr e = getExpr(work);
			sccp_modify(m, uses, values, types, e, work);
		}
		
		dce(m);
		//verboseStatus("after sccp");
		//print(dfs(m.entry.to));

	}

	void sccp_cfgopt(Map<Expr, Object> values, Map<Expr,Typeref> types, Set<Edge> reached)
	{
		Set<Block> blocks = new TreeSet<Block>();
		for (Edge e: reached)
			blocks.add(e.to);

		for (Block b: blocks)
		{
			// clean up phis
			for (Expr e: b)
			{
				if (e.op == OP_phi)
				{
					for (int j=e.pred.length-1; j >= 0; j--)
					{
						Edge p = e.pred[j];
						if (!reached.contains(p))
							e.removePhiInput(j);
					}
				}
				else if (e.succ != null)
				{
					if (e.succ.length > 1 && !jumpify(e, reached) && e.op == OP_lookupswitch)
					{
						Expr phi;
						if (b.size()==2 && (phi=b.first()).op == OP_phi && e.args[0]==phi)
						{
							// block is switch(phi)
							// TODO what about a switch with only some branches not taken?
							for (int i=phi.args.length-1; i >= 0; i--)
							{
								Object v = values.get(phi.args[i]);
								if (v instanceof Number)
								{
									int j = intValue(v);
									Edge in = phi.pred[i];
									Edge out = e.succ[j];
									copyTarget(out, in);
									phi.removePhiInput(i);
								}
							}
						}
					}
				}
				else if (e.isOper() && e.onStack())
				{
					boolean pure = true;
					for (Expr a: e.args) if (!type(types,a).isPrimitive()) pure = false;
					for (Expr a: e.locals) if (!type(types,a).isPrimitive()) pure = false;
					if (pure)
						e.setPure();
					constify(e, values.get(e));
				}
			}
		}
	}
	
	boolean subsume_arg(Expr e, int op, EdgeMap<Expr>uses)
	{
		e.op = op;
		Expr a = e.args[0];
		e.flags |= a.flags & (PX|EFFECT);
		a.setPure(); // so it becomes dead and is removed.
		uses.get(a).remove(e);
		e.args = copyOf(a.args, a.args.length);
		for (Expr x: e.args)
			uses.get(x).add(e);
		return true;
	}

	boolean canEarlyBindMethod(Method m, Binding b)
	{
		return m.abc.mergedAbcs.contains(b.abc);
	}
	
	boolean canEarlyBindSlot(Method m, Binding b)
	{
		return b.slot != 0 && m.abc.mergedAbcs.contains(b.abc);
	}
	
	static final Name AS3_TOSTRING = new Name(Name.AS3, "toString");

	void sccp_modify(Method m, EdgeMap<Expr> uses, Map<Expr, Object> values, Map<Expr, Typeref> types, 
			Expr e, TreeSet<Expr> work)
	{
		sccp_rename(uses, e, e.args);
		sccp_rename(uses, e, e.locals);
		boolean changed;
		do
		{
			changed = false;
			switch (e.op)
			{
			case OP_newclass:
			{
				// capture scope chain
				Type c = e.c;
				c.scopes = copyOf(m.cx.scopes, m.cx.scopes.length+e.scopes.length);
				int i = m.cx.scopes.length;
				for (Expr s: e.scopes)
					c.scopes[i++] = types.get(s);
				readyType(c);
				
				Type t = c.itype;
				t.scopes = copyOf(c.scopes, c.scopes.length+1);
				t.scopes[c.scopes.length] = c.ref.nonnull();
				readyType(t);
				break;
			}
			case OP_newfunction:
			{
				Method f = e.m;
				// TODO makeIntoPrototypeFunction()
				Type t = new Type(m.getName(), FUNCTION());
				t.scopes = copyOf(m.cx.scopes, m.cx.scopes.length+e.scopes.length);
				int i = m.cx.scopes.length;
				for (Expr s: e.scopes)
					t.scopes[i++] = types.get(s);
				f.cx = t;
				readyMethod(f);
				break;
			}
			case OP_returnvalue:
				if (type(types,e.args[0]) == VOID())
				{
					e.op = OP_returnvoid;
					e.args = noexprs;
				}
				else
				{
					Type t0 = type(types,e.args[0]);
					if (t0.extendsOrIsBase(m.returns.t))
					{
						Expr a0 = e.args[0];
						if (m.returns.t == INT() && a0.op == OP_convert_i)
						{
							uses.get(a0).remove(e);
							a0 = e.args[0] = a0.args[0];
							uses.get(a0).add(e);
						}
					}
				}
				break;
	
			case OP_getglobalscope:
			{
				if (m.cx.scopes.length == 0)
				{
					// global is inner scope 0, so copy that
					makeCopy(e, unwrapScope(e, 0));
					changed = true;
				}
				break;
			}
			
			case OP_getscopeobject:
			{
				makeCopy(e, unwrapScope(e, 0));
				changed = true;
				break;
			}
			
			case OP_istypelate:
			{
				Type t1 = type(types,e.args[1]);
				if (t1.itype != null && TypeCache.instance().containsNamedType(t1.itype))
				{
					e.op = OP_istype;
					e.ref = t1.itype.getName();
					e.args = new Expr[] { e.args[0] };
					e.clearPx();
					changed = true;
				}
				break;
			}
			
			case OP_istype:
			{
				if (TypeCache.instance().containsNamedType(e.ref))
					e.clearPx();
				break;
			}
			
			case OP_pushscope:
			case OP_pushwith:
			{
				if (!types.get(e.args[0]).nullable)
					e.clearPx();
				break;
			}
			
			case OP_coerce:
			{
				Expr a0 = e.args[0];
				Typeref t = types.get(e);
				Typeref t0 = types.get(a0);
				if (t == t0)
				{
					// upcast
					makeCopy(e, a0);
					changed = true;
				}
				else
				{
					Object v0 = values.get(a0);
					if (v0 == NULL() && t0.nullable && t0.t != VOID())
					{
						makeCopy(e, a0);
						changed = true;
					}
					else
					{
						if (TypeCache.instance().namedTypes.get(e.ref) == OBJECT())
						{
							e.op = OP_coerce_o;
							e.clearEffect();
							e.ref = null;
							e.imm = null;
							changed = true;
						}
					}
				}
				break;
			}
			
			// turn findprop into either getglobalscope, getscopeobject, or finddef to expose redundancies
			case OP_findpropstrict:
			case OP_findproperty:
			{
				int i = findInner(e.ref, e.scopes, types);
				if (i >= 0)
				{
					makeCopy(e, unwrapScope(e,i));
					for (Expr s: e.scopes)
						uses.get(s).remove(e);
					changed = true;
				}
				else if ((i = findOuter(e.ref, m.cx.scopes)) >= 0)
				{
					if (i == 0) // getglobalscope
					{
						e.op = OP_getglobalscope;
						e.scopes = noexprs;
						e.setPure();
						for (Expr s: e.scopes)
							uses.get(s).remove(e);
						changed = true;
					}
					else
					{
						// can't change the opcode
						e.setPure();
						// TODO - early bind e.ref
					}
				}
				else if (TypeCache.instance().globals.contains(e.ref))
				{
					e.op = OP_finddef;
					e.flags = flagTable[e.op];
					e.scopes = noexprs;
					e.ref = TypeCache.instance().globals.getName(e.ref);
					for (Expr s: e.scopes)
						uses.get(s).remove(e);
					changed = true;
				}
				/*
				 * TODO: This transformation is too simplistic.
				 * 
				else if (e.op == OP_findproperty)
				{
					// will return global if nothing found.
					if (m.cx.scopes.length == 0)
					{
						makeCopy(e, unwrapScope(e,0));
						for (Expr s: e.scopes)
							uses.get(s).remove(e);
						changed = true;
					}
					else
					{
						e.op = OP_getglobalscope;
						for (Expr s: e.scopes)
							uses.get(s).remove(e);
						e.scopes = noexprs;
						e.setPure();
						changed = true;
					}
				}
				*/
				break;
			}
			
			// getsuper should look in base of enclosing type.
			// if either bind to a final getter, use callstatic.
			
			case OP_getproperty:
			case OP_getsuper:
			{
				Typeref t0 = types.get(e.args[0]);
				Binding bind = t0.findGet(e.ref);
				if (isSlot(bind))
				{
					e.clearEffect();
					if (!t0.nullable)
						e.clearPx();
					e.ref = bind.getName();
					if (canEarlyBindSlot(m, bind))
					{
						if (!isConst(bind) || !constify(e, values.get(e)))
						{
							e.op = OP_getslot;
							e.imm = new int[] { bind.slot };
							changed = true;
						}
					}
				}
				else if (bind != null)
				{
					// narrow the binding
					e.ref = bind.getName();
				}
				break;
			}
			
			case OP_initproperty:
			{
				Type t0 = type(types,e.args[0]);
				Object v1 = values.get(e.args[1]);
				Binding bind = t0.find(e.ref);
				if (bind != null)
				{
					// narrow the binding
					e.ref = bind.getName();
					// isSlot() is to aggressive, breaks (at least) zlib
					if (isConst(bind) && bind.value != null && bind.value.equals(v1))
					{
						// initializing a slot to it's known default value?
						// TODO ensure no intervening writes to non-const values
						makeNop(e);
						for (Expr a: e.args) 
							uses.get(a).remove(e);
					}	
					else if (isSlot(bind) && canEarlyBindSlot(m, bind))
					{	
						e.op = OP_setslot;
						e.imm = new int[] { bind.slot };
						changed = true;
					}
				}
				break;
			}
			
			case OP_setproperty:
			case OP_setsuper:
			{
				Type t0 = type(types,e.args[0]);
				Binding bind = t0.find(e.ref);
				if (isSlot(bind))
				{
					e.ref = bind.getName();
					if (canEarlyBindSlot(m, bind))
					{
						e.op = OP_setslot;
						e.imm = new int[] { bind.slot };
						changed = true;
					}
				}
				else if (bind != null)
				{
					// narrow the binding
					e.ref = bind.getName();
				}
				break;
			}
			
			case OP_callproperty:
			case OP_callproplex:
			case OP_callsuper:
			case OP_constructprop:
			case OP_callpropvoid:
			{
				// TODO turn callproplex into callproperty if binding is method
				Type t0 = type(types,e.args[0]);
				Binding b0 = t0.findGet(e.ref);
				if (b0 != null)
				{
					// narrow the binding
					e.ref = b0.getName();
					if (e.op == OP_callproperty && isMethod(b0))
					{
						if (t0.isPrimitive() && e.args.length==1 && e.ref.equals(AS3_TOSTRING) && type(types,e) == STRING())
						{
							// TODO this may open up further reductions.  how to iterate?
							// or, need to add similar logic in sccp_eval
							e.op = OP_convert_s;
							e.setPure();
							changed=true;
						}
						else if (canEarlyBindMethod(m,b0) && (t0.isFinal() || b0.isFinal()))
						{
							e.op = OP_callstatic;
							e.m = b0.method;
							changed=true;
						}
						else if (USE_CALLMETHOD && canEarlyBindMethod(m,b0))
						{
							e.op = OP_callmethod;
							e.imm = new int[] { b0.slot };
							changed = true;
						}
					}
					else if (e.op == OP_callproperty && isClass(b0))
					{
						changed |= convertify(e, b0, types);
					}
				}
				if (uses.get(e).isEmpty())
				{
					if (e.op == OP_callsuper) 
						e.op = OP_callsupervoid;
					if (e.op == OP_callproperty)
						e.op = OP_callpropvoid;
				}
				break;
			}
			
			case OP_convert_u:
				if (e.args[0].op == OP_convert_i)
					e.args[0] = e.args[0].args[0];
				// fall through
			case OP_coerce_s:
			case OP_convert_s:
			case OP_convert_d:
			case OP_coerce_o:
			case OP_convert_b:
			case OP_convert_i:
			case OP_coerce_a:
			{
				Expr a0 = e.args[0];
				Type t = type(types,e);
				Type t0 = type(types,e.args[0]);
				if (t == t0)
				{
					makeCopy(e,e.args[0]);
					changed=true;
				}
				else if (e.op == OP_convert_i)
				{
					if (a0.op == OP_negate)
					{
						// convert_i(negate(x)) => negate_i(x)
						e.op = OP_negate_i;
						e.args = new Expr[] { a0.args[0] };
						changed=true;
					}
					else if (a0.op == OP_decrement)
					{
						e.op = OP_decrement_i;
						e.args = new Expr[] { a0.args[0] };
						changed = true;
					}
				}
				break;
			}
			
			case OP_subtract:
			{
				Object v1 = values.get(e.args[1]);
				if (doubleValue(v1) == 1)
				{
					e.args = new Expr[] { e.args[0] };
					e.op = OP_decrement;
					changed = true;
				}
				else if (doubleValue(v1) == -1)
				{
					e.args = new Expr[] { e.args[0] };
					e.op = OP_increment;
					changed = true;
				}
				break;
			}
			
			case OP_add:
			{
				Type t = type(types,e);
				Object v0 = values.get(e.args[0]);
				Object v1 = values.get(e.args[1]);
				if (t.numeric)
				{
					if (doubleValue(v0)==1)
					{
						e.args = new Expr[] { e.args[1] };
						e.op = OP_increment;
						changed = true;
					}
					else if (doubleValue(v1)==1)
					{
						e.args = new Expr[] { e.args[0] };
						e.op = OP_increment;
						changed = true;
					}
					else if (doubleValue(v0) == -1)
					{
						e.args = new Expr[] { e.args[1] };
						e.op = OP_decrement;
						changed = true;
					}
					else if (doubleValue(v1) == -1)
					{
						e.args = new Expr[] { e.args[0] };
						e.op = OP_decrement;
						changed = true;
					}
				}
				else if (t == STRING())
				{
					if ("".equals(v0))
					{
						e.args = new Expr[] { e.args[1] };
						e.op = OP_convert_s;
						changed = true;
					}
					else if ("".equals(v1))
					{
						e.args = new Expr[] { e.args[0] };
						e.op = OP_convert_s;
						changed = true;
					}
				}
			}
			}
		
			if (changed)
				work.addAll(uses.get(e));
		}
		while (changed);
	}

	void sccp_rename(EdgeMap<Expr> uses, Expr e, Expr[]args)
	{

		addTraceAttr(e);
		
		for (int i=args.length-1; i >= 0; i--)
		{
			Expr a = args[i];
			if (a.op == OP_dup)
			{
				uses.get(a).remove(e);
				a = args[i] = a.locals[0];
				traceEntry("renamedLocal");
				addTraceAttr(a);
				uses.get(a).add(e);
			}
		}
		

	}
	
	Map<Expr,Typeref> verify_types(Method m, Deque<Block> code, Map<Block,Block> idom)
	{
		EdgeMap<Expr> uses = findUses(code);
		Map<Expr,Typeref> types = new TreeMap<Expr,Typeref>();
		Set<Expr> work = new TreeSet<Expr>();
		for (Block b: code)
			work.addAll(b.exprs);
		do
		{
			Expr e = getExpr(work);
			if (e.onStack() || e.inLocal() || e.onScope() || e.op==OP_phi)
			{
				Typeref tref = verify_eval(m, e, types, idom);
				if (!tref.equals(types.get(e)))
				{
					types.put(e, tref);
					work.addAll(uses.get(e));
				}
			}
		}
		while (!work.isEmpty());
		return types;
	}

	void sccp_analyze(Method m, EdgeMap<Expr> uses, Map<Expr, Object> values, Map<Expr, Typeref> types, Set<Edge> reached)
	{

		addTraceAttr("Method", m);
	
		Set<Edge> flowWork = new TreeSet<Edge>();
		Set<Expr> ssaWork = new TreeSet<Expr>();
		Set<Expr> ready = new TreeSet<Expr>();

		flowWork.add(m.entry);
		do
		{
			while (!flowWork.isEmpty())
			{
				Edge edge = getEdge(flowWork);
				if (!reached.contains(edge))
				{
					reached.add(edge);
					Block b = edge.to;
					ready.addAll(b.exprs);
					ssaWork.addAll(b.exprs);
					for (Edge x: b.xsucc)
						flowWork.add(x);
				}
			}
			while (!ssaWork.isEmpty())
			{
				Expr e = getExpr(ssaWork);
				if (ready.contains(e))
				{

					addTraceAttr("Expr", e);
					sccp_eval(m, e, values, types, flowWork, ssaWork, uses);

				}
			}
		}
		while (!flowWork.isEmpty());

	}

	void insert_casts(Method m)
	{
		Deque<Block> code = dfs(m.entry.to);
		SetMap<Block,Edge> pred = preds(code);
		Map<Block,Block> idom = idoms(code, pred);
		m.verifier_types = verify_types(m, code, idom);
		

		
		// TODO this fixes things by inserting upcasts only.  We could use
		// the types we know from sccp_analyze and insert casts that tell
		// the verifier what we know that it can't figure out on its own.
		// this can be done expression by expression rather than looking
		// at phi nodes & splitting critical edges.
		
		// it would also be a good sanity check.  If the verifier deduces a
		// more specific type than we have, then we have a bug in either the
		// verifier or the optimizer.

		for (Block b: code)
		{
			for (Expr e: b)
			{
				if (e.op == OP_phi)
				{
					Typeref etype = m.verifier_types.get(e);  // merged type, possibly mdb of arg types
					for (int i=e.args.length-1; i >= 0; i--)
					{
						Expr a = e.args[i];
						Edge p = e.pred[i];
						
						if ( a.onScope() )
							continue;
	
						Typeref atype = m.verifier_types.get(a);
						if (isLoop(p, idom) ? !etype.equals(atype) : etype.t.isAtom() != atype.t.isAtom())
						{
							// skip String->String?
							if((etype.t == atype.t) && etype.nullable)
								continue;
							
							verboseStatus("MISSING CAST " + a + " " + atype+"->"+etype+" on " + p);

							if (isCritical(p,pred))
							{
								split(p, m, pred);
								p = e.pred[i];
							}
							// TODO best to insert this right after a?
							Expr upcast = upcast(a, m, etype.t);
							append(p, upcast);
							e.args[i] = upcast;

						}
					}
				}
			}
		}
		
		verboseStatus("VERIFY TYPES "+m.verifier_types);
		

	}
	
	Expr upcast(Expr a, Method m, Type t)
	{
		if (t == ANY())
		{
			return new Expr(m, OP_coerce_a, a);
		}
		else if (t == OBJECT())
		{
			return new Expr(m, OP_coerce_o, a);
		}

		return new Expr(m, OP_coerce, t.getName(), a);
	}

	/**
	 * visit a single expression.  compute it's type and constant value.  If
	 * either change, add any dependents to the appropriate work list.
	 * 
	 * @param m
	 * @param e
	 * @param values
	 * @param types
	 * @param flowWork
	 * @param ssaWork
	 * @param uses
	 */
	void sccp_eval(Method m, Expr e, 
			Map<Expr,Object> values, 
			Map<Expr,Typeref> types,
			Set<Edge>flowWork, Set<Expr>ssaWork, 
			EdgeMap<Expr> uses)
	{
		Object v = null;
		Typeref tref = null;
		
		if (e.op == OP_phi)
		{
			for (Expr a: e.args)
			{
				// compute the phi() meet operation.  ignore any inputs we
				// haven't evaluated yet.  If all inputs have the same value,
				// phi() has that value.  Otherwise return BOTTOM.
				Object av = values.get(a);
				if (av == null) continue; // ignore TOP inputs
				
				if (v == null)
					v = av;
				else if (!av.equals(v))
					v = BOTTOM;
				
				// same idea for types, but if they aren't all the same
				// then compute the most derived base class (mdb) of the types.
				Typeref aref = types.get(a);
				if (tref == null)
					tref = aref;
				else if (!tref.equals(aref))
					tref = mdb(tref,aref);
			}
		}
		else
		{
			// if any arg is TOP result is TOP (unchanged)
			for (Expr a : e.args) if (!values.containsKey(a))	return;
			for (Expr a : e.scopes) if (!values.containsKey(a))	return;
			for (Expr a : e.locals) if (!values.containsKey(a))	return;
			
			v = BOTTOM;
			tref = ANY().ref;
			
			switch (e.op)
			{
			default:
				System.err.println("unhandled op:" + e.op + ":"+ opNames[e.op]);
				assert(false);
			
			case OP_hasnext2_o:
			case OP_nextname:
			case OP_nextvalue:
			case OP_call:
			case OP_callsuper:
			case OP_getsuper:
			case OP_getdescendants:
				break;
				
			case OP_convert_o:
			{
				tref = types.get(e.args[0]).nonnull();
				v = values.get(e.args[0]);
				break;
			}	
			case OP_esc_xattr:
			case OP_esc_xelem:
				tref = STRING().ref.nonnull();
				break;
				
			case OP_newcatch:
				tref = m.handlers[e.imm[0]].activation;
				break;
				
			case OP_newobject:
				tref = OBJECT().ref.nonnull();
				break;
			
			case OP_newarray:
				tref = ARRAY().ref.nonnull();
				break;
				
			case OP_newactivation:
				tref = m.activation;
				break;
				
			case OP_getglobalscope:
				if (m.cx.scopes.length > 0)
				{
					tref = m.cx.scopes[0];
				}
				else
				{
					// same as getscopeobject<0>
					v = values.get(e.scopes[0].args[0]);
					tref = types.get(e.scopes[0].args[0]);
				}
				break;
				
			case OP_getscopeobject:
				v = values.get(e.scopes[0].args[0]);
				tref = types.get(e.scopes[0].args[0]);
				if ( tref == null )
				{
					//  FIXME: Should be more thorough.
					tref = ANY().ref;
				}
				break;
				
			case OP_newclass:
				tref = e.c.ref.nonnull();
				break;
				
			case OP_newfunction:
				tref = FUNCTION().ref.nonnull();
				break;
				
			case OP_finddef:
				if (TypeCache.instance().globals.contains(e.ref))
					tref = TypeCache.instance().globals.get(e.ref);
				break;
				
			case OP_findpropstrict:
			case OP_findproperty:
			{
				int i = findInner(e.ref, e.scopes, types);
				if (i >= 0)
				{
					v = values.get(e.scopes[i]);
					tref = types.get(e.scopes[i]);
				}
				else if ((i = findOuter(e.ref, m.cx.scopes)) >= 0)
				{
					tref = m.cx.scopes[i];
				}
				else if (TypeCache.instance().globals.contains(e.ref))
				{
					tref = TypeCache.instance().globals.get(e.ref);
				}
				else
				{
					// not found.  use global.
					if (m.cx.scopes.length > 0)
					{
						tref = m.cx.scopes[0];
					}
					else
					{
						v = values.get(e.scopes[0]);
						tref = types.get(e.scopes[0]);
					}
				}
				break;
			}
			
			case OP_getlex:
			{
				// findproperty + getproperty
				int i = findInner(e.ref, e.scopes, types);
				Typeref stref = i >= 0 ? types.get(e.scopes[i]) : 
					(i=findOuter(e.ref, m.cx.scopes)) >= 0 ? m.cx.scopes[i] :
						TypeCache.instance().globals.contains(e.ref) ? TypeCache.instance().globals.get(e.ref) :
							m.cx.scopes.length > 0 ? m.cx.scopes[0] :
								types.get(e.scopes[0]);
	
				Binding b = stref.t.findGet(e.ref);
				// code below is a copy of OP_getproperty
				if (isSlot(b))
				{
					// TODO we only compute const value here if primitive type.
					// it would be more correct if we knew whether the initializer
					// changed the const value.  (consts can be computed in init).
					tref = b.type;
					if (isConst(b) && b.defaultValueChanged())
						v = b.value;
				}
				else if (isMethod(b))
				{
					// TODO if base type is or might be XML, return ANY
					// TODO use MethodClosure, more specific than Function
					tref = FUNCTION().ref.nonnull();
				}
				else if (isGetter(b))
				{
					tref = b.method.returns;
				}
				break;
			}
			
			case OP_construct:
			{
				tref = OBJECT().ref.nonnull();
				break;
			}
			
			case OP_constructprop:
			{
				Type ot = type(types,e.args[0]); // type of base object
				Binding b = ot.findGet(e.ref);
				if (b != null && b.type != null && b.type.t.itype != null)
				{
					tref = b.type.t.itype.ref.nonnull();
					break;
				}
				break;
			}
			
			case OP_callproperty:
			case OP_callproplex:
			{
				Type ot = type(types, e.args[0]);
				Binding b = ot.findGet(e.ref);
				if (isMethod(b))
				{
					tref = b.method.returns;
				}
				else if (isSlot(b) && b.type != null)
				{
					// each of these has same logic as convert_i, convert_s, etc
					if (b.type.t.itype == INT()) 
					{
						tref = INT().ref;
						if ( e.args.length > 1)
							v = eval_convert_i(values.get(e.args[1]));
					}
					else if (b.type.t.itype == UINT()) 
					{
						tref = UINT().ref;
						if ( e.args.length > 1)
							v = eval_convert_u(values.get(e.args[1]));
					}
					else if (b.type.t.itype == STRING())
					{
						tref = STRING().ref.nonnull();
						if ( e.args.length > 1)
							v = eval_convert_s(values.get(e.args[1]));
					}
					else if (b.type.t.itype == BOOLEAN())
					{
						tref = BOOLEAN().ref;
						if ( e.args.length > 1)
							v = eval_convert_b(values.get(e.args[1]));
					}
					else if (b.type.t.itype == NUMBER())
					{
						tref = NUMBER().ref;
						if ( e.args.length > 1)
							v = eval_convert_d(values.get(e.args[1]));
					}
				}
				break;
			}
							
			case OP_applytype:
				tref = types.get(e.args[0]).nonnull();
				break;
			
			case OP_callstatic:
				tref = e.m.returns;
				break;
			
			case OP_arg:
				if (e.imm[0] < m.getParams().length)
					tref = m.getParams()[e.imm[0]];
				else if (m.needsArguments()||m.needsRest() && e.imm[0] == m.getParams().length)
					tref = ARRAY().ref.nonnull();
				else
					tref = VOID().ref;
				break;
				
			case OP_xarg:
				tref = m.handlers[e.imm[0]].type;
				break;
				
			case OP_getslot:
			{
				Type t0 = type(types, e.args[0]);
				Binding b = t0.findSlot(e.imm[0]);
				if (b != null)
					tref = b.type;
				break;
			}
			
			case OP_getproperty:
			{
				Type t0 = type(types, e.args[0]);
				Binding b = t0.findGet(e.ref);
				if (isSlot(b))
				{
					// TODO we only compute const value here if primitive type.
					// it would be more correct if we knew whether the initializer
					// changed the const value.  (consts can be computed in init).
					tref = b.type;
					if (isConst(b) && b.defaultValueChanged())
						v = b.value;
				}
				else if (isMethod(b))
				{
					// TODO if base type is or might be XML, return ANY
					// TODO use MethodClosure, more specific than Function
					tref = FUNCTION().ref.nonnull();
				}
				else if (isGetter(b))
				{
					tref = b.method.returns;
				}
				break;
			}
			
			case OP_pushundefined:
				v = e.value;
				tref = VOID().ref;
				break;
				
			case OP_pushnull:
				v = e.value;
				tref = NULL().ref;
				break;
				
			case OP_pushtrue:
			case OP_pushfalse:
				v = e.value;
				tref = BOOLEAN().ref;
				break;
				
			case OP_pushbyte:
			case OP_pushshort:
			case OP_pushint:
				v = e.value;
				tref = INT().ref;
				break;
				
			case OP_pushuint:
				v = e.value;
				tref = UINT().ref;
				break;
				
			case OP_pushstring:
				v = e.value;
				tref = STRING().ref.nonnull();
				break;
				
			case OP_pushnan:
			case OP_pushdouble:
				v = e.value;
				tref = NUMBER().ref;
				break;
				
			case OP_pushnamespace:
				v = e.value;
				tref = NAMESPACE().ref.nonnull();
				break;
				
			case OP_jump:
				flowWork.add(e.succ[0]);
				return;
	
			case OP_lookupswitch:
			{
				Object v1 = values.get(e.args[0]);
				if (v1 == BOTTOM)
					for (Edge s: e.succ)
						flowWork.add(s);
				else
				{
					// input is const
					int i = intValue(v1);
					if (i < 0 || i >= e.succ.length-1) 
						i = e.succ.length-1;
					flowWork.add(e.succ[i]);
				}
				return;
			}
			
			case OP_iffalse:
			case OP_iftrue:
			{
				Object v1 = values.get(e.args[0]);
				if (v1 == BOTTOM)
				{
					flowWork.add(e.succ[0]);
					flowWork.add(e.succ[1]);
				}
				else if (e.op == OP_iffalse)
					flowWork.add(e.succ[booleanValue(v1) ? 0 : 1]);
				else if (e.op == OP_iftrue)
					flowWork.add(e.succ[booleanValue(v1) ? 1 : 0]);
				return;
			}
			
			case OP_pushscope:
			case OP_pushwith:
				// treat this as a copy.
				v = values.get(e.args[0]);
				tref = types.get(e.args[0]).nonnull();
				break;
				
			case OP_convert_b:
				tref = BOOLEAN().ref;
				v = eval_convert_b(values.get(e.args[0]));
				break;
				
			case OP_not:
			{
				tref = BOOLEAN().ref;
				Object v0 = values.get(e.args[0]);
				if (v0 != BOTTOM)
					v = booleanValue(v0) ? FALSE : TRUE;
				break;
			}
				
			case OP_deleteproperty:
				// TODO result is const false for any declared property
			case OP_deldescendants:
			case OP_hasnext:
			case OP_hasnext2:
			case OP_equals:
			case OP_strictequals:
			case OP_in:
			case OP_istype:
			case OP_istypelate:
			case OP_instanceof:
				tref = BOOLEAN().ref;
				break;
				
			case OP_lessthan:
			case OP_lessequals:
			case OP_greaterthan:
			case OP_greaterequals:
			{
				tref = BOOLEAN().ref;
				Object v0 = values.get(e.args[0]);
				Object v1 = values.get(e.args[1]);
				if (v0.equals(NAN) || v0 == UNDEFINED || v1.equals(NAN) || v1 == UNDEFINED)
					v = FALSE;
				else if (v0 != BOTTOM && v1 != BOTTOM)
					v = e.op == OP_lessthan ?     lessthan(v0,v1) :
						e.op == OP_lessequals ?  !lessthan(v1,v0) :
					    e.op == OP_greaterthan ?  lessthan(v1,v0) :
					    	                     !lessthan(v0,v1);
				break;
			}
			
			case OP_convert_s:
				tref = STRING().ref.nonnull();
				v = eval_convert_s(values.get(e.args[0]));
				break;
			
			case OP_coerce_s:
			{
				tref = eval_coerce_s(types.get(e.args[0]));
				v = eval_coerce_s(values.get(e.args[0]));
				break;
			}

			case OP_coerce_o:
			{
				Typeref t0 = types.get(e.args[0]);
				tref = eval_coerce_o(t0);
				v = eval_coerce_o(values.get(e.args[0]), t0.t);
				break;
			}

			case OP_coerce_a:
			{
				//  This cast has meaning if it's casting from void.
				//  Otherwise, it's an upcast and can be removed;
				//  casts will be re-inserted as appropriate.
				if ( ! (types.get(e.args[0]).equals(VOID().ref) ) )
				{
					v = values.get(e.args[0]);
					tref = types.get(e.args[0]);
				}
				else
				{
					tref = ANY().ref;
				}
				break;
			}
			
			case OP_coerce:
			{
				Typeref t0 = types.get(e.args[0]);
				Object v0 = values.get(e.args[0]);
				Type t = TypeCache.instance().namedTypes.get(e.ref);
				assert ( t != null );
				
				if (t == STRING())
				{
					tref = eval_coerce_s(t0);
					v = eval_coerce_s(v0);
				}
				else if (t == OBJECT())
				{
					tref = eval_coerce_o(t0);
					v = eval_coerce_o(v0,t0.t);
				}
				else if (t == INT())
				{
					tref = t.ref;
					v = eval_convert_i(v0);
				}
				else if (t == UINT()) 
				{
					tref = t.ref;
					v = eval_convert_u(v0);
				}
				else if (t == NUMBER()) 
				{
					tref = t.ref;
					v = eval_convert_d(v0);
				}
				else if (t == BOOLEAN()) 
				{
					tref = t.ref;
					v = eval_convert_b(v0);
				}
				else
				{
					// pointer style cast
					if (t0.t.extendsOrIsBase(t))
					{
						// ignore upcasts
						tref = t0;
						v = v0;
					}
					else if (t0.t == NULL() || t0.t == VOID())
					{
						tref = NULL().ref;
					}
					else
					{
						tref = t.ref;
					}
				}
				break;
			}
			
			case OP_astype:
				// TODO constant folding
				tref = TypeCache.instance().namedTypes.get(e.ref).ref;
				break;
			
			case OP_astypelate:
			{
				Typeref t1 = types.get(e.args[1]);
				if (t1.t.itype != null)
				{
					if (t1.t.itype.atom || t1.t.itype.numeric)
						tref = OBJECT().ref;
					else
						tref = t1.t.itype.ref;
				}
				else
				{
					tref = ANY().ref;
				}
				break;
			}
			
			case OP_typeof:
			{
				Type t0 = type(types,e.args[0]);
				if (t0 == INT() || t0 == UINT() || t0 == NUMBER())
					v = "number";
				else if (t0 == STRING())
					v = "string";
				else if (t0.extendsOrIsBase(XML()) || t0.extendsOrIsBase(XMLLIST()))
					v = "xml";
				else if (t0 == VOID())
					v = "undefined";
				else if (t0 == BOOLEAN())
					v = "boolean";
				else if (t0.extendsOrIsBase(FUNCTION()))
					v = "function";
				else if (t0 != OBJECT() && t0.extendsOrIsBase(OBJECT()))
					v = "object";
				tref = STRING().ref.nonnull();
				break;
			}
			
			case OP_add:
			{
				Expr a0 = e.args[0];
				Expr a1 = e.args[1];
				Typeref t0 = types.get(a0);
				Typeref t1 = types.get(a1);
				Object v0 = values.get(a0);
				Object v1 = values.get(a1);
				if (t0.t == STRING() && !t0.nullable || t1.t == STRING() && !t1.nullable)
				{
					tref = STRING().ref.nonnull();
					if (v0 != BOTTOM && v1 != BOTTOM)
						v = stringValue(v0) + stringValue(v1);
				}
				else if (t0.t.numeric && t1.t.numeric)
				{
					tref = NUMBER().ref;
					if (v0 instanceof Number && v1 instanceof Number)
						v = doubleValue(v0) + doubleValue(v1);
				}
				else
				{
					// TODO make all primitives extend a type so we can use that type here.
					tref = OBJECT().ref.nonnull(); // will be a String or a Number
				}
				break;
			}
			
			case OP_divide:
			{
				tref = NUMBER().ref;
				Object v0 = values.get(e.args[0]);
				Object v1 = values.get(e.args[1]);
				if (v0 instanceof Number && v1 instanceof Number)
					v = doubleValue(v0) / doubleValue(v1);
				break;
			}
			
			case OP_subtract:
			case OP_multiply:
			case OP_modulo:
			case OP_negate:
			case OP_increment:
			case OP_decrement:
				tref = NUMBER().ref;
				break;

			case OP_convert_d:
				tref = NUMBER().ref;
				v = eval_convert_d(values.get(e.args[0]));
				break;
				
			case OP_convert_i:
				tref = INT().ref;
				v = eval_convert_i(values.get(e.args[0]));
				break;

			case OP_convert_u:
				tref = UINT().ref;
				v = eval_convert_u(values.get(e.args[0]));
				break;
	
			case OP_bitor:
			{
				tref = INT().ref;
				Object v0 = values.get(e.args[0]);
				Object v1 = values.get(e.args[1]);
				if (v0 instanceof Number && v1 instanceof Number)
					v = intValue(v0) | intValue(v1);
				break;
			}
			
			case OP_bitand:
			{
				tref = INT().ref;
				Object v0 = values.get(e.args[0]);
				Object v1 = values.get(e.args[1]);
				if (v0 instanceof Number && v1 instanceof Number)
				{
					v = intValue(v0) & intValue(v1);
				}
				break;
			}
				
			case OP_bitnot:
			case OP_add_i:
			case OP_subtract_i:
			case OP_multiply_i:
			case OP_negate_i:
			case OP_bitxor:
			case OP_lshift:
			case OP_rshift:
			case OP_hasnext2_i:
			case OP_increment_i:
			case OP_decrement_i:
				// TODO constant folding
				tref = INT().ref;
				break;
				
			case OP_urshift:
				// TODO constant folding
				tref = UINT().ref;
				break;
				
			// these ops do not produce any value
			case OP_setslot:
			case OP_setproperty:
			case OP_setsuper:
			//case OP_setglobalslot: // deprecated
			case OP_initproperty:
			case OP_callpropvoid:
			case OP_constructsuper:
			case OP_callsupervoid:
			case OP_returnvoid:
			case OP_returnvalue:
			case OP_throw:
			case OP_popscope:
			case OP_debug:
			case OP_debugline:
			case OP_debugfile:
			case OP_bkpt:
			case OP_bkptline:
			case OP_checkfilter:
				return;
			}
		}
		
		assert(tref != null && tref.t != null);
		
		// singleton types have a specific value.
		if (tref.t == VOID())
			v = UNDEFINED;
		else if (tref.t == NULL())
			v = NULL();
		
		if (v != null && !v.equals(values.get(e)))
		{
			values.put(e, v);
			ssaWork.addAll(uses.get(e));
		}
		
		if (!tref.equals(types.get(e)))
		{
			types.put(e, tref);
			ssaWork.addAll(uses.get(e));
		}
	}
	
	Typeref verify_eval(Method m, Expr e,
			Map<Expr,Typeref> types, Map<Block,Block> idom)
	{
		Typeref tref = null;
				
		if (e.op == OP_phi)
		{
			boolean loop = false;
			for (int i=e.args.length-1; i >= 0; i--)
			{
				Expr a = e.args[i];
				loop |= isLoop(e.pred[i],idom);
				// compute the phi() meet operation.  ignore any inputs we
				// haven't evaluated yet.  If all inputs have the same value,
				// phi() has that value.  Otherwise return BOTTOM.
				
				// same idea for types, but if they aren't all the same
				// then compute the most derived base class (mdb) of the types.
				Typeref aref = types.get(a);
				if (aref == null)
					continue; // ignore unprocessed inputs
				if (tref == null)
					tref = aref;
				else if (!tref.equals(aref))
					tref = mdb(tref,aref);
			}
			
			if ( null == tref )
			{
				tref = ANY().ref;
			}
			// make nullable types nullable at top of loop so verifier
			// won't ever need to iterate.
			if (loop)
				tref = tref.t.ref;
		}
		else
		{
			tref = ANY().ref;
			
			// if any arg is TOP result is TOP (unchanged)
			for (Expr a : e.args) if (!types.containsKey(a))	return tref;
			for (Expr a : e.scopes) if (!types.containsKey(a))	return tref;
			for (Expr a : e.locals) if (!types.containsKey(a))	return tref;
			
			switch (e.op)
			{
			default:
				assert(false);
			
			case OP_hasnext2_o:
			case OP_nextname:
			case OP_nextvalue:
			case OP_call:
			case OP_getsuper:
			case OP_getdescendants:
				tref = ANY().ref;
				break;
				
			case OP_convert_o:
				// bug in verifier -- doesn't set state nonnull here.
				tref = types.get(e.args[0]);
				//tref = types.get(e.args[0]).nonnull();
				break;
			
			case OP_esc_xattr:
			case OP_esc_xelem:
				tref = STRING().ref.nonnull();
				break;
				
			case OP_newcatch:
				tref = m.handlers[e.imm[0]].activation;
				break;
				
			case OP_newobject:
				tref = OBJECT().ref.nonnull();
				break;
			
			case OP_newarray:
				tref = ARRAY().ref.nonnull();
				break;
				
			case OP_newactivation:
				tref = m.activation;
				break;
				
			case OP_getglobalscope:
				if (m.cx.scopes.length > 0)
				{
					tref = m.cx.scopes[0];
				}
				else
				{
					// same as getscopeobject<0>
					tref = types.get(e.scopes[0].args[0]);
				}
				break;
				
			case OP_getscopeobject:
				tref = types.get(e.scopes[0].args[0]);
				break;
				
			case OP_newclass:
				tref = e.c.ref.nonnull();
				break;
				
			case OP_newfunction:
				tref = FUNCTION().ref.nonnull();
				break;
				
			case OP_finddef:
				if (TypeCache.instance().globals.contains(e.ref))
					tref = TypeCache.instance().globals.get(e.ref);
				break;
				
			case OP_findpropstrict:
			case OP_findproperty:
			{
				int i = findInner(e.ref, e.scopes, types);
				if (i >= 0)
				{
					tref = types.get(e.scopes[i]);
				}
				else if ((i = findOuter(e.ref, m.cx.scopes)) >= 0)
				{
					tref = m.cx.scopes[i];
				}
				else if (TypeCache.instance().globals.contains(e.ref))
				{
					tref = TypeCache.instance().globals.get(e.ref);
				}
				else
				{
					// not found.  use global.
					if (m.cx.scopes.length > 0)
					{
						tref = m.cx.scopes[0];
					}
					else
					{
						tref = types.get(e.scopes[0]);
					}
				}
				break;
			}
			
			case OP_getlex:
			{
				// findproperty + getproperty
				int i = findInner(e.ref, e.scopes, types);
				Typeref stref = i >= 0 ? types.get(e.scopes[i]) : 
					(i=findOuter(e.ref, m.cx.scopes)) >= 0 ? m.cx.scopes[i] :
						TypeCache.instance().globals.contains(e.ref) ? TypeCache.instance().globals.get(e.ref) :
							m.cx.scopes.length > 0 ? m.cx.scopes[0] :
								types.get(e.scopes[0]);
	
				Binding b = stref.t.findGet(e.ref);
				tref = verify_eval_getproperty(tref, b);
				break;
			}
			
			case OP_construct:
			{
				Type base_type = type(types,e.args[0]);
				
				if ( base_type.itype != null )
					tref = base_type.itype.ref.nonnull();
				else
					tref = base_type.ref.nonnull();
				
				break;
			}
			
			case OP_constructprop:
			{
				Type ot = type(types,e.args[0]); // type of base object
				Binding b = ot.findGet(e.ref);
				if (b != null && b.type != null && b.type.t.itype != null)
				{
					tref = b.type.t.itype.ref.nonnull();
					break;
				}
				break;
			}
			
			case OP_callproperty:
			case OP_callproplex:
			{
				Type ot = type(types, e.args[0]);
				Binding b = ot.findGet(e.ref);
				if (isMethod(b))
				{
					tref = b.method.returns;
				}
				else if (isSlot(b) && b.type != null && b.type.t.itype != null)
				{
					// calling a class as a function, return type is cast to instance type
					// issue what about special cases? RegExp? Date?
					tref = b.type.t.itype.ref;
				}
				break;
			}
			
			case OP_callsuper:
			{
				Type ot = m.cx.base;
				Binding b = ot.findGet(e.ref);
				if (isMethod(b))
				{
					tref = b.method.returns;
				}
				break;
			}
			
			case OP_applytype:
				tref = types.get(e.args[0]).nonnull();
				break;
			
			case OP_callstatic:
				tref = e.m.returns;
				break;
			
			case OP_arg:
				if (e.imm[0] < m.getParams().length)
					tref = m.getParams()[e.imm[0]];
				else if (m.needsArguments()||m.needsRest() && e.imm[0] == m.getParams().length)
					tref = ARRAY().ref.nonnull();
				else
					tref = VOID().ref;
				break;
				
			case OP_xarg:
				tref = m.handlers[e.imm[0]].type;
				break;
				
			case OP_getslot:
			{
				Type t0 = type(types, e.args[0]);
				Binding b = t0.findSlot(e.imm[0]);
				if (b != null)
					tref = b.type;
				break;
			}
			
			case OP_getproperty:
			{
				Type t0 = type(types, e.args[0]);
				Binding b = t0.findGet(e.ref);
				tref = verify_eval_getproperty(tref, b);
				break;
			}
			
			case OP_kill:
				tref = ANY().ref;
				break;
				
			case OP_pushundefined:
				tref = VOID().ref;
				break;
				
			case OP_pushnull:
				tref = NULL().ref;
				break;

			case OP_pushnamespace:
				tref = NAMESPACE().ref.nonnull();
				break;
							
			case OP_pushscope:
			case OP_pushwith:
				// treat this as a copy.
				tref = types.get(e.args[0]).nonnull();
				break;
				
			case OP_pushtrue:
			case OP_pushfalse:
			case OP_convert_b:
			case OP_not:
			case OP_deleteproperty:
			case OP_deldescendants:
			case OP_hasnext:
			case OP_hasnext2:
			case OP_equals:
			case OP_strictequals:
			case OP_in:
			case OP_istype:
			case OP_istypelate:
			case OP_instanceof:
			case OP_lessthan:
			case OP_lessequals:
			case OP_greaterthan:
			case OP_greaterequals:
				tref = BOOLEAN().ref;
				break;
			
			case OP_convert_s:
			case OP_pushstring:
				tref = STRING().ref.nonnull();
				break;
			
			case OP_coerce_s:
			{
				Typeref t0 = types.get(e.args[0]);
				tref = new Typeref(STRING(), t0.nullable);
				break;
			}

			case OP_coerce_o:
			{
				Typeref t0 = types.get(e.args[0]);
				tref = new Typeref(OBJECT(), t0.nullable);
				break;
			}

			case OP_coerce_a:
			{
				Typeref t0 = types.get(e.args[0]);
				tref = new Typeref(ANY(), t0.nullable);
				break;
			}
			
			case OP_coerce:
				tref = TypeCache.instance().namedTypes.get(e.ref).ref;
				break;
			
			case OP_astype:
			{
				Typeref t0 = types.get(e.args[0]);
				Type t = TypeCache.instance().namedTypes.get(e.ref);
				if (!t0.t.extendsOrIsBase(t) || t0.t.isAtom() != t.isAtom())
				{
					// TODO figure out what verifier is really doing here.
					tref = t.ref;
				}
				else
				{
					tref = t0;
				}
				break;
			}
			
			case OP_astypelate:
			{
				Typeref t1 = types.get(e.args[1]);
				if (t1.t.itype != null)
				{
					if (t1.t.itype.atom || t1.t.itype.numeric)
						tref = OBJECT().ref;
					else
						tref = t1.t.itype.ref;
				}
				else
				{
					tref = ANY().ref;
				}
				break;
			}
				
			case OP_typeof:
				tref = STRING().ref.nonnull();
				break;
			
			case OP_add:
			{
				Expr a0 = e.args[0];
				Expr a1 = e.args[1];
				Typeref t0 = types.get(a0);
				Typeref t1 = types.get(a1);
				if (t0.t == STRING() && !t0.nullable || t1.t == STRING() && !t1.nullable)
				{
					tref = STRING().ref.nonnull();
				}
				else if (t0.t.numeric && t1.t.numeric)
				{
					tref = NUMBER().ref;
				}
				else
				{
					// TODO make all primitives extend a type so we can use that type here.
					tref = OBJECT().ref.nonnull(); // will be a String or a Number
				}
				break;
			}
			
			case OP_divide:
			case OP_subtract:
			case OP_multiply:
			case OP_modulo:
			case OP_negate:
			case OP_increment:
			case OP_decrement:
			case OP_convert_d:
			case OP_pushnan:
			case OP_pushdouble:
				tref = NUMBER().ref;
				break;

			case OP_convert_i:
			case OP_bitor:
			case OP_bitand:
			case OP_add_i:
			case OP_subtract_i:
			case OP_multiply_i:
			case OP_negate_i:
			case OP_bitxor:
			case OP_lshift:
			case OP_rshift:
			case OP_hasnext2_i:
			case OP_increment_i:
			case OP_decrement_i:
			case OP_pushbyte:
			case OP_pushshort:
			case OP_pushint:
			case OP_bitnot:
				tref = INT().ref;
				break;
				
			case OP_pushuint:
			case OP_convert_u:
			case OP_urshift:
				tref = UINT().ref;
				break;
			}
		}
		
		assert(tref != null && tref.t != null);
		return tref;
	}

	private Typeref verify_eval_getproperty(Typeref tref, Binding b)
	{
		if (isSlot(b))
		{
			tref = b.type;
		}
		else if (isMethod(b))
		{
			//tref = FUNCTION().ref.nonnull(); // TODO use MethodClosure
			// avmplus uses ANY here. see Verifier::readBinding().
			tref = ANY().ref;
		}
		else if (isGetter(b))
		{
			tref = b.method.returns;
		}
		return tref;
	}
	
	boolean isCritical(Edge e, SetMap<Block,Edge>pred)
	{
		return e.from.succ().length > 1 && pred.get(e.to).size() > 1;
	}
	
	/**
	 * 
	 * @param e - the edge to split.
	 * @post e points at the new block.
	 * @param m - the containing Method.
	 * @param pred - predecessors.  Not entirely relevant...
	 * @return the Edge from the new block to e's original "to."
	 */
	Edge split(Edge e, Method m, SetMap<Block,Edge>pred)
	{
		assert(e.handler == null); // can't split exception edges
		Expr j = new Expr(m, OP_jump);
		Block d = new Block(m);
		Block to = e.to;
		Edge e2 = new Edge(m,d,0,to);
		j.succ = new Edge[] { e2 };
		d.add(j);
		verboseStatus("SPLIT "+e + " ... " + d + ", " + e2);
		e.to = d;
		pred.get(d).add(e);
		pred.get(to).remove(e);
		pred.get(to).add(e2);
		replacePred(to,e,e2);
		return e2;
	}
	
	void replacePred(Block b, Edge before, Edge after)
	{
		for (Expr e: b)
		{
			if (e.op == OP_phi)
			{
				for (int i=0, n=e.pred.length; i < n; i++)
					if (e.pred[i] == before)
						e.pred[i] = after;
			}
		}
	}
	
	Expr append(Edge edge, Expr e)
	{
		edge.from.appendExpr(e);
		return e;
	}
	Expr prepend(Edge edge, Expr e)
	{
		Deque<Expr> exprs = edge.from.exprs;
		exprs.addFirst(e);
		return e;
	}
	
	Expr setlocal(Method m, int i, Expr a)
	{
		return new Expr(m, OP_setlocal, i, new Expr[] { a }, 1, 1);
	}
	
	Expr getlocal(Method m, int i)
	{
		return new Expr(m, OP_getlocal, i);
	}
	
	Expr dup(Method m, Expr e)
	{
		Expr dup = new Expr(m, OP_dup);
		dup.locals = new Expr[] { e };
		return dup;
	}
	
	/**
	 * the last phase before emitting code.
	 * - stack scheduling
	 * - scope scheduling
	 * - assign local variables
	 * - replace phi's with copies if necessary
	 * - recompute frame size
	 * @param code
	 */
	void remove_phi(Method m)
	{
		Deque<Block> code = dfs(m.entry.to);
		SetMap<Block,Edge> pred = preds(code);

		Map<Integer,Integer> locals = new TreeMap<Integer,Integer>();
		Map<Block,Deque<Expr>> exprs = new TreeMap<Block,Deque<Expr>>();
		ConflictGraph conflicts = new ConflictGraph();
		
		printMethod(m, "BEFORE SCHED");
		

		addTraceAttr(m);
		
		restused:
		if (m.needsArguments() || m.needsRest())
		{
			// if we have a rest param or arguments and we don't use it,
			// clear those flags and set the ignore-extra-args flag. 
			int rest = m.getParams().length;
			for (Expr e: m.entry.to)
				if (e.op == OP_arg && e.imm[0] == rest)
					break restused;
			m.flags &= ~(METHOD_Arguments|METHOD_Needrest);
			m.flags |= METHOD_IgnoreRest;
			verboseStatus("IGNORE_REST for "+m.getName());
		}

		int max_local = m.getParams().length-1;
		
		sched_greedy(m, code, locals, pred, exprs, conflicts);
		
		alloc_locals(code, locals, conflicts, m.fixedLocals);
		
		
		// insert phi copies on edges where needed
		Set<Edge> splits = new TreeSet<Edge>();
		for (Block b: code)
		{
			// identify the edges that need copies, split them, add copies.
			// only split an edge once during this whole pass.
			for (Expr e: b)
			{
				if (e.op != OP_phi)
					break;
				if (!locals.containsKey(e.id))
					continue;

				addTraceAttr(e);
				int lhs = locals.get(e.id);
				for (int i=e.args.length-1; i>=0; i--)
				{
					traceEntry("PhiInput");
					addTraceAttr("i", i);
					addTraceAttr(e.args[i]);
					int rhs = locals.get(e.args[i].id);
					if (lhs != rhs)
					{
						Edge p = e.pred[i];
						if (!splits.contains(p))
						{
							split(p,m,pred);
							splits.add(p = e.pred[i]);
						}
						traceEntry("copyPhiInput");
						addTraceAttr("lhs", lhs);
						addTraceAttr("rhs", rhs);
						Expr get = getlocal(m, rhs);
						prepend(p, get);
						append(p, setlocal(m,lhs,get));
					}
				}

			}
			
			// now swap in the scheduled code and renumber the get/setlocals we have in there.
			b.exprs = exprs.get(b);
			
			for ( Expr e: b.exprs)
			{
				// assign locals & update local_count
				int loc = max_local;
				if (e.op == OP_getlocal || e.op == OP_setlocal)
				{
					loc = e.imm[0] = locals.get(e.imm[0]);
				}
				else if (e.op == OP_hasnext2)
				{
					int loc0 = locals.get(e.locals[0].id);
					int loc1 = locals.get(e.locals[1].id);
					e.imm = new int[] { loc0, loc1 };
					loc = loc0 > loc1 ? loc0 : loc1;
				}
				if (loc > max_local)
					max_local = loc;
			}
		}
		
		m.local_count = max_local+1;
		
		// some of the edges we split didn't need to be.
		cfgopt(m);
		
		printMethod(m, "AFTER SCHED");
		

	}
	
	/**
	 *  Compute a Method's max_stack and max_scope settings.
	 *  @param m - the Method of interest.
	 *  @post m.max_stack and m_max_scope set.
	 *  @note Factored out of remove_phi so that the verifier
	 *    appeasment logic can safely issue getlocal insns.
	 */
	void computeFrameCounts(Method m)
	{
		Deque<Block> code = dfs(m.entry.to);
		
		
		int max_stack = 0;
		int max_scope = 0;
		
		Map<Block,Integer>stkin = new TreeMap<Block,Integer>();
		Map<Block,Integer>scpin = new TreeMap<Block,Integer>();
		stkin.put(m.entry.to, 0);
		scpin.put(m.entry.to, 0);
		
		for ( Block b: code )
		{
			int stkdepth = stkin.get(b);
			int scpdepth = scpin.get(b);

			for (Expr e: b)
			{
				assert(!e.isSynthetic());
				
				// compute max_stack
				assert(stkdepth >= e.args.length);
				stkdepth -= e.args.length;
				if (e.onStack())
				{
					stkdepth++;
				}
				if (stkdepth > max_stack)
					max_stack = stkdepth;
				
				// compute max_scope
				assert(scpdepth >= e.scopes.length);
				if (e.op == OP_popscope)
					scpdepth--;
				else if (e.onScope())
					scpdepth++;
				if (scpdepth > max_scope)
					max_scope = scpdepth;
			}
			for (Edge s: b.succ())
				update_depth(s.to, stkdepth, stkin, scpdepth, scpin);
			for (Edge s: b.xsucc)
				update_depth(s.to, 1, stkin, 0, scpin);
		}
		
		m.max_stack = max_stack;
		m.max_scope = max_scope;
	}
	
	/**
	 *  Work around legacy verifier restrictions:
	 *  Kill predecessor blocks' locals if they're live out
	 *  on more than one path and not live in to a block.
	 *  @param m - the Method under analysis.
	 */
	void appeaseLegacyVerifier(Method m)
	{

		addTraceAttr(m);
		
		Deque<Block> code = schedule(m.entry.to);
		SetMap<Block, Edge> pred = preds(code);
		Set<Edge> single_path_to_exit = new HashSet<Edge>();
	
		Map<Block,LocalVarState> reg_state_by_block = getLocalVarState(m);
		
		TypeConstraintMap constraints = new TypeConstraintMap();
		
		//  Create type constraints:
		//  Find edges where locals' types
		//  conflict with the expected type, which
		//  may be the consensus type for the local
		//  in the block or may be specific to the
		//  block.  Apply coercions as necessary.
		for ( Block b: code)
		{
			verboseStatus("Building constraints for " + b);

			LocalVarState block_state = reg_state_by_block.get(b);			
			assert (block_state != null);
			
			BitSet active  = block_state.getActiveVariables();
			
			//  Kill active variables that aren't in a successor
			//  block's live-in set.
			for ( Edge s:b.succ())
			{	
				if ( singlePathToExit(s, pred, single_path_to_exit))
				{
					//  No possibliity of conflict.
					continue;
				}
				
				Block successor = s.to;
				
				LocalVarState to_state = reg_state_by_block.get(successor);
				assert ( to_state != null);
				
				TypeConstraints tc = constraints.getConstraints(s);
				BitSet to_livein  = to_state.getLivein();
				
				for ( Integer r : foreach(active) )
				{
					if ( !( to_livein.get(r) || m.fixedLocals.values().contains(r) ) )
					{	
						//  If the target block redefines this variable,
						//  and all incoming types agree, then the kill
						//  is redundant.
						if ( to_state.def.get(r) || to_state.killed_vars.get(r) )
						{
							Typeref first_incoming_type = to_state.getInitialType(r);
							
							for ( Edge p: pred.get(successor) )
							{	
								boolean needs_kill;
								
								//  TODO: It should be possible to extend this 
								//  "zone of protection" to more than one
								//  predecessor block, but the verifier rejects it.
								needs_kill = pred.get(successor).size() > 1;
								
								/*
								Typeref pred_incoming_type = reg_state_by_block.get(p.from).getFinalType(r);
								
								if ( successor.is_backwards_branch_target )
									needs_kill = !first_incoming_type.equals(pred_incoming_type);
								else
									needs_kill = !first_incoming_type.t.isMachineCompatible(pred_incoming_type.t);
							
								//  TODO: Need better analysis of when ANY means ANY and when it means "low."
								needs_kill |= pred_incoming_type.t.equals(ANY);
								*/

								if ( needs_kill )
								{
									//  TODO: These can be largely eliminated
									//  when the verifier gets smarter.
									tc.addKill(r);
									break;
								}

							}
						}
						else
						{
							tc.addKill(r);
						}
					}
				}
			}
			
			//  Analyze the types of live-in variables; form an
			//  objective input type, then coerce as necessary
			//  to get to that type.
			BitSet livein  = block_state.getLivein();
			
			for ( Integer r : foreach(livein) )
			{
				Typeref consensus_type = block_state.getInitialType(r);
				assert(consensus_type != null);
				
				for ( Edge p: pred.get(b))
				{
					LocalVarState from_state = reg_state_by_block.get(p.from);
					assert( from_state != null);
					
					consensus_type = typeMeet(consensus_type, from_state.getFinalType(r));
				}
				
				for ( Edge p: pred.get(b))
				{
					LocalVarState from_state = reg_state_by_block.get(p.from);
					assert( from_state != null);
					
					TypeConstraints tc = constraints.getConstraints(p);
					
					if ( block_state.hard_coercions[r] != null )
					{
						tc.addCoercion(r, block_state.hard_coercions[r]);
					}
					else if ( needsCoercion(m, consensus_type, from_state.getFinalType(r), b.is_backwards_branch_target ))
					{
						tc.addCoercion(r, consensus_type);
					}
				}
			}
		}
		
		//  Find kills and coercions that can be done in the 
		//  in the source block instead of the target blocks.
		//  TODO: Reach back through exblocks?
		for ( Block b: code )
		{	
			LocalVarState block_state = reg_state_by_block.get(b);			
			assert (block_state != null);
			
			BitSet active  = block_state.getActiveVariables();
			
			TypeConstraints source_block_constraints = null;
			
			for ( Integer r: foreach(active))
			{
				TypeConstraints first_constraint = null;
				boolean all_constraints_agree = true;
				
				for ( Edge s:b.succ() )
				{
					TypeConstraints tc = constraints.getConstraints(s); 
					if ( null == first_constraint )
					{
						first_constraint = tc;
					}

					//  If the active register isn't in the constraint set,
					//  then this will be false, and thus it's necessary to
					//  ask the first constraint if it agrees with itself.
					all_constraints_agree = first_constraint.agreesWith(tc, r);
					if ( !all_constraints_agree )
						break;
				}
				
				if ( all_constraints_agree )
				{
					if ( null == source_block_constraints )
						source_block_constraints = new TypeConstraints(null);
					
					for ( Edge s: b.succ())
					{
						source_block_constraints.takeConstraintFrom(constraints.get(s), r);
					}
				}
			}
			
			if ( source_block_constraints != null )
				fixConstraints(m, b, source_block_constraints, block_state);
		}
		
		//  Fix any remaining constraints by
		//  splitting the affected edge and applying
		//  constraints to the new block.
		//  TODO: These blocks should be amenable to pooling.
		for ( Block b: code )
		{	
			for ( Edge p:b.succ() )
			{
				//  Split the liveout block, and apply
				//  the constraints to the split block.
				TypeConstraints tc = constraints.getConstraints(p); 
	
				if ( tc != null && tc.killregs.size() > 0 || tc.coercions.size() > 0 )
				{
						split(p, m, pred);
						p.to.must_isolate_block = true;
						fixConstraints(m, p.to, tc, null);
				}
			}
		}
		

	}

	boolean singlePathToExit(Edge s, SetMap<Block, Edge> pred, Set<Edge> known_single_paths)
	{
		Block b = s.to;

		if ( pred.get(b).size() > 1 )
			return false;
		else if ( known_single_paths.contains(s) )
			return true;
		
		boolean single_path = false;	//  not a control value, compiler appeasement
		
		if ( b.succ() == noedges  )
			single_path =  true;
		else 
		{
			for ( Edge s_prime: b.succ() )
			{
				single_path = singlePathToExit(s_prime, pred, known_single_paths);
				if ( !single_path )
					break;
			}
		}
		
		if ( single_path )
		{
			known_single_paths.add(s);
		}
		return single_path;
	}

	boolean needsCoercion(Method m, Typeref to_ty, Typeref from_ty, boolean backwards_branch)
	{
		if ( to_ty.equals(from_ty) || ignoreTypeConflict(m, to_ty, from_ty) )
			return false;
		
		if ( isNumericType(from_ty) && isNumericType(to_ty))
			return false;
		
		boolean needs_coercion;
		
		Typeref merged_type = typeMerge(to_ty, from_ty);
		
		if ( null == merged_type )
		{
			//  No sensible meet of these types,
			//  coercion necessary.
			needs_coercion = true;
		}
		else if ( backwards_branch )
		{
			//  FIXME:  The type modeling in LocalVarState
			//  needs to account for cross-block nullable changes.
			needs_coercion = true;
			//needs_coercion = ! from_ty.equals(to_ty);
		}
		else
		{
			needs_coercion = !to_ty.t.isMachineCompatible(merged_type.t);
		}
		
		return needs_coercion;
		
	}

	private boolean isNumericType(Typeref ty)
	{
		return ty.t.numeric;
	}

	/**
	 * Ignore type conflicts that are probably due to other bugs.
	 * @param m 
	 * @param liveinType - the suspect type.
	 * @param from_ty 
	 * @return true if the type appears to be bogus.
	 * @warn this routine is bogus.
	 */
	boolean ignoreTypeConflict(Method m, Typeref to_ty, Typeref from_ty)
	{
		boolean result = to_ty.t.getName().name.startsWith("global") && from_ty.t.getName().name.startsWith("global");
		result |= from_ty.t.equals(m.activation.t) && to_ty.t.equals(m.activation.t);
		return result;
	}
	

	
	
	/**
	 *  Fix type constraints for a block.
	 *  @param m - the Method that contains the Block.
	 *  @param b - the Block to be fixed.
	 *  @param bc - the Block's constraints.
	 * @param block_state 
	 */
	void fixConstraints(Method m, Block b, TypeConstraints bc, LocalVarState block_state)
	{
		verboseStatus("fixConstraints " + b );
		
		//  A fair number of expressions can be coerced
		//  when they're defined.
		Map<Expr,Expr> coerce_in_place = new HashMap<Expr,Expr>();
		
		if ( block_state != null )
		{
			Set<Integer> coerced_locals = new HashSet<Integer>(bc.coercions.keySet());
			
			for ( Integer r: coerced_locals )
			{
				if ( ! block_state.read_after_def.get(r))
				{
					Expr generator = block_state.generating_exprs.get(r);
					
					if ( generator != null )
					{
						coerce_in_place.put(generator, coerceExpr(m, bc.coercions.get(r).t, generator));
						bc.coercions.remove(r);
					}
				}
			}
			
			if ( !coerce_in_place.isEmpty() )
			{
				Deque<Expr> replaced_exprs = new ArrayDeque<Expr>();
				
				while ( !b.exprs.isEmpty())
				{
					Expr ex = b.exprs.removeFirst();

					if ( coerce_in_place.containsKey(ex))
					{
						replaced_exprs.add(coerce_in_place.get(ex));
						coerce_in_place.remove(ex);
					}
					
					replaced_exprs.add(ex);
				}
			
				assert(coerce_in_place.isEmpty());
				b.exprs = replaced_exprs;
			}
		}

		Expr last = b.succ().length > 0? b.exprs.removeLast(): null;
		
		for ( Integer regnum: bc.coercions.keySet() )
		{
			Typeref ty = bc.coercions.get(regnum);
			
			if ( ty.equals(VOID().ref) )
			{
				Expr void_expr = new Expr(m, OP_pushundefined);
				b.exprs.add(void_expr);
				b.exprs.add(setlocal(m, regnum, void_expr));
			}
			if ( ty.equals(NULL().ref) )
			{
				Expr void_expr = new Expr(m, OP_pushnull);
				b.exprs.add(void_expr);
				b.exprs.add(setlocal(m, regnum, void_expr));
			}
			else
			{
				Expr getlocal = getlocal(m, regnum);
				b.exprs.add(getlocal);
				
				Expr coerce_expr = coerceExpr(m, ty.t, getlocal);
				b.exprs.add(coerce_expr);
				b.exprs.add(setlocal(m, regnum, coerce_expr));
			}
			verboseStatus("\tlocal " + regnum);

		}
		
		for ( Integer k: bc.killregs )
		{
			b.exprs.add(new Expr(m, OP_kill, k.intValue()));
			verboseStatus("kill " + k);
		}
		
		if ( last != null )
			b.exprs.add(last);
	}
	
	Expr coerceExpr(Method m, Type t, Expr a)
	{
		Expr result = null;
		
		assert(t != null);
		
		if ( ANY().equals(t))
			result = new Expr(m, OP_coerce_a, a);
		else if (VOID().equals(t) )
			result = new Expr(m, OP_pushundefined);
		else if ( NULL().equals(t) )
			result = new Expr(m, OP_pushnull);
		else if ( INT().equals(t))
			result = new Expr(m, OP_convert_i, a);
		else if ( OBJECT().equals(t))
			result = new Expr(m, OP_coerce_o, a);
		else if ( STRING().equals(t))
			result = new Expr(m, OP_coerce_s, a);
		else
		{
			result = new Expr(m, OP_coerce, t.getName(), a);
		}
		
		verboseStatus("coerceExpr " + formatExpr(result));
		
		return result;
	}

	void alloc_locals(Deque<Block> code, Map<Integer, Integer> locals, ConflictGraph conflicts, Map<Expr, Integer> fixed_locals)
	{
		for (Block b: code)
		{
			for (Expr e: b)
			{
				if (locals.containsKey(e.id))
				{
					alloc1(e,conflicts,locals);
					
					if ( fixed_locals.containsKey(e) && locals.get(e.id) != -1)
						fixed_locals.put(e, locals.get(e.id));
				}
			}
		}

		for (Block b: code)
		{
			for (Expr e: b)
			{
				if (locals.containsKey(e.id))
				{
					alloc2(e,conflicts,locals);
					
					if ( fixed_locals.containsKey(e) && locals.get(e.id) != -1)
						fixed_locals.put(e, locals.get(e.id));
				}
			}
		}

		verboseStatus("CONFLICTS " + conflicts);
		verboseStatus("LOCALS "+locals);
	}
	
	void update_depth(Block b, int stkdepth, Map<Block,Integer> stkin, int scpdepth, Map<Block,Integer> scpin)
	{
		if (stkin.containsKey(b))
			assert(stkin.get(b) == stkdepth);
		else
			stkin.put(b,stkdepth);

		if (scpin.containsKey(b))
			{}//			assert(scpin.get(b) == scpdepth);
		else
			scpin.put(b,scpdepth);
	}
	
	void allocate(int id, int loc, Map<Integer,Integer>locals, ConflictGraph conflicts)
	{
		traceEntry("allocate");
		addTraceAttr("id", id);
		addTraceAttr("loc", loc);
		assert(locals.get(id) == -1 && loc != -1);
		locals.put(id, loc);
		
		// sanity check
		for (int j: conflicts.get(id))
			assert(locals.get(j) != loc);
	}
	
	void alloc1(Expr e, ConflictGraph conflicts, Map<Integer,Integer> locals)
	{
		if (locals.get(e.id) != -1)
			return;

		BitSet used = new BitSet();
		for (int i: conflicts.get(e.id))
			if (locals.get(i) != -1)
				used.set(locals.get(i));
		
		int loc = -1;
		//  If the expression's locked to a specific local (e.g., it's an arg), it must use that local.
		if (e.locals.length == 1 && e.inLocal() && locals.containsKey(e.locals[0].id) && (loc=locals.get(e.locals[0].id)) != -1)
		{
			assert(!used.get(loc));
			allocate(e.id, loc, locals, conflicts);
		}
		
		if (e.op != OP_phi)
			return;
		
		//  If any phi input is already allocated, and the local's available, use that slot. 
		for (Expr a: e.args)
		{
			if (locals.containsKey(a.id) && (loc=locals.get(a.id)) != -1 && !used.get(loc))
			{
				allocate(e.id, loc, locals, conflicts);
				break;
			}
		}

		if (loc == -1)
		{
			//  No previous allocation found; allocate lowest-numbered free local.
			loc = 0;
			while (used.get(loc))
				loc++;
			allocate(e.id, loc, locals, conflicts);
		}
		
		// try to assign all inputs to the same local to avoid copies
		nextarg:
		for (Expr a: e.args)
		{
			if (locals.get(a.id) == -1)
			{
				for (int j: conflicts.get(a.id))
					if (locals.get(j) == loc)
						continue nextarg;
				allocate(a.id, loc, locals, conflicts);
			}
		}
	}

	void alloc2(Expr e, ConflictGraph conflicts, Map<Integer,Integer> locals)
	{
		if (locals.get(e.id) != -1)
			return;

		BitSet used = new BitSet();
		for (int i: conflicts.get(e.id))
			if (locals.get(i) != -1)
				used.set(locals.get(i));
		
		
		//  Ensure that nothing leaked out of alloc1.
		assert ( ! (e.locals.length == 1 && e.inLocal() && locals.containsKey(e.locals[0].id) && (locals.get(e.locals[0].id)) != -1) );
	
		int loc;

		//  If an arg has a register allocated, try to re-use it.
		if (e.args.length != 0 && locals.containsKey(e.args[0].id) && (loc=locals.get(e.args[0].id)) != -1 &&
				!used.get(loc))
		{
			addTraceAttr("MayUseLoc", loc);
			allocate(e.id, loc, locals, conflicts);
			return;
		}

		// otherwise assign the lowest numbered free local
		loc = 0;
		while (used.get(loc))
			loc++;
		allocate(e.id, loc, locals, conflicts);
	}
	
	Map<Block,LocalVarState> getLocalVarState(Method m)
	{
		Map<Block,LocalVarState> result = new TreeMap<Block,LocalVarState>();
		Map<Block, Typeref[]> frames_by_block = new TreeMap<Block, Typeref[]>();
		
		Deque<Block> code = schedule(m.entry.to);

		//  Verifier's initial frame state:
		//  Parameters have known types,
		//  locals are type ANY.
		Typeref[] frame_state = new Typeref[m.local_count];
		
		System.arraycopy(m.getParams(), 0, frame_state, 0, m.getParams().length);
			
		for (int i = m.getParams().length; i < frame_state.length; i++)
			frame_state[i] = ANY().ref;
		
		verboseStatus("FRAME_STATE");
		
		for ( Block b: code )
		{
			if ( frames_by_block.containsKey(b))
				frame_state = frames_by_block.get(b);

			frame_state = buildLocalState(m, b, frame_state, result, frames_by_block);
		}
		
		//  Compute liveout sets.
		computeLiveout(code, result);
		
		return result;
	}
	
	Typeref[] buildLocalState(Method m, Block b, Typeref[] frame_state, Map<Block,LocalVarState> local_map, Map<Block, Typeref[]> states_by_block)
	{	
		LocalVarState block_state = local_map.get(b);
			
		if ( null == block_state )
		{
			block_state =  new LocalVarState(m, b, frame_state);
			local_map.put(b, block_state);
			
			switch (b.exprs.peekLast().op)
			{
			
			default:
			{
				break;
			}
			
			case OP_lookupswitch:
			{	
				for ( Edge p: b.succ())
					checkTarget(b, p.to, block_state.fs_out, states_by_block);
				break;
			}
			
			case OP_jump:
			{
				checkTarget(b, b.succ()[0].to, block_state.fs_out, states_by_block);
				break;
			}

			case OP_ifnlt:
			case OP_ifnle:
			case OP_ifngt:
			case OP_ifnge:
			case OP_ifne:
			case OP_ifstrictne:
			case OP_iftrue:
			case OP_iffalse:
			case OP_ifeq:
			case OP_iflt:
			case OP_ifle:
			case OP_ifgt:
			case OP_ifge:
			case OP_ifstricteq:
			    {
			    	checkTarget(b, b.succ()[1].to, block_state.fs_out, states_by_block);
			    	//  Leading edge is always the fall-through.
			    	break;
			    }
			}
		}
		
		return local_map.get(b).fs_out;
	}
	
	void checkTarget(Block branching_block, Block target_block, Typeref[] current_frame_state, Map<Block, Typeref[]> frames_by_block)
	{
		if ( !frames_by_block.containsKey(target_block))
		{
			verboseStatus ("    .. checkTarget(" + branching_block + "->" + target_block + ") copying frame state");
			
			Typeref[] target_frame = new Typeref[current_frame_state.length];
			System.arraycopy(current_frame_state, 0, target_frame, 0, current_frame_state.length);
			frames_by_block.put(target_block, target_frame);
		}
		else
		{
			Typeref[] previous_state = frames_by_block.get(target_block);
			
			verboseStatus("    .. checkTarget(" + branching_block + "->" + target_block + ") merging frame state");
			
			for ( int i = 0; i < previous_state.length; i++)
			{
				Typeref merged_type = typeMeet(previous_state[i], current_frame_state[i]); 
				
				if ( target_block.is_backwards_branch_target)
					previous_state[i] = merged_type.nullable();
				else
					previous_state[i] = merged_type;
			}
		}
		
		dumpFrameState(current_frame_state);
	}
	
	void dumpFrameState(Typeref[] fs_out)
	{
		if ( verbose_mode )
		{
			StringBuffer frame_state_buffer = new StringBuffer();
			frame_state_buffer.append("\tLocals: ");
			for ( int i = 0; i < fs_out.length; i++)
			{
				frame_state_buffer.append(fs_out[i].toString());
				frame_state_buffer.append(" ");
			}
			verboseStatus(frame_state_buffer);
		}
	}
	
	/**
	 *  Compute variable live-out sets for a control-flow graph.
	 *  Follows Cooper & Torczon's [section 9.2.2] Round-robin, iterative solver
	 * @param code - The CFG.  Not required to be in any particular order.
	 * @param live_map - the result map of blocks to sets of live-out variables.
	 * @pre live_map must already have per-block data 
	 *   for upwardly exposed vars, defines, and kills.
	 */
	void computeLiveout(Deque<Block> code, Map<Block,LocalVarState> live_map)
	{
		boolean changed = true;
		
		while ( changed )
		{
			changed = false;
			
			for ( Block b: code)
			{
				LocalVarState current_state = live_map.get(b);
				
				BitSet next_liveout = new BitSet();
				
				for ( Edge p: b.succ() )
				{
					next_liveout.or(live_map.get(p.to).getLivein());
				}
				
				for ( Edge x:b.xsucc)
				{
					next_liveout.or(live_map.get(x.to).getLivein());
				}
				
				changed |= current_state.mergeLiveout(next_liveout);
			}
		}
	}
	
	static class ConflictGraph
	{
		Map<Integer,Set<Integer>> conflicts = new TreeMap<Integer,Set<Integer>>();
		
		void add(Expr e1, Expr e2)
		{
			get(e1.id).add(e2.id);
			get(e2.id).add(e1.id);
		}
		
		boolean contains(Expr a, Expr b)
		{
			return conflicts.containsKey(a.id) && conflicts.get(a.id).contains(b.id);
		}
		
		public String toString()
		{
			return String.valueOf(conflicts);
		}
		
		Set<Integer> get(int i)
		{
			Set<Integer> s = conflicts.get(i);
			if (s == null)
				conflicts.put(i, s = new TreeSet<Integer>());
			return s;
		}
	}
	
	boolean hasStackEffect(Expr e)
	{
		if (e == null || e.op == OP_arg)
			return true;
		return e.onStack() || e.args.length > 0;
	}
	
	Typeref typeMerge(Typeref t1, Typeref t2)
	{
		Typeref result = null;
		
		Type merged_type = typeMeet(t1.t, t2.t);

		if (!merged_type.equals(ANY()) || (t1.t.equals(ANY()) && t2.t.equals(ANY())))
			result = new Typeref ( merged_type, t1.nullable || t2.nullable);

		return result;
	}

	
	Typeref typeMeet(Typeref t1, Typeref t2)
	{
		Typeref result = null;
		
		Type merged_type = typeMeet(t1.t, t2.t);

		result = new Typeref ( merged_type, t1.nullable | t2.nullable);
		
		return result;
	}
	
	/**
	 *  Type-meet as per the AVM verifier.
	 *  @param t1 a type.  May be null. 
	 *  @param t2 a type.  May be null.
	 *  @return the type meet of these types.
	 *  @return null if no common type exists.
	 */
	Type typeMeet(Type t1, Type t2)
	{
		if ( t1.equals(t2) )
			return t1;
		else if ( isNumericType(t1.ref) && isNumericType(t2.ref))
			return NUMBER();
		else if ( VOID().equals(t1) || NULL().equals(t1))
			return t2;
		else if ( VOID().equals(t2) || NULL().equals(t2) )
			return t1;

		//  Return the common base type or ANY.
		Type common_base = mdb(t1.ref, t2.ref).t;
		
		return common_base;
	}
	
	
	
	/**
	 * Schedule the expressions in the method to maximize use of the operand
	 * stack, by processing the flow graph and expressions backwards.  If we can't
	 * issue an instruction to fill a stack slot then we issue a getlocal instead,
	 * mark the expression live.
	 * 
	 * When an expression is marked live, add a conflict edge with each other live
	 * expression at that point. [Chotin paper?]
	 * 
	 * Phi expressions are handled specially - we make each argument live
	 * at the end of the corresponding predecessor block.  Since the stack is empty
	 * at the end of each BB, all phi nodes are allocated to a variable.  However,
	 * later, we attempt to allocate locals so phi nodes don't require copies.
	 * 
	 * @param code
	 * @param locals
	 * @param pred
	 * @return
	 */

	ConflictGraph sched_greedy(Method m, 
			Deque<Block> code, 
			Map<Integer,Integer> locals, 
			SetMap<Block,Edge>pred,
			Map<Block,Deque<Expr>> exprs,
			ConflictGraph cg)
	{

		addTraceAttr(m);
		
		SetMap<Block,Expr> liveout = new SetMap<Block,Expr>();
		Map<Block,Deque<Expr>> stkout = new TreeMap<Block,Deque<Expr>>();
		Map<Block,Deque<Expr>> scpout = new TreeMap<Block,Deque<Expr>>();
		HashMap<Block,Deque<Object>> listings = new HashMap<Block,Deque<Object>>();
		
		// low postorder numbers are first, 
		PriorityQueue<Block> work = new PriorityQueue<Block>(code.size(),new Comparator<Block>() {
			public int compare(Block b1,Block b2) {
				return b1.postorder-b2.postorder;
			}
		});
		
		work.addAll(code);

		while (!work.isEmpty())
		{
			Block b = work.remove();
			while (work.peek() == b) 
				work.remove(); // remove dups

			Set<Expr> live = new TreeSet<Expr>();
			Deque<Expr> in = new ArrayDeque<Expr>(b.exprs);
			Deque<Expr> stk = new ArrayDeque<Expr>();
			Deque<Expr> scp = new ArrayDeque<Expr>();
			Deque<Object> verbose = new LinkedDeque<Object>();
			Deque<Expr> out = new LinkedDeque<Expr>();

			Set<Expr> out_of_order = new TreeSet<Expr>();
			

			addTraceAttr(b);

			live.addAll(liveout.get(b));
			live.addAll(b.getLiveOut());
			live.addAll(m.fixedLocals.keySet());

			for (Expr l: live)
				locals.put(l.id, l.op == OP_arg ? l.imm[0] : -1);

			exprs.put(b,out);
			listings.put(b,verbose);

			Set<Expr>phis = new TreeSet<Expr>();
			while (!in.isEmpty() || !stk.isEmpty())
			{
				while (!stk.isEmpty() && hasStackEffect(in.peekLast()))
				{
					showstate(live, stk, scp, verbose);
					
					Expr e = remove_dup(stk, m, out, verbose);

					addTraceAttr(e);
					addTraceAttr("formattedExpr", formatExpr(e));
					
					if (e.inLocal() || e.op == OP_phi ||
						e != in.peekLast() || stk.contains(e))
					{
						/*
						if ( e != in.peekLast() && ! e.hasEffect() )
						{
							verboseStatus(".. out-of-order, but issue " + e);
							issue_expr(e, m, out, verbose, stk, scp, live, locals);
							out_of_order.add(e);
						}
						else
						*/
						{

							addTraceAttr(e);
							if ( e.inLocal() ) addTraceAttr("inLocal");
							else if ( e.op == OP_phi ) addTraceAttr("OP_phi");
							else if ( e != in.peekLast() ) addTraceAttr("stackMismatch", e.toString() + " != last Expr: " + formatExpr(in.peekLast()) );
							else if ( stk.contains(e) ) addTraceAttr("stackOverload", "stk.contains(" + e.toString() + ")");

							issue_load(e, m, out, verbose, live, locals);

						}
					}
					else if (live.contains(e))
					{
						// stack top ready to be issued but it's live. issue store.
						// push e back twice: once for store, once to consume.  then
						// go around loop once more to handle the dup + issue.
						traceEntry("DefineLiveExpr", e);
						define(e,live,cg);
						issue_store(e, m, out, verbose, stk);
						traceEntry("PushBack", e);
						stk.add(e);
					}
					else if (e.op == OP_xarg)
					{
						assert(stk.isEmpty());
						while (!stk.isEmpty())
							loadTOS(m, stk, scp, out, verbose, live, locals);
						verbose.addFirst(in.removeLast());
					}
					else
					{
						// e is ready to issue
						traceEntry("IssueExpr", e);
						issue_expr(in.removeLast(), m, out, verbose, stk, scp, live, locals);
					}

					continue;
				}

				if (!in.isEmpty())
				{
					showstate(live, stk, scp, verbose);
					Expr e = in.removeLast();

					addTraceAttr(e);
					addTraceAttr("formattedExpr", formatExpr(e));
					if ( out_of_order.contains(e) )
					{
						traceEntry("IssuedOutOfOrder", e );
						continue;
					}
					else if (e.op == OP_phi)
					{
						issue_phi(e, verbose, phis, live, cg);
					}
					else if (e.op == OP_arg)
					{
						verbose.addFirst(e);
						if (live.contains(e))
							define(e,live,cg);
					}
					else
					{
						if (live.contains(e))
						{
							traceEntry("LiveExpr");
							addTraceAttr(e);
							define(e,live,cg);
							//  ISSUE: Why not just issue a dup before the store?
							if (e.onStack())
							{
								traceEntry("StoreLiveExprFromStack ", e);
								issue_store(e, m, out, verbose, stk);
								traceEntry("PushBackOnStack", e);
								in.add(e);
							}
							else if (e.inLocal())
							{
								traceEntry("IssueExprFromLocal", e);
								issue_expr(e, m, out, verbose, stk, scp, live, locals);
							}
							else if (e.onScope())
							{
								traceEntry("IssueScopeExpr", e);
								issue_expr(e, m, out, verbose, stk, scp, live, locals);
							}
							else
							{
								assert(false);
							}
						}
						else if (e.op == OP_xarg)
						{
							issue_pop(m,out,verbose,e);
							verbose.addFirst(e);
						}
						else
						{

							addTraceAttr(e);
							if (e.onStack())
							{
								traceEntry("StackPop", e);
								issue_pop(m,out,verbose,e);
							}
							issue_expr(e, m, out, verbose, stk, scp, live, locals);

						}
					}

				}
			}
			
			fwd_state(m, locals, pred, liveout, stkout, scpout, work, b, live, stk, scp, verbose, out, phis);

		}
		verboseStatus("STK_LIVEOUT " + liveout);
		verboseStatus("CONFLICTS " + cg);

		for (Block b: code)
		{
			verboseStatus("");
			verboseStatus(b);
			for (Object o: listings.get(b)) 
				if (o instanceof Expr) 
					print((Expr)o); 
				else 
					verboseStatus(o);
		}

		return cg;
	}
	
	static void traceEntry(String traceTag)
	{
		tm.traceEntry(traceTag);
	}
	
	static void traceEntry(String traceTag, String attrValue)
	{
		tm.traceEntry(traceTag, attrValue);
	}
	
	static void traceEntry(String traceTag, String attrName, String attrValue)
	{
		tm.traceEntry(traceTag, attrName, attrValue);
	}
	
	static void traceEntry(String traceTag, String attrName, Object attrValue)
	{
		tm.traceEntry(traceTag);
		addTraceAttr(attrName, attrValue);
	}
	
	static void traceEntry(String traceTag, int attrValue)
	{
		tm.traceEntry(traceTag, attrValue);
	}
	
	
	static void traceEntry(String traceTag, Expr expr)
	{
		traceEntry(traceTag);
		addTraceAttr(expr);
	}
	
	
	static void addTraceAttr(String attrName)
	{
		tm.addAttr(attrName, "true");
	}
	
	static void addTraceAttr(Object o)
	{
		if ( null == o )
			return;
		else if ( o instanceof Block )
			addTraceAttr("Block", o);
		else if ( o instanceof Edge)
			addTraceAttr("Edge", o);
		else if ( o instanceof Expr)
			addTraceAttr("Expr", o);
		else if ( o instanceof Method )
			addTraceAttr("Method", o);
		else
			addTraceAttr(o.getClass().getSimpleName(), o);
	}
	
	static void addTraceAttr(String attrName, Object attr) 
	{
		tm.addAttr(attrName, attr);
		
		if ( attr != null && 
				( attrName.equalsIgnoreCase("Expr") || 
				attrName.equalsIgnoreCase("Method") || 
				attrName.equalsIgnoreCase("Block")))
		{
			tm.addAttr("HashCode", Integer.toHexString(attr.hashCode()));
		}
	}
	
	static void addTraceAttr(String attrName, int attr) 
	{
		tm.addAttr(attrName, attr);
	}
	
	static void addTraceAttr(String attrName, String attr) 
	{
		tm.addAttr(attrName, attr);
	}

	void showstate(Set<Expr> live, Deque<Expr> stk, Deque<Expr> scp, Deque<Object> verbose)
	{
		verbose.addFirst("              live "+live + " stk " + stk);
		if (!scp.isEmpty())
			verbose.addFirst("              scp  "+scp);
	}
	
	Expr remove_dup(Deque<Expr>stk, Method m, Deque<Expr>out, Deque<Object>verbose)
	{
		Expr e = stk.removeLast();
		while (e == stk.peekLast())
			issue_dup(stk.removeLast(), m, out, verbose);
		return e;
	}
	
	void try_dup(Deque<Expr>stk, Method m, Deque<Expr>out, Deque<Object>verbose)
	{
		if (stk.size()>2)
		{
			Expr e = stk.removeLast();
			while (e == stk.peekLast())
				issue_dup(stk.removeLast(), m, out, verbose);
			stk.add(e);
		}
	}
	
	void issue_phi(Expr e, Deque<Object>verbose, Set<Expr>phis, Set<Expr>live, ConflictGraph cg)
	{

		addTraceAttr(e);
		addTraceAttr("live", live.contains(e));

		verbose.addFirst(e);
		phis.add(e);
		if (live.contains(e))
			for (Expr l: live)
				if (l != e)
				{
					traceEntry("conflict");
					addTraceAttr(e);
					addTraceAttr("conflictsWith", l);
					cg.add(l,e);
				}

	}

	ConflictGraph sched_lazy(Method m, 
			Deque<Block> code, 
			Map<Integer,Integer> locals, 
			SetMap<Block,Edge>pred,
			Map<Block,Deque<Expr>> exprs,
			ConflictGraph cg)
	{
		SetMap<Block,Expr> liveout = new SetMap<Block,Expr>();
		Map<Block,Deque<Expr>> stkout = new TreeMap<Block,Deque<Expr>>();
		Map<Block,Deque<Expr>> scpout = new TreeMap<Block,Deque<Expr>>();
		HashMap<Block,Deque<Object>> listings = new HashMap<Block,Deque<Object>>();
		
		// low postorder numbers are first, 
		PriorityQueue<Block> work = new PriorityQueue<Block>(code.size(),new Comparator<Block>() {
			public int compare(Block b1,Block b2) {
				return b1.postorder-b2.postorder;
			}
		});
		
		work.addAll(code);
		while (!work.isEmpty())
		{
			Block b = work.remove();
			while (work.peek() == b) 
				work.remove(); // remove dups

			Set<Expr> live = new TreeSet<Expr>();
			Deque<Expr> in = new ArrayDeque<Expr>(b.exprs);
			Deque<Expr> stk = new ArrayDeque<Expr>();
			Deque<Expr> scp = new ArrayDeque<Expr>();
			Deque<Object> verbose = new LinkedDeque<Object>();
			Deque<Expr> out = new LinkedDeque<Expr>();

			// if any succ has defined an expected stack, use it.
			// if more than one have then they all have to match.
			if (stkout.containsKey(b))
				stk.addAll(stkout.get(b));

			// merge the live vars from each succ
			live.addAll(liveout.get(b));

			for (Expr l: live)
				locals.put(l.id, l.op == OP_arg ? l.imm[0] : -1);
			
			exprs.put(b,out);
			listings.put(b,verbose);
			
			Set<Expr>phis = new TreeSet<Expr>();

			while (!in.isEmpty())
			{
				showstate(live, stk, scp, verbose);
				Expr e = in.removeLast();
				
				if (e.op == OP_phi)
				{
					issue_phi(e, verbose, phis, live, cg);
					continue;
				}
				assert(phis.isEmpty());

				boolean onstack = false;
				while (stk.contains(e))
				{
					onstack = true;
					Expr f = remove_dup(stk, m, out, verbose);
					if (f != e || stk.contains(e))
						issue_load(f,m,out,verbose,live,locals);
				}
				
				if (e.op == OP_arg)
				{
					if (onstack)
						issue_load(e,m,out,verbose,live,locals);
					verbose.addFirst(e);
					if (live.contains(e))
						define(e,live,cg);
				}
				else
				{
					if (live.contains(e))
					{
						if (e.op == OP_xarg)
							while (!stk.isEmpty())
								loadTOS(m,stk,scp,out,verbose,live,locals);
						define(e, live, cg);
						if (onstack)
							stk.add(e);
						issue_store(e, m, out, verbose, stk);
						in.add(e);
					}
					else if (e.op == OP_xarg)
					{
						if (!stk.isEmpty())
						{
							while (!stk.isEmpty())
								loadTOS(m,stk,scp,out,verbose,live,locals);
							in.add(e); // put xarg back
							if (onstack)
								stk.add(e); // make xarg the only thing on the stack.
						}
						else
						{
							if (!onstack)
								issue_pop(m,out,verbose,e);
							verbose.addFirst(e); //print but don't issue it.
						}
					}
					else
					{
						if (!onstack && e.onStack())
							issue_pop(m,out,verbose,e);
						issue_expr(e, m, out, verbose, stk, scp, live, locals);
					}
				}
			}
			
			fwd_state(m, locals, pred, liveout, stkout, scpout, work, b, live, stk, scp, verbose, out, phis);
		}
		verboseStatus("SCHED LIVEOUT " + liveout);
		verboseStatus("SCHED STKOUT " + stkout);
		verboseStatus("SCHED CONFLICTS " + cg);

		for (Block b: code)
		{
			verboseStatus("");
			verboseStatus(b);
			for (Object o: listings.get(b)) 
				if (o instanceof Expr) 
					print((Expr)o); 
				else 
					verboseStatus(o);
		}		
		return cg;
	}
	
	/** 
	 * issue a load for whatever is on the stack top
	 */
	void loadTOS(Method m, Deque<Expr>stk, Deque<Expr>scp, Deque<Expr>out, Deque<Object>verbose, Set<Expr>live, Map<Integer,Integer>locals)
	{
		// stk doesn't match, make all successors expect nothing.
		showstate(live, stk, scp, verbose);
		Expr e = stk.removeLast();
		if (e == stk.peekLast())
			issue_dup(e, m, out, verbose);
		else
			issue_load(e, m, out, verbose, live, locals);
	}

	/**
	 * forward the stack & live variable state from the top of the current
	 * block (b) to the end of each predecessor block, translating phi nodes
	 * at the same time.
	 * 
	 * @param m
	 * @param locals
	 * @param pred
	 * @param liveout
	 * @param stkout
	 * @param work
	 * @param b
	 * @param live
	 * @param stk
	 * @param verbose
	 * @param out
	 * @param phis
	 */
	void fwd_state(Method m, Map<Integer, Integer> locals, 
			SetMap<Block, Edge> pred, SetMap<Block, Expr> liveout, 
			Map<Block, Deque<Expr>> stkout, Map<Block,Deque<Expr>> scpout,
			PriorityQueue<Block> work, Block b, Set<Expr> live, 
			Deque<Expr> stk, Deque<Expr> scp, 
			Deque<Object> verbose, Deque<Expr> out, Set<Expr> phis)
	{
		// first prune stack to something safe to forward.
		TreeMap<Block,Deque<Expr>>stkout2 = new TreeMap<Block,Deque<Expr>>(stkout);
		
		for (Edge p: pred.get(b))
		{
			Block f = p.from;
			Deque<Expr> stk2 = clone_stk(phis,stk,p);
			if (!stkout2.containsKey(f))
			{
				stkout2.put(f,stk2);
			}
			else
			{
				int prefix = stacks_equal(stk2,stkout2.get(f));
				assert(stk.size() >= prefix);
				while (stk.size() > prefix)
					loadTOS(m,stk,scp,out,verbose,live,locals);
			}
		}
		showstate(live, stk, scp, verbose);
		
		for (Edge p: pred.get(b))
		{
			Block f = p.from;

			// forward live exprs
			Set<Expr> live2 = clone_live(phis,live,p);
			if (liveout.get(f).addAll(live2))
				work.add(f);

			// forward stack exprs
			Deque<Expr> stk2 = clone_stk(phis,stk,p);
			if (!stkout.containsKey(f))
			{
				stkout.put(f, stk2);
			}
			else
			{
				int prefix = stacks_equal(stk2,stkout.get(f));
				assert(stk2.size() == prefix && stkout.get(f).size() >= prefix);
				if (stkout.get(f).size() > prefix)
				{
					stkout.put(f, stk2);
					work.add(f);
					for (Edge s: f.succ())
						if (s.to != b)
							work.add(s.to);
				}
			}
		}
	}
	
	/**
	 * clone the live vars set for a particular predecessor edge,
	 * replacing phi's with the expr corresponding to that edge.
	 *
	 * @param phis
	 * @param live
	 * @param p
	 * @return
	 */
	Set<Expr> clone_live(Set<Expr>phis, Set<Expr>live, Edge p)
	{
		if (phis.isEmpty() || live.isEmpty())
			return live;
		Set<Expr> copy = new TreeSet<Expr>();
		for (Expr e: live)
			copy.add(phis.contains(e) ? e.args[findPhiArg(e, p)] : e);
		return copy;
	}
	
	/**
	 * clone the stack layout for a predecessor edge, replacing phi's
	 * with the argument coming from that edge.
	 * 
	 * @param phis
	 * @param stk
	 * @param p
	 * @return
	 */
	Deque<Expr> clone_stk(Set<Expr>phis, Deque<Expr>stk, Edge p)
	{
		if (phis.isEmpty() || stk.isEmpty())
			return stk;
		Deque<Expr> copy = new ArrayDeque<Expr>();
		for (Expr e: stk)
			copy.add(phis.contains(e) ? e.args[findPhiArg(e, p)] : e);
		return copy;
	}
	
	int stacks_equal(Deque<Expr>stk1, Deque<Expr>stk2)
	{
		int i=0;
		Iterator<Expr> i1 = stk1.iterator();
		Iterator<Expr> i2 = stk2.iterator();
		while (i1.hasNext() && i2.hasNext())
		{
			if (i1.next() != i2.next())
				return i;
			i++;
		}
		return i;
	}
	
	void define(Expr e, Set<Expr> live, ConflictGraph cg)
	{

		addTraceAttr(e);
		live.remove(e);
		for (Expr l: live)
		{
			cg.add(e,l);
			traceEntry("conflict");
			addTraceAttr(e);
			addTraceAttr("conflictsWith", l);
		}

	}

	void issue_expr(Expr e, Method m, Deque<Expr>out, Deque<Object> verbose, Deque<Expr>stk, Deque<Expr>scp, Set<Expr>live, Map<Integer,Integer> locals)
	{

		addTraceAttr(e);
		if (!e.isSynthetic())
			out.addFirst(e);
		verbose.addFirst(e);
		for (Expr a: e.args)
		{
			traceEntry("PushArg", "Expr", a);
			stk.add(a);
		}
		for (Expr a: e.locals)
		{
			traceEntry("UseLocal", "Expr", a);
			use(a, live, locals);
		}
		try_dup(stk, m, out, verbose);

	}
	
	void issue_store(Expr e, Method m, Deque<Expr>out, Deque<Object> verbose, Deque<Expr>stk)
	{
		Expr set = setlocal(m, e.id, e);

		addTraceAttr("setlocalExpr", formatExpr(set));
		out.addFirst(set);
		verbose.addFirst(set);
		traceEntry("Push", formatExpr(e));
		stk.add(e);

	}
	
	void issue_dup(Expr e, Method m, Deque<Expr>out, Deque<Object> verbose)
	{
		Expr dup = dup(m,e);
		out.addFirst(dup);
		traceEntry("issue_dup", dup);
		verbose.addFirst(dup);
	}
	
	void issue_pop(Method m, Deque<Expr>out, Deque<Object> verbose, Expr a)
	{
		Expr pop = new Expr(m, OP_pop, a);
		out.addFirst(pop);
		verbose.addFirst(pop);
	}

	void issue_load(Expr e, Method m, Deque<Expr>out, Deque<Object>verbose, Set<Expr>live, Map<Integer,Integer>locals)
	{
		use(e, live, locals);
		Expr get = getlocal(m,e.id);
		out.addFirst(get);
		traceEntry("issue_load", get);
		verbose.addFirst(get);
	}

	void use(Expr e, Set<Expr> live, Map<Integer, Integer> locals)
	{
		traceEntry("use");
		addTraceAttr(e);
		live.add(e);
		locals.put(e.id, e.op == OP_arg ? e.imm[0] : -1);
		addTraceAttr("locals_entry", locals.get(e.id));
	}
	
	void rename(Expr e, Expr[] args, Map<Expr,Expr> map, EdgeMap<Expr> ssaSucc)
	{

		addTraceAttr(e);
		
		for (int i=0, n=args.length; i<n; i++)
		{
			Expr a = args[i];
			while (map.containsKey(a))
			{
				ssaSucc.get(a).remove(e);
				traceEntry("renamedArg");
				addTraceAttr("i", i);
				addTraceAttr("orig", args[i]);
				a = args[i] = map.get(a);
				a.is_live_out  = a.onStack() || a.inLocal();
				addTraceAttr("new", args[i]);
				ssaSucc.get(a).add(e);
			}
		}
		

	}
	
	/**
	 * Copy propagation.
	 * 
	 * Phi nodes that only choose themselves or one other variable
	 * are replaced by references to that other variable:
	 * 
	 *    @i = phi(@i ... @j), op(@i)   =>    = op(@j)
	 *
	 * additionally, references to a dup are replaced by references to the
	 * dup's argument.  Dup is a copy instruction inserted by some previous
	 * optimization. 
	 * 
	 *    @i = dup(@j), op(@i)   =>  op(@j)
	 * 
	 * We take advantage of SSA's sparseness by propagating changes along
	 * def->use edges and iterating until our worklist is empty.
	 * 
	 * This pass also removes any phi arguments that are dead, i.e. if the
	 * edge contributing the argument is from an unreachable block.  This
	 * may turn the phi into a copy which is subsequently removed.
	 */
	void cp(Deque<Block> code)
	{

		EdgeMap<Expr> uses = findUses(code);
		Map<Expr,Expr> map = new HashMap<Expr,Expr>();
		Set<Expr> work = new TreeSet<Expr>();
		
		for (Block b: code)
		{
			if ( ! b.must_isolate_block)
			{
				for (Expr e: b)
					if (e.op == OP_phi || e.op == OP_dup)
						work.add(e);
			}
		}
		
		while (!work.isEmpty())
		{
			Expr e = getExpr(work);
			rename(e, e.args, map, uses);
			rename(e, e.scopes, map, uses);
			rename(e, e.locals, map, uses);
			if (e.op == OP_dup)
			{
				map.put(e, e.locals[0]);
				work.addAll(uses.get(e));
			}
			else if (e.op == OP_phi)
			{
				assert(e.args.length == e.pred.length);
				for (int j=e.pred.length-1; j >= 0; j--)
					if (!code.contains(e.pred[j].from))
						e.removePhiInput(j);
				Expr a = null;
				for (int j=e.pred.length-1; j >= 0; j--)
				{	
					if (e.args[j] != e && e.args[j] != a)
						if (a == null)
							a = e.args[j];
						else
						{
							a = null;
							break;
						}
				}
				if (a != null && map.get(e) != a)
				{
					map.put(e, a);
					work.addAll(uses.get(e));
					e.clearEffect();
				}
			}
		}
		
		//  Marshall live-out exprs by block.
		for ( Block b: code)
		{
			for ( Expr e: b.exprs)
			{
				if ( e.is_live_out )
				{
					b.addLiveOut(e);
				}
			}
				
		}
		

	}

	boolean hasSideEffect(Expr e)
	{
		return e.isPx() || e.hasEffect();
	}
	
	void schedule_loop(Block b, EdgeMap<Block> loops, Deque<Block> scheduled)
	{
		Set<Block> loop = loops.get(b);
		for (Block lb: dfs(b))
		{
			if (!scheduled.contains(lb) && loop.contains(lb))
			{
				scheduled.add(lb);
				if (loops.containsKey(lb))
					schedule_loop(lb, loops, scheduled);
			}
		}
	}
	
	/**
	 * layout blocks.  Normal forward flow is laid out in reverse postorder.
	 * Loops are handled specially to keep blocks in the loop body close to
	 * each other.  loop exit blocks are postponed until after the loop.
	 * @param entry
	 * @return
	 */
	Deque<Block> schedule(Block entry)
	{
		Deque<Block>code = dfs(entry);
		Deque<Block>scheduled = new ArrayDeque<Block>();
		SetMap<Block,Edge> pred = preds(code);
		Map<Block,Block> idom = idoms(code,pred);
		EdgeMap<Block> loops = findLoops(code,idom,pred);
		
		if (!loops.isEmpty())
			verboseStatus("LOOPS "+loops);
		
		for (Block b: code)
		{
			//  TODO: Post-test loops  fail the AVM verifier
			//  under certain conditions (not well understood).
			if (!scheduled.contains(b))
				scheduled.add(b);
			if (loops.containsKey(b))
				schedule_loop(b, loops, scheduled);
		}
		
		//  Rearrange conditional branches so that fall-through edges
		//  occur in the optimizer's natural flow, and flag any
		//  backwards branch targets.
		Deque<Block> branch_analysis = new ArrayDeque<Block>();
		branch_analysis.addAll(scheduled);
		Set<Block> already_seen = new HashSet<Block>();
		
		while (branch_analysis.size()>1)
		{
			Block b = branch_analysis.removeFirst();
			
			Expr last = b.last();
			
			Block next = branch_analysis.peekFirst();
			if (isBranch(last) && last.succ[0].to != next &&
					last.succ[1].to == next)
				invert(last);
			
			//  Check for backwards branches.
			already_seen.add(b);

			b.is_backwards_branch_target = false;
			
			for ( Edge s: b.succ())
			{
				s.to.is_backwards_branch_target |= s.is_backwards_branch = already_seen.contains(s.to);
			}
		}
		
		if ( verbose_mode )
			for (Block b: code)
				if ( b.is_backwards_branch_target )
					verboseStatus(".. backwards branch target:" + b);
		
		return scheduled;
	}
	
	boolean isJump(Expr e)
	{
		return e.op == OP_jump;
	}
	
	boolean isBranch(Expr e)
	{
		return e.succ != null && e.succ.length == 2 && e.op != OP_lookupswitch;
	}
	
	
	/**
	 * returns true if P->S is a loop back edge.  This is the
	 * case if S is visited first in reverse postorder and S
	 * dominates P.
	 * 
	 * @param p
	 * @param s
	 * @param idom
	 * @return
	 */
	boolean isLoop(Edge e, Map<Block,Block>idom)
	{
		return e.isBackedge() && dominates(e.to, e.from, idom);
	}
	
	EdgeMap<Block> findLoops(Deque<Block> code)
	{
		SetMap<Block,Edge> pred = preds(code);
		return findLoops(code, idoms(code, pred), pred);
	}
	
	/**
	 * loop code layout
	 * the loop is defined by the back edge from T->H.  H (header) is the source
	 * of the back edge.  We want H at the bottom of the loop and T at the top.
	 * Lay the blocks out in DFS order starting with T and skipping any blocks
	 * that aren't part of the loop.
	 * 
	 * prefer to have fall-through blocks that are part of the loop.
	 */
	
	EdgeMap<Block> findLoops(Deque<Block> code, Map<Block,Block>idom, SetMap<Block,Edge>pred)
	{
		EdgeMap<Block> loops = new EdgeMap<Block>();
		for (Block b: code)
			for (Edge s: b.succ())
				if (isLoop(s, idom))
				{
					verboseStatus("backedge "+s);
					Block h = s.to;
					// find the set of blocks that are in the loop body.
					Set<Block> loop = loops.get(h);
					Set<Block> work = new TreeSet<Block>();
					for (Edge p: pred.get(h))
					{
						if (isLoop(p,idom) && !loop.contains(p.from) && p.from != h)
						{
							loop.add(p.from);
							work.add(p.from);
						}
					}
					while (!work.isEmpty())
					{
						Block x = getBlock(work);
						for (Edge p: pred.get(x))
						{
							if (p.from != h && !loop.contains(p.from))
							{
								loop.add(p.from);
								work.add(p.from);
							}
						}
					}
				}
		return loops;
	}
		
	void dce_mark(BitSet used, Expr e)
	{
		if (used.get(e.id))
			return;
		used.set(e.id);
		for (Expr a: e.args) dce_mark(used, a);
		for (Expr a: e.scopes) dce_mark(used, a);
		for (Expr a: e.locals) dce_mark(used, a);
	}

	/**
	 * Dead Code Elimination.  First perform copy propagation and then
	 * remove any expressions not used by the essential expressions
	 * that have side effects.  
	 * @param m
	 */
	void dce(Method m)
	{
		Deque<Block> code = dfs(m.entry.to);
		
		cp(code);
		
		BitSet marked = new BitSet();
		for (Block b: code)
			for (Expr e: b)
				if (hasSideEffect(e))
					dce_mark(marked,e);
		
		for (Block b: code)
			for (Iterator<Expr> i = b.iterator(); i.hasNext();)
				if (!marked.get(i.next().id))
				{
					i.remove();
				}
	}
	
	class TypeConstraintMap extends HashMap<Edge, TypeConstraints>
	{
		/** @see Serializable */
		private static final long serialVersionUID = 1903880092224622848L;

		TypeConstraintMap()
		{
			super();
		}
		
		/**
		 *  Retrieve or create an Edge's constraints.
		 *  @param key - the Edge of interest.
		 *  @return the Edge's constraints.
		 */
		TypeConstraints getConstraints(Edge key)
		{
			TypeConstraints result = get(key);
			
			if ( null == result )
			{
				result = new TypeConstraints(key);
				put(key, result);
			}
			
			return result;
		}
		
	}
	
	String format(char op, Object[] a, char cp)
	{
		if (a == null)
			return "";
		StringBuilder s = new StringBuilder();
		s.append(op);
		for (Object o: a)
			s.append(o).append(' ');
		if (a.length > 0)
			s.setCharAt(s.length()-1,cp);
		else
			s.append(cp);
		return s.toString();
	}
		
	static boolean isSlot(Binding b)
	{
		return (b != null)? b.isSlot(): false;
	}
	static boolean isConst(Binding b)
	{
		return (b != null)? b.isConst(): false;
	}
	static boolean isClass(Binding b)
	{
		return (b != null)? b.isClass(): false;
	}
	static boolean isMethod(Binding b)
	{
		return (b != null)? b.isMethod() :false;
	}
	static boolean isGetter(Binding b)
	{
		return (b != null)? b.isGetter(): false;
	}
	static boolean isSetter(Binding b)
	{
		return (b != null)? b.isSetter(): false;
	}
	
	/**
	 * how many stack elements need to be popped to complete
	 * the given multiname reference.
	 */
	static int[] refArgc = 
	{
	    0,//byte CONSTANT_Void = 0x00;  // not actually interned
	    0,//byte CONSTANT_Utf8 = 0x01;
	    0, //0x02
	    0,//byte CONSTANT_Integer = 0x03;
	    0,//byte CONSTANT_UInteger = 0x04;
	    0,//byte CONSTANT_PrivateNamespace = 0x05;
	    0,//byte CONSTANT_Double = 0x06;
	    0,//byte CONSTANT_Qname = 0x07;  // ns::name, const ns, const name
	    0,//byte CONSTANT_Namespace = 0x08;
	    0,//byte CONSTANT_Multiname = 0x09;    //[ns...]::name, const [ns...], const name
	    0,//byte CONSTANT_False = 0x0A;
	    0,//byte CONSTANT_True = 0x0B;
	    0,//byte CONSTANT_Null = 0x0C;
	    0,//byte CONSTANT_QnameA = 0x0D;    // @ns::name, const ns, const name
	    0,//byte CONSTANT_MultinameA = 0x0E;// @[ns...]::name, const [ns...], const name
	    1,//byte CONSTANT_RTQname = 0x0F;    // ns::name, var ns, const name
	    1,//byte CONSTANT_RTQnameA = 0x10;    // @ns::name, var ns, const name
	    2,//byte CONSTANT_RTQnameL = 0x11;    // ns::[name], var ns, var name
	    2,//byte CONSTANT_RTQnameLA = 0x12; // @ns::[name], var ns, var name
	    0,//0x13
	    0,//0x14
	    0,//byte CONSTANT_Namespace_Set = 0x15; // a set of namespaces - used by multiname
	    0,//byte CONSTANT_PackageNamespace = 0x16; // a namespace that was derived from a package
	    0,//byte CONSTANT_PackageInternalNs = 0x17; // a namespace that had no uri
	    0,//byte CONSTANT_ProtectedNamespace = 0x18;
	    0,//byte CONSTANT_ExplicitNamespace = 0x19;
	    0,//byte CONSTANT_StaticProtectedNs = 0x1A;
	    1,//byte CONSTANT_MultinameL = 0x1B;
	    1,//byte CONSTANT_MultinameLA = 0x1C;
	};
	
	static class FrameState
	{
		Expr[] frame;
		int sp;
		int scopep;
		
		public FrameState(Expr[] frame, int sp, int scopep)
		{
			super();
			this.frame = new Expr[frame.length];
			this.sp = sp;
			this.scopep = scopep;
		}
	}
	
	static boolean isLive(int i, Method m, int scopep)
	{
		return i < scopep || i >= m.local_count + m.max_scope;
	}
	
	Block createBlock(Method m, Edge edge, Map<Block,FrameState>states, Expr[] frame, int sp, int scopep)
	{

		Block b = new Block(m);
		addTraceAttr("Block", b);
		FrameState state = new FrameState(frame,sp,scopep);

		if (edge != null)
		{
			edge.to = b;
			traceEntry("Edge");
			addTraceAttr("to", b);
		}
		for (int i=0; i < sp; i++)
		{
			if (isLive(i,m,scopep) && frame[i] != null)
			{
				Expr e = new Expr(m,OP_phi);
				if (edge != null)
				{
					e.args = new Expr[] { frame[i] };
					e.pred = new Edge[] { edge };
				}
				b.add(state.frame[i] = e);
			}
		}
		traceFrame("NewBlockFrame", m, frame, scopep, sp);
		states.put(b, state);

		return b;
	}
	
	/**
	 * merge state with block at position pos.  If the target block
	 * doesn't exist, create it first.
	 * 
	 * @param m
	 * @param edge
	 * @param blocks
	 * @param states
	 * @param pos
	 * @param frame
	 * @param sp
	 * @param scopep
	 */
	void merge(Method m, Edge edge, Map<Integer,Block> blocks, Map<Block,FrameState> states, int pos, Expr[] frame, int sp, int scopep)
	{

		addTraceAttr("Edge", edge);
		
		if (!blocks.containsKey(pos))
		{
			Block b = createBlock(m,edge,states,frame,sp,scopep);
			blocks.put(pos, b);
		}
		else if (edge != null)
		{
			edge.to = blocks.get(pos);
			mergeFrameStates(m, edge, states, frame, sp, scopep);
		}

	}
	
	/**
	 * merge current state with existing block (edge.to)
	 * @param m
	 * @param edge
	 * @param states
	 * @param frame
	 * @param sp
	 * @param scopep
	 */
	void mergeFrameStates(Method m, Edge edge, Map<Block,FrameState>states, Expr[] frame, int sp, int scopep)
	{

		FrameState target = states.get(edge.to);
		
		/*
		//  FIXME: There are a restricted set of circumstances
		//  where it's permissible to have a stack mismatch --
		//  asc doesn't completely restore scope stacks at a join
		//  from a catch block to a return, for example.
		//  Need a bottom value or sth similar to represent this.
		
		assert(target.sp == sp);
		assert(target.scopep == scopep);
		*/
		for (int i=0; i < sp; i++)
		{
			if (isLive(i,m,scopep) && frame[i] != target.frame[i])
			{
				if ( target.frame[i] == null )
				{
					//  FIXME: See above comment;
					//  only valid value here is 
					//  an invalid value.
				}
				else
				{
					assert(frame[i] != null && target.frame[i].op == OP_phi);
					target.frame[i].append(frame[i], edge);
				}
			}
		}
		

	}

	void xmerge(Method m, Edge edge, Map<Integer,Block> blocks, Map<Block,FrameState> states, int pos, Expr[] frame, int sp, int scopep)
	{

		scopep = m.local_count;
		sp = scopep + m.max_scope;
		
		Handler h = edge.handler;
		
		if (h.entry == null)
		{
			// first time, create handler block that jumps to catch block
			addTraceAttr("firstTime");
			Block hb = h.entry = createBlock(m, edge, states, frame, sp, scopep);
			Expr xarg, jump;
			hb.add(xarg = new Expr(m,OP_xarg, edge.label));
			hb.add(jump = new Expr(m,OP_jump));
			jump.succ = new Edge[] { new Edge(m, hb, 0, blocks.get(pos)) };
			Expr save = frame[sp];
			frame[sp] = xarg;
			
			traceEntry("HandlerBlock");
			addTraceAttr("Block", hb);
			addTraceAttr("Edge", edge);
			traceFrame("Frame", m, frame, scopep, sp);
			
			// and merge the handler block with the real exception target.
			merge(m, jump.succ[0], blocks, states, pos, frame, sp+1, scopep);
			frame[sp] = save;
		}
		else
		{
			// each time, merge current state with handler block state.
			addTraceAttr("notFirstTime");
			edge.to = h.entry;
			mergeFrameStates(m, edge, states, frame, sp, scopep);
		}

	}
	
	void traceFrame(String desc, Method m, Expr[] frame, int scopep, int sp)
	{


		
		int i = 0;
		for ( i = 0; i < m.local_count; i++ )
		{
			traceEntry("Local");
			addTraceAttr("number", i);
			addTraceAttr("value", frame[i]);
		}

		

		addTraceAttr("scopep", scopep);
		for (; i < scopep; i++ )
		{
			traceEntry("Scope");
			addTraceAttr("index", i);
			addTraceAttr("value", frame[i]);
		}

		

		addTraceAttr("sp", sp);
		for ( i = m.local_count + m.max_scope; i < sp; i++ )
		{
			traceEntry("Operand");
			addTraceAttr("index", i);
			addTraceAttr("value", frame[i]);
		}

		

	}

	static Expr[] capture(Expr[] frame, int top, int len)
	{
		Expr[] args = new Expr[len];
		System.arraycopy(frame, top-len, args, 0, len);

		addTraceAttr("stackPtr", top);
		addTraceAttr("len", len);
		for ( int i = 0; i < len; i++)
		{
			traceEntry("PopStack");
			addTraceAttr(args[i]);
		}

		return args;
	}
	
	void print(Expr e)
	{
		if ( !verbose_mode )
			return;
		PrintWriter pw = new PrintWriter(System.out);
		printssa(e, pw);
		pw.flush();
	}
	
	void printabc(Expr e, PrintWriter out)
	{
		if ( verbose_mode )
			out.println(formatExprAsAbc(e));
	}
	
	String formatExprAsAbc(Expr e)
	{	
		StringBuilder s = new StringBuilder();
		s.append("    " + opNames[e.op]);
		if (e.imm != null)
		{
			s.append('<');
			for (int i: e.imm)
				s.append(i).append(',');
			s.setCharAt(s.length()-1,'>');
		}
		if (e.succ != null)
			s.append(format('[',e.succ,']'));
		if (e.value != null)
		{
			s.append(" ");
			s.append(formatObject(e.value));
		}
		if (e.ref != null)
		{
			s.append(" ");
			s.append(e.ref);
		}
			
		return s.toString();
	}
	
	void printssa(Expr e, PrintWriter out)
	{		
		out.println(formatExpr(e));
	}
	
	String formatExpr(Expr e)
	{
		if ( null == e )
		{
			return "null";
		}
		
		StringBuffer outBuffer = new StringBuffer();
		
		outBuffer.append(e.toString());
		if (e.onStack() || e.inLocal() || e.onScope())
			outBuffer.append(" =");
		else
			outBuffer.append("  ");
			
		if (e.value == null)
			outBuffer.append(" "+opNames[e.op]);
		if (e.imm != null)
		{
			outBuffer.append('<');
			for (int i: e.imm)
				outBuffer.append(i).append(',');
			outBuffer.setCharAt(outBuffer.length()-1,'>');
		}
		if (e.args.length > 0)
			outBuffer.append(format('(',e.args,')'));
		if (e.locals.length > 0)
			outBuffer.append(format('(',e.locals,')'));
		if (e.scopes.length > 0)
			outBuffer.append(format('{',e.scopes,'}'));
		if (e.pred.length>0)
			outBuffer.append(format('[',e.pred,']'));
		if (e.succ != null)
			outBuffer.append(format('[',e.succ,']'));
		if (e.value != null)
			outBuffer.append(formatObject(e.value));
		if (e.ref != null)
			outBuffer.append(" "+e.ref);//.format()); // full name
	
		return outBuffer.toString();
	}
	
	void print(Object value, PrintWriter out)
	{
		out.print(formatObject(value));
	}
	
	String formatObject(Object value)
	{
		if (value instanceof String)
			return(" \"" + ((String)value).replace("\n","\\n").replace("\r","\\r") + "\"");
		else
			return(" "+ value);
	}
	
	void printMethod(Method m, String banner)
	{
		if ( ! verbose_mode )
			return;
		
		PrintWriter pw = new PrintWriter(System.out);
		
		pw.println();
		pw.println();
		
		pw.println(banner);
		pw.println("\t"+m.getName()+" local_count="+m.local_count+" max_stack="+m.max_stack+" max_scope="+m.max_scope);
		
		Deque<Block> blocks = dfs(m.entry.to);

		pw.println(blocks);

		for (Block b: blocks)
			print(b,pw);
		pw.println();
		pw.flush();
	}

	void printabc(Deque<Block> blocks)
	{
		if ( ! verbose_mode )
			return;
		verboseStatus(blocks);
		PrintWriter pw = new PrintWriter(System.out);
		for (Block b: blocks)
			printabc(b,pw);
		pw.flush();
	}
	
	void print(Block b, PrintWriter pw)
	{
		pw.println();
		printssa(b, pw);
	}
	
	void printabc(Block b, PrintWriter out)
	{
		out.println();
		out.println(b);
		if (b.xsucc.length > 0)
			out.println(Arrays.toString(b.xsucc));
		for (Expr s: b)
			printabc(s,out);
	}

	void printssa(Block b, PrintWriter out)
	{
		out.println(b);
		if (b.xsucc.length > 0)
			out.println(Arrays.toString(b.xsucc));
		for (Expr s: b)
			printssa(s,out);
	}
		
	void dot(String suffix, Method m)
	{
		// don't bother with single-block methods.
		if (m.entry.to.succ().length == 0)
			return;
		
		// save a dot file for the method
		try
		{
			PrintWriter out = new PrintWriter(new FileWriter(m.getName()+suffix+".dot"));
			try
			{
				Deque<Block> code = dfs(m.entry.to);
				
				out.println("digraph {");
				out.println("compound=true;");
				out.println("label=\""+m.getName()+suffix+"\";");
				out.println("labelloc=top;");
				out.println("fontsize=10;");
				
				if (SHOW_DFG)
				{
					out.println("ranksep=.1; nodesep=.1;");
					out.println("node [shape=plaintext,width=.05,height=.05,fontsize=12];");
				}
				else
				{
					out.println("ranksep=.25; nodesep=.25;");
					out.println("node [shape=box,width=.1,height=.1,fontsize=12];");
				}
					
				out.println("edge [arrowsize=.5,fontsize=8,labelfontsize=8];");
				
				for (Block b: code)
					if (SHOW_DFG)
						dot_dfg(b,out);
					else
						dot(b,out);
				
				if ( SHOW_DOMINATORS )
				{
					Map<Block,Block> doms = idoms(code,allpreds(code));
					out.println("node [shape=box];");
					out.println("subgraph cluster1 { label=\"Dominators\"; color=white; ");
					for (Block b: dfs(m.entry.to))
					{
						out.println("D"+b+" [label="+b+"];");
						if (doms.containsKey(b))
							out.println("D"+doms.get(b)+" -> D"+b);
					}
					out.println("}");
				}
				
				out.println("}");
			}
			finally
			{
				out.close();
			}
		}
		catch (IOException e) 
		{
			throw new RuntimeException(e);
		}
	}
	
	static class LabelWriter extends PrintWriter
	{
		StringWriter w;
		LabelWriter(StringWriter w)
		{
			super(w);
			this.w = w;
		}
		public void println() { print("\\l"); flush(); }
		public void print(String s) 
		{
			super.print(s.replace("\"","''").replace("\u0278","&phi;")); 
		}
		public String toString()
		{
			return w.toString();
		}
	}
	
	void dot(Block b, PrintWriter out)
	{
		LabelWriter w = new LabelWriter(new StringWriter());
		
		// create the label
		if (SHOW_CODE)
			printssa(b,w);
		else
			w.print(b);
		String attr = "label=\""+w+"\"";
		
		out.println(b+" ["+attr+"];");
		
		// CFG edges
		for (Edge e: b.succ())
			dot(e, out);
		for (Edge e: b.xsucc)
			dot(e, out);
	}
	
	void dot_dfg(Block b, PrintWriter out)
	{
		LabelWriter w = new LabelWriter(new StringWriter());
		
		// create the label
		w.print(b);
		String attr = "label=\""+w+"\"; labeljust=l";
		
		// dfg edges
		out.println("subgraph cluster"+b+" { "+attr+";");
		Expr n = null;
		Iterator<Expr> i = b.iterator();
		if (i.hasNext())
			n = i.next();
		while (n != null)
		{
			Expr e = n;
			w = new LabelWriter(new StringWriter());
			printssa(e,w);
			out.print("E"+e.id+" [label=\""+w+"\"];");
			if (i.hasNext())
			{
				n = i.next();
				out.print("E"+e.id+" -> E"+n.id+" [style=invisible,arrowhead=none,weight=4];");
			}
			else
			{
				n = null;
			}
		}
		out.println("}");
		for (Expr e: b)
		{
			for (Expr a: e.args)
				out.print("E"+a.id+" -> E"+e.id+" [color=green];");
			for (Expr a: e.locals)
				out.print("E"+a.id+" -> E"+e.id+" [color=green];");
			for (Expr a: e.scopes)
				out.print("E"+a.id+" -> E"+e.id+" [color=grey,style=dashed];");
			if (e.isPx())
			{
				for (Edge x: b.xsucc)
				{
					//out.print("E"+e.id+" -> E"+x.to.first().id+
					//		" [weight=2,style=dashed,ltail=cluster"+x.from+",lhead=cluster"+x.to+"];");
					out.print("E"+e.id+" -> E"+x.to.first().id+
							" [weight=2,style=dashed,color=red];");
				}
			}
		}
		for (Edge s: b.succ())
		{
			Expr e = b.last();
			int weight = s==b.last().succ[0] ? 4 : 2;
			//out.print("E"+e.id+" -> E"+s.to.first().id+
			//		" [weight="+weight+",ltail=cluster"+s.from+",lhead=cluster"+s.to+"];");
			out.print("E"+e.id+" -> E"+s.to.first().id+
					" [weight="+weight+"];");
		}
	}
	
	void dot(Edge e, PrintWriter out)
	{
		ArrayList<String> attrs = new ArrayList<String>();
		if (e.isThrowEdge())
		{
			attrs.add("style=dashed");
		}
		else
		{
			// TODO smarter edge classification
			if (e.isBackedge())
				attrs.add("tailport=w,headport=w");

			if (e.label == 0)
				attrs.add("weight=2");
			else
				attrs.add("taillabel=\""+e.label+"\"");
		}
		out.println(e.from + " -> " + e.to + " "+attrs+";");
	}

	void verboseStatus(String msg)
	{
		if ( verbose_mode )
			System.out.println(msg);
	}

	void verboseStatus(Object o)
	{
		if ( verbose_mode )
			System.out.println(o.toString());
	}
	
	class LocalVarState
	{
		/**
		 *  Simulated verifier frame state;
		 *  only locals are simulated.
		 */
		Typeref[] fs_out;
		
		/**
		 *  Expected types of input registers.
		 */
		Typeref[] fs_in;

		Typeref[] hard_coercions;

		/**
		 *  Live-Out variables are variables that are
		 *  used (without being redefined) in a successor
		 *  block.  Note: the relationship is transitive.
		 */
		private BitSet liveout = new BitSet();
		
		/** 
		 *  Variables killed in this block via explicit OP_kill insn. 
		 */
		private BitSet killed_vars = new BitSet();
		
		/**
		 *  Variables defined in this block.
		 *  @warn denormalized from defining_exprs
		 */
		private BitSet def = new BitSet();
		
		/**
		 *  Upwardly-exposed variables, read in this block
		 *  before any definition.  This means that their
		 *  value comes from predecessor blocks. 
		 */
		private BitSet ue_vars = new BitSet();
		
		/**
		 *  Variables read in block after their definition.  This means
		 *  the variable can't be cast at its definition site, although
		 *  it could if the read's type agreed with the successors'.
		 */
		private BitSet read_after_def = new BitSet();
		
		/**
		 *  Generating expresssions for variable definitions; these are
		 *  candidates for coercion before the variable's set, saving a
		 *  considerable amount of hassle down the CFG.
		 */
		private Map<Integer, Expr> generating_exprs = new HashMap<Integer, Expr>();
		
		/**
		 *  Set on backwards branch targets, catch
		 *  targets, etc -- the verifier will use
		 *  more conservative type assumptions.
		 */
		private boolean conservative_verifier_rules;
		
		private Method m;
		private Block b;
		
		/**
		 * Construct a LocalVariableState; compute its
		 * def, kill, and upwardly-exposed sets; and 
		 * compute its frame state.
		 * @param m - the Method under analysis.
		 * @param b - the Block to which this analysis applies.
		 * @param initial_frame_state - the previously computed frame state.
		 * @param is_scheduled_backedge 
		 */
		LocalVarState(Method m, Block b, Typeref[] initial_frame_state)
		{
			this.conservative_verifier_rules = b.is_backwards_branch_target;
			
			this.fs_in = new Typeref[initial_frame_state.length];

			if ( ! this.conservative_verifier_rules )
			{
				System.arraycopy(initial_frame_state, 0, this.fs_in, 0, initial_frame_state.length);
			}
			else
			{
				for ( int i = 0; i < m.local_count; i ++ )
				{
					this.fs_in[i] = initial_frame_state[i].nullable();
				}
				for ( int i = m.local_count + m.max_scope; i < this.fs_in.length; i++)
				{
					this.fs_in[i] = initial_frame_state[i].nullable();
				}
			}
			
			this.fs_out = new Typeref[initial_frame_state.length];
			System.arraycopy(this.fs_in, 0, this.fs_out, 0, this.fs_in.length);
			
			
			this.hard_coercions = new Typeref[initial_frame_state.length];
			
			this.m = m;
			this.b = b;
			
			//  Keep a shadow of the frame state so that it's only dumped when it changes.
			Typeref[] saved_fs = null;
			
			if ( verbose_mode )
			{
				verboseStatus(b);
				StringBuffer verbose_succ = new StringBuffer();
				verbose_succ.append("\tsucc: ");
				for ( Edge p: b.succ())
				{
					verbose_succ.append(p);
					verbose_succ.append(" ");
				}
				verboseStatus(verbose_succ);
				dumpFrameState(fs_out);
				saved_fs = new Typeref[initial_frame_state.length];
				System.arraycopy(fs_out, 0, saved_fs, 0, fs_out.length);
			}
			
			
			for ( Expr e: b.exprs)
			{	
				if ( verbose_mode )
					verboseStatus(formatExprAsAbc(e));

				switch(e.op)
				{
					case OP_getlocal0:
					case OP_getlocal1:
					case OP_getlocal2:
					case OP_getlocal3:
					{
						uses( e.op - OP_getlocal0);
						break;
					}
					case OP_getlocal:
					{
						uses(e.imm[0]);
						break;
					}
	
					case OP_setlocal0:
					case OP_setlocal1:
					case OP_setlocal2:
					case OP_setlocal3:
					{
						defines( e.op - OP_setlocal0, e );
						break;
					}
					
					case OP_setlocal:
					{
						defines(e.imm[0], e);
						break;
					}
					
					case OP_hasnext2:
					{
						uses(e.imm[0]);
						uses(e.imm[1]);
						
						expectsType(e.imm[0], ANY().ref);
						expectsType(e.imm[1], INT().ref);
						hard_coercions[e.imm[0]] = ANY().ref;
						
						defines(e.imm[0], e);
						break;
					}
	
					case OP_kill:
					{
						setKilled(e.imm[0]);
						break;
					}

					case OP_inclocal:
					case OP_inclocal_i:
					case OP_declocal:
					case OP_declocal_i:
					{
						uses(e.imm[0]);
						break;
					}
					
					case OP_getslot:
					case OP_setslot:
					{
						Expr stem = e.args[0];
						if ( stem.inLocal() )
						{
							expectsType(stem.imm[0], m.verifier_types.get(stem));
						}
						break;
					}

					case OP_nextvalue:
					case OP_nextname:
					{
						//  TODO: Anything to do here?
						break;
					}
						
					default:
						assert(!e.inLocal());
				}
				
				if ( verbose_mode )
				{
					for ( int i = 0; i < fs_out.length; i++ )
					{
						if ( saved_fs[i] != fs_out[i] )
						{
							dumpFrameState(fs_out);
							System.arraycopy(fs_out, 0, saved_fs, 0, fs_out.length);
							break;
						}
					}
				}
			}
		}
		
		private void expectsType(int i, Typeref expected_type)
		{
			//  If the variable's defined in this block,
			//  then it doesn't need coercion.
			if ( !( def.get(i) || this.fs_in[i].t.equals(expected_type.t) ) )
			{
				//  TODO: track these coerced locals with a new bit set
				//  and cross check to ensure they're all livein.
				verboseStatus("\texpectsType " + i + " " + expected_type);
				this.fs_in[i] = this.fs_out[i] = expected_type;
			}
		}

		/**
		 * @param reg - the local of interest.
		 * @return the live-in type the verifier will expect
		 *   to see on entry to the block. 
		 */
		public Typeref getInitialType(int reg)
		{
			return fs_in[reg];
		}
		
		/**
		 * @param reg - the local of interest.
		 * @return the type the local has at the end of this block.
		 */
		public Typeref getFinalType(int reg)
		{
			return fs_out[reg];
		}

		public BitSet getKilled()
		{
			return (BitSet)this.killed_vars.clone();
		}

		private boolean mergeLiveout(BitSet next_liveout) 
		{
			next_liveout.or(this.liveout);
			boolean result = !this.liveout.equals(next_liveout);
			
			if ( result )
			{
				this.liveout = next_liveout;
			}
			
			return result;
		}

		/**
		 *  Registers contributed by predecessor blocks. 
		 *  @return (liveout - def) + UE
		 */
		BitSet getLivein()
		{
			 BitSet result = (BitSet)this.liveout.clone();
			 result.andNot(this.def);
			 result.or(this.ue_vars);
			 return result;
		}
		
		/**
		 * Locals still active at the end of a block.
		 * @note changes as variables are killed.
		 * @return (UE + def) - killed
		 */
		BitSet getActiveVariables()
		{
			BitSet result = getLivein();
			result.or(this.def);
			
			if ( b.equals(m.entry.to))
			{
				//  Note parameters as active.
				for ( int i = 0; i < m.getParams().length; i++)
					result.set(i);
			}
			result.andNot(this.killed_vars);
			return result;
		}
		
		BitSet getLiveout()
		{
			return (BitSet)liveout.clone();
		}
		
		BitSet getDefined()
		{
			return (BitSet)this.def.clone();
		}
		
		private void uses(int varnum)
		{
			if ( !def.get(varnum) )
			{
				if ( !isAPriori(varnum) )
					ue_vars.set(varnum);
			}
			else
			{
				read_after_def.set(varnum);
			}
		}
		
		/**
		 * Is this local a routine parameter?
		 * If so, it is a priori present and 
		 * shouldn't be considered upwardly exposed.
		 * @param varnum - the local of interest.
		 * @return true if the local's a parameter.
		 */
		private boolean isAPriori(int varnum)
		{
			return (this.b.equals(this.m.entry.to) && varnum < this.m.getParams().length);
		}
		
		private void defines(int varnum, Expr generating_expr)
		{
			fs_out[varnum] = definingType(generating_expr);
			def.set(varnum);
			generating_exprs.put(varnum, generating_expr);
			
			killed_vars.clear(varnum);
			read_after_def.clear(varnum);
		}
		
		private Typeref definingType(Expr e)
		{
			Typeref result = null;

			if ( OP_hasnext2 == e.op )
			{
				result = ANY().ref;
			}
			else if ( OP_setlocal == e.op )
			{
				Expr value = e.args[0];

				if ( OP_getlocal == value.op )
				{
					result = fs_out[value.imm[0]];
				}
				else
				{
					result = verify_eval(this.m, value, m.verifier_types, null);
				}
			}
			else
			{
				assert(false);
			}

			assert ( result != null );
			return result;
		}
		
		public void setKilled(int varnum)
		{
			assert(!killed_vars.get(varnum));
			killed_vars.set(varnum);
			generating_exprs.remove(varnum);
		}
	}
	
	
	static class TypeConstraints implements Comparable
	{	
		Set<Integer> killregs = new TreeSet<Integer>();
		Map<Integer, Typeref> coercions = new HashMap<Integer, Typeref>();
		
		/**
		 *  Path to the destination block.
		 */
		Edge path;
		
		/**
		 * The original destination block.
		 * May be different than path.to if
		 * the path is split during fixup.
		 * @see compareTo
		 */
		Block dest_block;
		
		TypeConstraints(Edge path)
		{
			this.path = path;
			if ( path != null)
				this.dest_block = path.to;
		}
		
		void takeConstraintFrom(TypeConstraints tc, Integer r) 
		{
			if ( killregs.contains(r) )
			{
				assert(tc.killregs.contains(r));
				tc.killregs.remove(r);
			}
			else if ( coercions.containsKey(r) )
			{
				assert(tc.coercions.containsKey(r) && tc.coercions.get(r).t.isMachineCompatible(this.coercions.get(r).t));
				tc.coercions.remove(r);
			}
			else if ( tc.killregs.contains(r) )
			{
				this.killregs.add(r);
				tc.killregs.remove(r);
			}
			else if ( tc.coercions.containsKey(r) )
			{
				this.coercions.put(r, tc.coercions.get(r));
				tc.coercions.remove(r);
			}
			else
				throw new IllegalStateException("neither constraint set contains local " + r);
		}

		boolean agreesWith(TypeConstraints tc, Integer r) 
		{
			if ( this.killregs.contains(r))
				return tc.killregs.contains(r);
			else if ( this.coercions.containsKey(r))
				return tc.coercions.containsKey(r) && this.coercions.get(r).t.isMachineCompatible((tc.coercions.get(r).t));

			//  Local not found in this constraint set;
			//  by definition, the sets are in conflict
			//  with respect to this local.
			return false;
		}

		void addKill(int reg)
		{
			assert(!coercions.containsKey(reg));
			this.killregs.add(reg);
		}
		
		void addCoercion(int reg, Typeref ty)
		{
			assert(!coercions.containsKey(reg) && !killregs.contains(reg));
			coercions.put(reg, ty);
		}
		
		public boolean equals(Object o)
		{
			return 0 == compareTo(o);
		}

		public int compareTo(Object arg0)
		{
			if ( ! ( arg0 instanceof TypeConstraints ) )
				return -1;
			
			TypeConstraints other = (TypeConstraints) arg0;
			
			if ( dest_block.id != other.dest_block.id )
				return (dest_block.id > other.dest_block.id)? 1:-1;
			
			if ( killregs.size() > other.killregs.size())
				return 1;
			else if ( other.killregs.size() > this.killregs.size())
				return -1;
			
			if ( coercions.size() > other.coercions.size() )
				return 1;
			else if ( other.coercions.size() > this.coercions.size())
				return -1;
			
			
			for ( Integer x: this.killregs )
				if ( ! other.killregs.contains(x))
					return 1;
			for ( Integer y: other.killregs )
				if ( ! this.killregs.contains(y))
					return -1;
			
			for ( Integer r: this.coercions.keySet() )
			{
				Typeref this_ctype = coercions.get(r);
				Typeref other_ctype = other.coercions.get(r);
				
				if ( null == other_ctype )
					return 1;
				
				if ( !this_ctype.equals(other_ctype) )
					return ( this_ctype.hashCode() > other_ctype.hashCode() )? 1: -1;
			}
			
			for ( Integer o_r: other.coercions.keySet())
				if ( !this.coercions.containsKey(o_r))
					return -1;
			
			return 0;
		}
	}

	class Reader
	{
		int pos;
		byte[] abc;

		Reader(int pos, byte[] abc)
		{
			this.pos = pos;
			this.abc = abc;
		}

		Reader(Reader r)
		{
			this(r.pos, r.abc);
		}

		int readU8()
		{
			return 255 & abc[pos++];
		}

		int readU16()
		{
			return readU8() | readU8() << 8;
		}

		int readS24()
		{
			return readU16() | ((byte) readU8()) << 16;
		}

		int readU30()
		{
		    int result = readU8();
		    if (0==(result & 0x00000080))
		        return result;
		    result = result & 0x0000007f | readU8()<<7;
		    if (0==(result & 0x00004000))
		        return result;
		    result = result & 0x00003fff | readU8()<<14;
		    if (0==(result & 0x00200000))
		        return result;
		    result = result & 0x001fffff | readU8()<<21;
		    if (0==(result & 0x10000000))
		        return result;
		    return   result & 0x0fffffff | readU8()<<28;
		}
		
		double readDouble()
		{
			return Double.longBitsToDouble(readU16() | ((long)readU16())<<16 |
					((long)readU16())<<32 | ((long)readU16())<<48);
		}
	}
	
	class AbcWriter extends ByteArrayOutputStream
	{
		void rewind(int n)
		{
			super.count -= n;
		}
		void writeU16(int i)
		{
			write(i);
			write(i>>8);
		}
		
		void writeS24(int i)
		{
			writeU16(i);
			write(i>>16);
		}
		
		void write64(long i)
		{
			writeS24((int)i);
			writeS24((int)(i>>24));
			writeU16((int)(i>>48));
		}
		
		void writeU30(int v)
		{
			if (v < 128 && v >= 0)
			{
				write(v);
			}
			else if (v < 16384 && v >= 0)
			{
				write(v & 0x7F | 0x80);
				write(v >> 7);
			}
			else if (v < 2097152 && v >= 0)
			{
				write(v & 0x7F | 0x80);
				write(v >> 7 | 0x80);
				write(v >> 14);
			}
			else if (v < 268435456 && v >= 0)
			{
				write(v & 0x7F | 0x80);
				write(v >> 7 | 0x80);
				write(v >> 14 | 0x80);
				write(v >> 21);
			}
			else
			{
				write(v & 0x7F | 0x80);
				write(v >> 7 | 0x80);
				write(v >> 14 | 0x80);
				write(v >> 21 | 0x80);
				write(v >> 28);
			}
		}
		
		int sizeOfU30(int v)
		{
			if (v < 128 && v >= 0)
			{
				return 1;
			}
			else if (v < 16384 && v >= 0)
			{
				return 2;
			}
			else if (v < 2097152 && v >= 0)
			{
				return 3;
			}
			else if (v < 268435456 && v >= 0)
			{
				return 4;
			}
			else
			{
				return 5;
			}
		}
	}	
}
