Scala classfile manipulation library

changeset 9:eb3efd8e664e

Working on a dependency analysis tool and supporting code.

It doesn't really work at the moment.
author david@mel
date Wed Aug 13 09:54:58 2008 +0100 (2008-08-13)
parents 2c3fecea8d8d
children e7556829559e
files Rakefile src/attributes.scala src/classy.scala src/classy.scala.orig src/code/code.scala src/code/code.scala.broken src/tools/Dependencies.scala src/util/bytes.scala src/util/bytestring.scala
line diff
     1.1 --- a/Rakefile	Tue Jun 17 10:34:55 2008 +0100
     1.2 +++ b/Rakefile	Wed Aug 13 09:54:58 2008 +0100
     1.3 @@ -14,6 +14,10 @@
     1.4    sh "fsc -cp \"#{CLASSPATH.to_cp}\" -d build #{FileList["src/**/*.scala"]}"
     1.5  end
     1.6  
     1.7 +task :run => :compile do
     1.8 +  sh "scala -cp \"#{CLASSPATH.to_cp}\" classy.tools.DependencyFinder build"
     1.9 +end
    1.10 +
    1.11  task :shell => [:compile] do 
    1.12    sh "scala -cp \"#{CLASSPATH.to_cp}\" "
    1.13  end
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/attributes.scala	Wed Aug 13 09:54:58 2008 +0100
     2.3 @@ -0,0 +1,24 @@
     2.4 +package classy.attributes;
     2.5 +
     2.6 +import sbinary._;
     2.7 +  import Instances._;
     2.8 +  import Operations.binary;
     2.9 +  import generic.Generic;
    2.10 +
    2.11 +abstract class Attribute[T <: Attributed](name : String){
    2.12 +  type Value;
    2.13 +
    2.14 +  implicit def ValueIsBinary(implicit cp : ConstantPool) : Binary[Value];
    2.15 +
    2.16 +  def apply(att : T)(implicit pool : ConstantPool) : List[Value] = { 
    2.17 +    val nameIndex = pool.indexOfUTF(name);
    2.18 +    att.attributes.filter(att => att.nameIndex == nameIndex).map(_.content.to[Value]).toList
    2.19 +  }
    2.20 +}
    2.21 +
    2.22 +object SourceFileAttribute extends Attribute[classy.Class]("SourceFile"){
    2.23 +  type Value = String;
    2.24 +
    2.25 +  implicit def ValueIsBinary(implicit pool : ConstantPool) : Binary[Value] = 
    2.26 +    Generic.wrap[String, Char](pool.indexOfUTF(_), pool.getUTF(_))
    2.27 +}
     3.1 --- a/src/classy.scala	Tue Jun 17 10:34:55 2008 +0100
     3.2 +++ b/src/classy.scala	Wed Aug 13 09:54:58 2008 +0100
     3.3 @@ -5,8 +5,8 @@
     3.4  import generic.Generic._;
     3.5  import Operations._;
     3.6  import ConstantPool._;
     3.7 -import util.bytestring.ByteString;
     3.8 -import util.bytestring.ByteString._;
     3.9 +import util.bytes.ByteString;
    3.10 +import util.bytes.ByteString._;
    3.11  
    3.12  object Format{
    3.13    implicit def tablesAreBinary[T <: AnyRef](implicit bin : Binary[T]) : Binary[Table[T]] = new Binary[Table[T]]{
    3.14 @@ -33,45 +33,45 @@
    3.15      }
    3.16    }
    3.17  
    3.18 -  implicit val ConstantPoolInfoIsBinary : Binary[ConstantPool.Info] = new Binary[ConstantPool.Info]{
    3.19 +  implicit val ConstantPoolInfoIsBinary : Binary[ConstantPool.Index] = new Binary[ConstantPool.Index]{
    3.20      def reads(input : Input) = {
    3.21        import input.read;
    3.22        input.read[Byte] match {
    3.23 -        case TagClass => CPClass(read[Char]);
    3.24 -        case TagFieldRef => CPFieldRef(read[Char], read[Char])
    3.25 -        case TagMethodRef => CPMethodRef(read[Char], read[Char])
    3.26 -        case TagInterfaceMethodRef =>	CPInterfaceMethodRef(read[Char], read[Char])
    3.27 -        case TagString => CPString(read[Char])	
    3.28 -        case TagInteger => CPInteger(read[Int]);
    3.29 -        case TagFloat => CPFloat(read[Float]);
    3.30 -        case TagLong => CPLong(read[Long]);
    3.31 -        case TagDouble =>	CPDouble(read[Double]);
    3.32 -        case TagNameAndType => CPNameAndType(read[Char], read[Char]);
    3.33 -        case TagUtf8 => CPUtf8(read[String]);	
    3.34 +        case TagClass => ClassIndex(read[Char]);
    3.35 +        case TagFieldRef => FieldIndex(read[Char], read[Char])
    3.36 +        case TagMethodRef => MethodIndex(read[Char], read[Char])
    3.37 +        case TagInterfaceMethodRef =>	InterfaceMethodIndex(read[Char], read[Char])
    3.38 +        case TagString => StringIndex(read[Char])	
    3.39 +        case TagInteger => IntegerIndex(read[Int]);
    3.40 +        case TagFloat => FloatIndex(read[Float]);
    3.41 +        case TagLong => LongIndex(read[Long]);
    3.42 +        case TagDouble =>	DoubleIndex(read[Double]);
    3.43 +        case TagNameAndType => NameAndTypeIndex(read[Char], read[Char]);
    3.44 +        case TagUtf8 => Utf8(read[String]);	
    3.45        }
    3.46      }
    3.47  
    3.48 -    def writes(info : Info)(output : Output) = {
    3.49 +    def writes(info : Index)(output : Output) = {
    3.50        import output.write;
    3.51        info match {
    3.52 -        case CPClass(i) => write(TagClass); write(i);
    3.53 -        case CPFieldRef(i, j) => write(TagFieldRef); write(i); write(j);
    3.54 -        case CPMethodRef(i, j) => write(TagMethodRef); write(i); write(j);
    3.55 -        case CPInterfaceMethodRef(i, j) => write(TagInterfaceMethodRef); write(i); write(j);
    3.56 -        case CPString(i) => write(TagString); write(i);
    3.57 -        case CPInteger(i) => write(TagInteger); write(i);   
    3.58 -        case CPFloat(i) => write(TagFloat); write(i);
    3.59 -        case CPLong(i) => write(TagLong); write(i);
    3.60 -        case CPDouble(i) => write(TagDouble); write(i);
    3.61 -        case CPNameAndType(i, j) => write(TagNameAndType); write(i); write(j)
    3.62 -        case CPUtf8(str) => write(TagUtf8); write(str);
    3.63 +        case ClassIndex(i) => write(TagClass); write(i);
    3.64 +        case FieldIndex(i, j) => write(TagFieldRef); write(i); write(j);
    3.65 +        case MethodIndex(i, j) => write(TagMethodRef); write(i); write(j);
    3.66 +        case InterfaceMethodIndex(i, j) => write(TagInterfaceMethodRef); write(i); write(j);
    3.67 +        case StringIndex(i) => write(TagString); write(i);
    3.68 +        case IntegerIndex(i) => write(TagInteger); write(i);   
    3.69 +        case FloatIndex(i) => write(TagFloat); write(i);
    3.70 +        case LongIndex(i) => write(TagLong); write(i);
    3.71 +        case DoubleIndex(i) => write(TagDouble); write(i);
    3.72 +        case NameAndTypeIndex(i, j) => write(TagNameAndType); write(i); write(j)
    3.73 +        case Utf8(str) => write(TagUtf8); write(str);
    3.74        }   
    3.75      }
    3.76    }
    3.77  
    3.78    implicit val ConstantPoolIsBinary : Binary[ConstantPool] = new Binary[ConstantPool]{
    3.79      def reads(input : Input) = 
    3.80 -      new ConstantPool(new Table[ConstantPool.Info]((input.read[Char] - 1).toChar, x => input.read[ConstantPool.Info]))
    3.81 +      new ConstantPool(new Table[ConstantPool.Index]((input.read[Char] - 1).toChar, x => input.read[ConstantPool.Index]))
    3.82      
    3.83      def writes(pool : ConstantPool)(output : Output) = {
    3.84        import output.write;
    3.85 @@ -99,6 +99,19 @@
    3.86    implicit val FieldInfoIsBinary = new MemberBinary(FieldInfo);
    3.87    implicit val MethodInfoIsBinary = new MemberBinary(MethodInfo);
    3.88  
    3.89 +  implicit val ExceptionHandlerIsBinary : Binary[ExceptionHandler] = asProduct4(ExceptionHandler)(
    3.90 +    e => (e.startPC,
    3.91 +          e.endPC,
    3.92 +          e.handlerPC,
    3.93 +          e.catchType)) 
    3.94 +
    3.95 +  implicit val CodeIsBinary : Binary[Code] = asProduct5(Code)(
    3.96 +    c => (c.maxStack,
    3.97 +          c.maxLocals,
    3.98 +          c.code,
    3.99 +          c.exceptionHandlers,
   3.100 +          c.attributes))
   3.101 +
   3.102    implicit val ClassIsBinary : Binary[Class] = withStamp(0xCAFEBABE)(
   3.103      asProduct10(Class)((x : Class) => (x.minorVersion, 
   3.104                                        x.majorVersion, 
   3.105 @@ -121,7 +134,7 @@
   3.106              interfacesIndices : IndexTable,
   3.107                         fields : Table[FieldInfo],
   3.108                        methods : Table[MethodInfo],
   3.109 -                   attributes : Table[AttributeInfo]){
   3.110 +                   attributes : Table[AttributeInfo]) extends Attributed{
   3.111    val name = constantPool.nameOfClass(thisClass);
   3.112    val superName = constantPool.nameOfClass(superClass); 
   3.113    val interfaces = interfacesIndices.toList.map(constantPool.nameOfClass); 
   3.114 @@ -134,11 +147,13 @@
   3.115    def elements = body.elements; 
   3.116  }
   3.117  
   3.118 -class Table[T <: AnyRef](val length : Char, populate : Char => T) extends Iterable[T]{  
   3.119 +class Table[T <: AnyRef](val length : Char, populate : Char => T) extends Collection[T]{  
   3.120 +  def size : Int = length;
   3.121 +
   3.122    private val body : Array[AnyRef] = (0 until length).map(x => populate(x.toChar)).toArray;
   3.123  
   3.124    def apply(x : Int) : T = body(x).asInstanceOf[T]; 
   3.125 -  def apply(x : Char) : T = this(x)
   3.126 +  def apply(x : Char) : T = this(x : Int)
   3.127  
   3.128    def elements = new Iterator[T]{
   3.129      var i = -1;
   3.130 @@ -149,16 +164,36 @@
   3.131      def hasNext = i + 1 < body.length;
   3.132    }
   3.133  
   3.134 +  def zipWithIndex : Array[(T, Char)] = body.zipWithIndex.map({case (x, i) => (x.asInstanceOf[T], i.toChar)});
   3.135 +
   3.136    override def toString = body.mkString("Table(", ",", ")");
   3.137  }
   3.138  
   3.139 -case class ConstantPool(contents : Table[ConstantPool.Info]){
   3.140 +case class ConstantPool(contents : Table[ConstantPool.Index]){
   3.141 +  import ConstantPool._;
   3.142 +  
   3.143 +  lazy val reverseIndex = Map(contents.zipWithIndex :_*)
   3.144 +
   3.145 +  def indexOfUTF(string : String) = reverseIndex(ConstantPool.Utf8(string));
   3.146 +  def getUTF(index : Char) = {
   3.147 +    val ConstantPool.Utf8(str) = this(index);
   3.148 +    str 
   3.149 +  }
   3.150 +
   3.151    def apply(index : Char) = contents(index - 1);
   3.152 +  def reference(index : Char) : Reference = this(index) match {
   3.153 +    case ClassIndex(nameIndex) => { val Utf8(name) = this(nameIndex); ClassReference(name); }
   3.154 +    case MethodIndex(classIndex, nameAndTypeIndex) => MethodReference(reference(classIndex).asInstanceOf[ClassReference], reference(nameAndTypeIndex).asInstanceOf[NameAndTypeReference])      
   3.155 +    case InterfaceMethodIndex(classIndex, nameAndTypeIndex) => InterfaceMethodReference(reference(classIndex).asInstanceOf[ClassReference], reference(nameAndTypeIndex).asInstanceOf[NameAndTypeReference])      
   3.156 +    case FieldIndex(classIndex, nameAndTypeIndex) => FieldReference(reference(classIndex).asInstanceOf[ClassReference], reference(nameAndTypeIndex).asInstanceOf[NameAndTypeReference])      
   3.157 +    case StringIndex(index) => { val Utf8(name) = reference(index); StringReference(name) }
   3.158 +    case x => x.asInstanceOf[Reference]
   3.159 +  }
   3.160    def count = contents.length + 1.toChar;  
   3.161  
   3.162    def nameOfClass(index : Char) = {
   3.163 -    val CPClass(nameIndex) = this(index);
   3.164 -    val CPUtf8(name) = this(nameIndex);
   3.165 +    val ClassIndex(nameIndex) = this(index);
   3.166 +    val Utf8(name) = this(nameIndex);
   3.167      name;
   3.168    }
   3.169  }
   3.170 @@ -176,43 +211,63 @@
   3.171    val TagNameAndType =	12.toByte
   3.172    val TagUtf8 = 1.toByte
   3.173  
   3.174 -  abstract class Info;
   3.175 -  case class CPClass(nameIndex : Char)  extends Info{
   3.176 -    override def toString = "CPClass(" + nameIndex.toInt + ")";
   3.177 +  trait Index;
   3.178 +  trait Reference;
   3.179 +  case class ClassIndex(nameIndex : Char)  extends Index{
   3.180 +    override def toString = "ClassIndex(" + nameIndex.toInt + ")";
   3.181    } 
   3.182 -  case class CPMethodRef(classIndex : Char, nameAndTypeIndex : Char) extends Info{
   3.183 -    override def toString = "CPMethodRef(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   3.184 +  case class MethodIndex(classIndex : Char, nameAndTypeIndex : Char) extends Index{
   3.185 +    override def toString = "MethodIndex(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   3.186    } 
   3.187 -  case class CPFieldRef(classIndex : Char, nameAndTypeIndex : Char) extends Info{
   3.188 -    override def toString = "CPFieldRef(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   3.189 +  case class FieldIndex(classIndex : Char, nameAndTypeIndex : Char) extends Index{
   3.190 +    override def toString = "FieldIndex(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   3.191    } 
   3.192 -  case class CPInterfaceMethodRef(classIndex : Char, nameAndTypeIndex : Char) extends Info{
   3.193 -    override def toString = "CPInterfaceMethodRef(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   3.194 +  case class InterfaceMethodIndex(classIndex : Char, nameAndTypeIndex : Char) extends Index{
   3.195 +    override def toString = "InterfaceMethodIndex(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   3.196    }
   3.197 -  case class CPString(stringIndex : Char) extends Info{
   3.198 -    override def toString = "CPString(" + stringIndex.toInt + ")";
   3.199 +  case class StringIndex(stringIndex : Char) extends Index{
   3.200 +    override def toString = "StringIndex(" + stringIndex.toInt + ")";
   3.201    }
   3.202 -  case class CPInteger(value : Int) extends Info 
   3.203 -  case class CPFloat(value : Float) extends Info 
   3.204 -  case class CPLong(value : Long) extends Info 
   3.205 -  case class CPDouble(value : Double) extends Info 
   3.206 -  case class CPNameAndType(nameIndex : Char, descriptorIndex : Char) extends Info{
   3.207 -    override def toString = "CPNameAndType(" + nameIndex.toInt + ", " + descriptorIndex.toInt + ")";
   3.208 +  case class NameAndTypeIndex(nameIndex : Char, descriptorIndex : Char) extends Index{
   3.209 +    override def toString = "NameAndTypeIndex(" + nameIndex.toInt + ", " + descriptorIndex.toInt + ")";
   3.210    } 
   3.211 -  case class CPUtf8(value : String) extends Info 
   3.212 +  case class IntegerIndex(value : Int) extends Index with Reference; 
   3.213 +  case class FloatIndex(value : Float) extends Index with Reference; 
   3.214 +  case class LongIndex(value : Long) extends Index with Reference; 
   3.215 +  case class DoubleIndex(value : Double) extends Index with Reference; 
   3.216 +  case class Utf8(value : String) extends Index with Reference;
   3.217 +
   3.218 +  case class ClassReference(name : String) extends Reference;
   3.219 +  abstract class MemberReference extends Reference{
   3.220 +    val owner : ClassReference;
   3.221 +    val nameAndType : NameAndTypeReference;
   3.222 +  }
   3.223 +  case class MethodReference(owner : ClassReference, nameAndType : NameAndTypeReference) extends MemberReference;
   3.224 +  case class FieldReference(owner : ClassReference, nameAndType : NameAndTypeReference) extends MemberReference;
   3.225 +  case class InterfaceMethodReference(override val owner : ClassReference, override val nameAndType : NameAndTypeReference) extends MemberReference; 
   3.226 +  case class StringReference(value : String) extends Reference;
   3.227 +  case class IntegerReference(value : Int) extends Reference;
   3.228 +  case class FloatReference(value : Float) extends Reference;
   3.229 +  case class LongReference(value : Long) extends Reference;
   3.230 +  case class DoubleReference(value : Double) extends Reference;
   3.231 +  case class NameAndTypeReference(name : String, descriptor : String) extends Reference{
   3.232 +    lazy val jtype = types.Type.parseSignature(descriptor);
   3.233 +  }
   3.234  }
   3.235  
   3.236 -
   3.237  case class AttributeInfo(nameIndex : Char, content : ByteString); 
   3.238  
   3.239 -abstract class MemberInfo{
   3.240 +trait Attributed{
   3.241 +  val attributes : Table[AttributeInfo];
   3.242 +}
   3.243 +
   3.244 +abstract class MemberInfo extends Attributed{
   3.245    val accessFlags : Char;
   3.246    val nameIndex : Char;
   3.247    val descriptorIndex : Char;
   3.248    val attributes : Table[AttributeInfo];
   3.249  }
   3.250  
   3.251 -
   3.252  case class FieldInfo(accessFlags : Char, 
   3.253                         nameIndex : Char, 
   3.254                   descriptorIndex : Char, 
   3.255 @@ -223,3 +278,10 @@
   3.256                    descriptorIndex : Char, 
   3.257                         attributes : Table[AttributeInfo]) extends MemberInfo;
   3.258  
   3.259 +case class Code(maxStack : Char, 
   3.260 +               maxLocals : Char, 
   3.261 +                    code : ByteString, 
   3.262 +       exceptionHandlers : Table[ExceptionHandler],
   3.263 +              attributes : Table[AttributeInfo]) extends Attributed;
   3.264 +
   3.265 +case class ExceptionHandler(startPC : Char, endPC : Char, handlerPC : Char, catchType : Char);
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/classy.scala.orig	Wed Aug 13 09:54:58 2008 +0100
     4.3 @@ -0,0 +1,258 @@
     4.4 +package classy;
     4.5 +
     4.6 +import sbinary._;
     4.7 +import Instances._;
     4.8 +import generic.Generic._;
     4.9 +import Operations._;
    4.10 +import ConstantPool._;
    4.11 +import Format._;
    4.12 +
    4.13 +object Format{
    4.14 +  implicit val AttributeInfoIsBinary : Binary[AttributeInfo] = 
    4.15 +    asProduct2(AttributeInfo)((x : AttributeInfo) => (x.nameIndex, x.content));
    4.16 +
    4.17 +  class MemberBinary[T <: MemberInfo](con : (Char, Char, Char, Table[AttributeInfo]) => T)
    4.18 +      extends Binary[T]{
    4.19 +    def reads(in : Input) = con(in.read[Char], in.read[Char], in.read[Char], in.read[Table[AttributeInfo]]);    
    4.20 +
    4.21 +    def writes(t : T)(out : Output) = {
    4.22 +      out.write(t.accessFlags);
    4.23 +      out.write(t.nameIndex);
    4.24 +      out.write(t.descriptorIndex);
    4.25 +      out.write(t.attributes);
    4.26 +    }
    4.27 +  }
    4.28 +
    4.29 +
    4.30 +  implicit val FieldInfoIsBinary = new MemberBinary(FieldInfo);
    4.31 +  implicit val MethodInfoIsBinary = new MemberBinary(MethodInfo);
    4.32 +
    4.33 +  implicit val ClassIsBinary : Binary[Class] = withStamp(0xCAFEBABE)(
    4.34 +    asProduct10(Class)((x : Class) => (x.minorVersion, 
    4.35 +                                      x.majorVersion, 
    4.36 +                                      x.constantPool, 
    4.37 +                                      x.accessFlags,
    4.38 +                                      x.thisClass,
    4.39 +                                      x.superClass,
    4.40 +                                      x.interfacesIndices,
    4.41 +                                      x.fields,
    4.42 +                                      x.methods,
    4.43 +                                      x.attributes)))
    4.44 +
    4.45 +
    4.46 +  implicit val ConstantPoolInfoIsBinary : Binary[ConstantPool.Info] = new Binary[ConstantPool.Info]{
    4.47 +    def reads(input : Input) = {
    4.48 +      import input.read;
    4.49 +      input.read[Byte] match {
    4.50 +        case TagClass => CPClass(read[Char]);
    4.51 +        case TagFieldRef => CPFieldRef(read[Char], read[Char])
    4.52 +        case TagMethodRef => CPMethodRef(read[Char], read[Char])
    4.53 +        case TagInterfaceMethodRef =>	CPInterfaceMethodRef(read[Char], read[Char])
    4.54 +        case TagString => CPString(read[Char])	
    4.55 +        case TagInteger => CPInteger(read[Int]);
    4.56 +        case TagFloat => CPFloat(read[Float]);
    4.57 +        case TagLong => CPLong(read[Long]);
    4.58 +        case TagDouble =>	CPDouble(read[Double]);
    4.59 +        case TagNameAndType => CPNameAndType(read[Char], read[Char]);
    4.60 +        case TagUtf8 => CPUtf8(read[String]);	
    4.61 +      }
    4.62 +    }
    4.63 +
    4.64 +    def writes(info : Info)(output : Output) = {
    4.65 +      import output.write;
    4.66 +      info match {
    4.67 +        case CPClass(i) => write(TagClass); write(i);
    4.68 +        case CPFieldRef(i, j) => write(TagFieldRef); write(i); write(j);
    4.69 +        case CPMethodRef(i, j) => write(TagMethodRef); write(i); write(j);
    4.70 +        case CPInterfaceMethodRef(i, j) => write(TagInterfaceMethodRef); write(i); write(j);
    4.71 +        case CPString(i) => write(TagString); write(i);
    4.72 +        case CPInteger(i) => write(TagInteger); write(i);   
    4.73 +        case CPFloat(i) => write(TagFloat); write(i);
    4.74 +        case CPLong(i) => write(TagLong); write(i);
    4.75 +        case CPDouble(i) => write(TagDouble); write(i);
    4.76 +        case CPNameAndType(i, j) => write(TagNameAndType); write(i); write(j)
    4.77 +        case CPUtf8(str) => write(TagUtf8); write(str);
    4.78 +      }   
    4.79 +    }
    4.80 +  }
    4.81 +
    4.82 +  implicit val ConstantPoolIsBinary : Binary[ConstantPool] = new Binary[ConstantPool]{
    4.83 +    def reads(input : Input) = 
    4.84 +      new ConstantPool(new Table[ConstantPool.Info]((input.read[Char] - 1).toChar, x => input.read[ConstantPool.Info]))
    4.85 +    
    4.86 +    def writes(pool : ConstantPool)(output : Output) = {
    4.87 +      import output.write;
    4.88 +      write(pool.count);
    4.89 +      pool.contents.foreach(write);
    4.90 +    }       
    4.91 +  }
    4.92 +
    4.93 +  implicit def tablesAreBinary[T <: AnyRef](implicit bin : Binary[T]) : Binary[Table[T]] = new Binary[Table[T]]{
    4.94 +    def reads(input : Input) = {
    4.95 +      val length = input.read[Char]
    4.96 +      new Table[T](length, (i : Char) => input.read[T]);
    4.97 +    }
    4.98 +
    4.99 +    def writes(table : Table[T])(output : Output){
   4.100 +      output.write(table.length);
   4.101 +      table.foreach(output.write(_ : T));
   4.102 +    }
   4.103 +  }
   4.104 +
   4.105 +  implicit val IndexTableIsBinary : Binary[IndexTable] = new Binary[IndexTable]{
   4.106 +    def reads(input : Input) = {
   4.107 +      val length = input.read[Char]
   4.108 +      new IndexTable(length, (i : Char) => input.read[Char]);
   4.109 +    }
   4.110 +
   4.111 +    def writes(table : IndexTable)(output : Output){
   4.112 +      output.write(table.length);
   4.113 +      table.foreach(output.write(_ : Char));
   4.114 +    }
   4.115 +  }
   4.116 +
   4.117 +}
   4.118 +
   4.119 +case class Class(minorVersion : Char, 
   4.120 +                 majorVersion : Char, 
   4.121 +                 constantPool : ConstantPool,
   4.122 +                  accessFlags : Char,
   4.123 +                    thisClass : Char,
   4.124 +                   superClass : Char,
   4.125 +            interfacesIndices : IndexTable,
   4.126 +                       fields : Table[FieldInfo],
   4.127 +                      methods : Table[MethodInfo],
   4.128 +                   attributes : Table[AttributeInfo]){
   4.129 +  val name = constantPool.nameOfClass(thisClass);
   4.130 +  val superName = constantPool.nameOfClass(superClass); 
   4.131 +  val interfaces = interfacesIndices.toList.map(constantPool.nameOfClass); 
   4.132 +}
   4.133 +
   4.134 +abstract class MemberInfo{
   4.135 +  val accessFlags : Char;
   4.136 +  val nameIndex : Char;
   4.137 +  val descriptorIndex : Char;
   4.138 +  val attributes : Table[AttributeInfo];
   4.139 +}
   4.140 +
   4.141 +
   4.142 +case class FieldInfo(accessFlags : Char, 
   4.143 +                       nameIndex : Char, 
   4.144 +                 descriptorIndex : Char, 
   4.145 +                      attributes : Table[AttributeInfo]) extends MemberInfo;
   4.146 + 
   4.147 +case class MethodInfo(accessFlags : Char, 
   4.148 +                        nameIndex : Char, 
   4.149 +                  descriptorIndex : Char, 
   4.150 +                       attributes : Table[AttributeInfo]) extends MemberInfo;
   4.151 +
   4.152 +case class AttributeInfo(nameIndex : Char, content : Array[Byte]){
   4.153 +} 
   4.154 +
   4.155 +trait Attributed{
   4.156 +  val attributes : Table[AttributeInfo];
   4.157 +  private val cache = new scala.collection.mutable.HashMap[Attribute[T] forSome { type T }, Any];
   4.158 +
   4.159 +  def get[T](attribute : Attribute[T]) : Option[T] =  
   4.160 +    cache.get(attribute) match {
   4.161 +      case (x : Some[T]) => x;
   4.162 +      case None => attributes.find(at => at.nameIndex == attribute.index) match {
   4.163 +        case Some(at) => {
   4.164 +          import attribute.binary;
   4.165 +          val t = fromByteArray[T](at.content);
   4.166 +          cache(attribute) = t;
   4.167 +          Some(t);
   4.168 +        }
   4.169 +        case None => None;
   4.170 +      }
   4.171 +    }
   4.172 +}
   4.173 +
   4.174 +class Attribute[Attr](val index : Char)(implicit val binary : Binary[Attr]){
   4.175 +} 
   4.176 +
   4.177 +case class ConstantPool(contents : Table[ConstantPool.Info]){
   4.178 +  def apply(index : Char) = contents(index - 1);
   4.179 +  def count = contents.length + 1.toChar;  
   4.180 +
   4.181 +  def nameOfClass(index : Char) = {
   4.182 +    val CPClass(nameIndex) = this(index);
   4.183 +    val CPUtf8(name) = this(nameIndex);
   4.184 +    name;
   4.185 +  }
   4.186 +
   4.187 +  lazy val reverseIndex = Map[ConstantPool.Info, Char](contents.zipWithIndex.toArray :_*);
   4.188 +    
   4.189 +  def indexOf (cp : ConstantPool.Info) : Char = reverseIndex.getOrElse(cp, 0);
   4.190 +  def indexOfUtf (str : String) : Char = indexOf(CPUtf8(str));   
   4.191 +}
   4.192 +
   4.193 +object ConstantPool{
   4.194 +  val TagClass = 7.toByte
   4.195 +  val TagFieldRef =	9.toByte
   4.196 +  val TagMethodRef =	10.toByte
   4.197 +  val TagInterfaceMethodRef =	11.toByte
   4.198 +  val TagString =	8.toByte
   4.199 +  val TagInteger =	3.toByte
   4.200 +  val TagFloat =	4.toByte
   4.201 +  val TagLong =	5.toByte
   4.202 +  val TagDouble =	6.toByte
   4.203 +  val TagNameAndType =	12.toByte
   4.204 +  val TagUtf8 = 1.toByte
   4.205 +
   4.206 +  abstract class Info;
   4.207 +  case class CPClass(nameIndex : Char)  extends Info{
   4.208 +    override def toString = "CPClass(" + nameIndex.toInt + ")";
   4.209 +  } 
   4.210 +  case class CPMethodRef(classIndex : Char, nameAndTypeIndex : Char) extends Info{
   4.211 +    override def toString = "CPMethodRef(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   4.212 +  } 
   4.213 +  case class CPFieldRef(classIndex : Char, nameAndTypeIndex : Char) extends Info{
   4.214 +    override def toString = "CPFieldRef(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   4.215 +  } 
   4.216 +  case class CPInterfaceMethodRef(classIndex : Char, nameAndTypeIndex : Char) extends Info{
   4.217 +    override def toString = "CPInterfaceMethodRef(" + classIndex.toInt + ", " + nameAndTypeIndex.toInt + ")";
   4.218 +  }
   4.219 +  case class CPString(stringIndex : Char) extends Info{
   4.220 +    override def toString = "CPString(" + stringIndex.toInt + ")";
   4.221 +  }
   4.222 +  case class CPInteger(value : Int) extends Info 
   4.223 +  case class CPFloat(value : Float) extends Info 
   4.224 +  case class CPLong(value : Long) extends Info 
   4.225 +  case class CPDouble(value : Double) extends Info 
   4.226 +  case class CPNameAndType(nameIndex : Char, descriptorIndex : Char) extends Info{
   4.227 +    override def toString = "CPNameAndType(" + nameIndex.toInt + ", " + descriptorIndex.toInt + ")";
   4.228 +  } 
   4.229 +  case class CPUtf8(value : String) extends Info 
   4.230 +}
   4.231 +
   4.232 +
   4.233 +class IndexTable(val length : Char, populate : Char => Char) extends Iterable[Char]{
   4.234 +  private val body : Array[Char] = (0 until length).map(x => populate(x.toChar)).toArray
   4.235 +  def apply(x : Int) = body(x);
   4.236 +
   4.237 +  def elements = body.elements; 
   4.238 +  override def toString = mkString("Table(", ",", ")");
   4.239 +}
   4.240 +
   4.241 +class Table[T <: AnyRef](val length : Char, populate : Char => T) extends Collection[T]{  
   4.242 +  def size : Int = length;
   4.243 +  private val body : Array[AnyRef] = (0 until length).map(x => populate(x.toChar)).toArray;;
   4.244 +
   4.245 +  def apply(x : Int) : T = body(x).asInstanceOf[T]; 
   4.246 +  def apply(x : Char) : T = this(x)
   4.247 +
   4.248 +  def elements = new Iterator[T]{
   4.249 +    var i = -1;
   4.250 +    def next = {
   4.251 +      i += 1; body(i).asInstanceOf[T];
   4.252 +    }
   4.253 +    
   4.254 +    def hasNext = i + 1 < body.length;
   4.255 +  }
   4.256 +
   4.257 +  def zipWithIndex = new Table[(T, Char)](length, x => (this(x), x));
   4.258 +
   4.259 +  override def toString = body.mkString("Table(", ",", ")");
   4.260 +}
   4.261 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/code/code.scala	Wed Aug 13 09:54:58 2008 +0100
     5.3 @@ -0,0 +1,226 @@
     5.4 +package classy.code; 
     5.5 +
     5.6 +import classy.util.bytes._
     5.7 +import opcodes._;
     5.8 +import types._;
     5.9 +import ConstantPool._;
    5.10 +
    5.11 +class CodeIterator(val code : ByteString, pool : ConstantPool, var pc : Int) {
    5.12 +  val codeArray = new ByteBuffer(code);
    5.13 +  protected var opcode:Opcode = null
    5.14 +  protected var padding:Array[Int] = Array(0, 3, 2, 1)
    5.15 +
    5.16 +  setOpcode()
    5.17 +
    5.18 +  def getPC():Int = pc
    5.19 +
    5.20 +  protected def setOpcode():Unit = {
    5.21 +    opcode = if (isValid()) Opcode.Opcodes(codeArray.getU1(pc)) else null
    5.22 +  }
    5.23 +
    5.24 +  def getOpcode():Opcode = {
    5.25 +    opcode
    5.26 +  }
    5.27 +
    5.28 +  def moveTo(pc:Int):Unit = {
    5.29 +    this.pc = pc
    5.30 +
    5.31 +    setOpcode()
    5.32 +  }
    5.33 +
    5.34 +  def isValid() : boolean = pc < codeArray.size
    5.35 +
    5.36 +  def moveToNext(){
    5.37 +    moveTo(pc + getInstructionSize())
    5.38 +  }
    5.39 +
    5.40 +  def moveToSuccessor(succ:Int) {
    5.41 +    moveTo(getSuccessorPC(succ))
    5.42 +  }
    5.43 +
    5.44 +  def moveRelatively(offset:Int){
    5.45 +    moveTo(pc + offset)
    5.46 +  }
    5.47 +
    5.48 +  def getInstructionSize():Int = {
    5.49 +    if (opcode.size != Opcode.Unknown) {
    5.50 +      opcode.size
    5.51 +    } else 
    5.52 +      if (opcode == Opcode.Tableswitch) {
    5.53 +        var lowOffset:Int = 1 + pad4(pc + 1) + 4
    5.54 +
    5.55 +        var low : Int = codeArray.getS4(pc + lowOffset)
    5.56 +
    5.57 +        var high : Int = codeArray.getS4(pc + lowOffset + 4)
    5.58 +
    5.59 +        lowOffset + 8 + 4 * (high - low + 1)
    5.60 +      } else 
    5.61 +        if (opcode == Opcode.Lookupswitch) {
    5.62 +          var npairsOffset:Int = 1 + pad4(pc + 1) + 4
    5.63 +          var npairs:Int = codeArray.getS4(pc + npairsOffset)
    5.64 +          npairsOffset + 4 + 8 * npairs
    5.65 +        } else 
    5.66 +          if (opcode == Opcode.Wide) {
    5.67 +            if (codeArray.getU1(pc + 1) == Opcode.Iinc.code) 6
    5.68 +            else 4
    5.69 +          } else error("Unknown size for instruction " + opcode)
    5.70 +  }
    5.71 +
    5.72 +  def getSuccessorCount():Int = {
    5.73 +    if (opcode.successorCount != Opcode.Unknown) {
    5.74 +      opcode.successorCount
    5.75 +    } else 
    5.76 +      if (opcode == Opcode.Tableswitch) {
    5.77 +        var lowPos:Int = pc + 1 + pad4(pc + 1) + 4
    5.78 +
    5.79 +        1 + codeArray.getS4(lowPos + 4) - codeArray.getS4(lowPos) + 1
    5.80 +      } else 
    5.81 +        if (opcode == Opcode.Lookupswitch) {
    5.82 +          var npairsPos:Int = pc + 1 + pad4(pc + 1) + 4
    5.83 +
    5.84 +          1 + codeArray.getS4(npairsPos)
    5.85 +        } else 
    5.86 +          throw new Error("Unknown successors for instruction " + opcode)
    5.87 +  }
    5.88 +
    5.89 +  def getSuccessorPC(index:Int):Int = {
    5.90 +    assert (index >= 0 && index < getSuccessorCount())
    5.91 +
    5.92 +    opcode.jumpKind match  {
    5.93 +      case Opcode.JmpNext => pc + getInstructionSize()
    5.94 +      case Opcode.JmpAlwaysS2Offset => pc + codeArray.getS2(pc + 1)
    5.95 +      case Opcode.JmpAlwaysS4Offset => pc + codeArray.getS4(pc + 1)
    5.96 +      case Opcode.JmpMaybeS2Offset => 
    5.97 +        if (index == 0) pc + getInstructionSize()
    5.98 +        else pc + codeArray.getS2(pc + 1)
    5.99 +
   5.100 +      case Opcode.JmpTable => {
   5.101 +          var defaultPos:Int = pc + 1 + pad4(pc + 1)
   5.102 +
   5.103 +          if (index == 0) pc + codeArray.getS4(defaultPos)
   5.104 +          else pc + codeArray.getS4(defaultPos + 3 * 4 + 4 * (index - 1))
   5.105 +        }
   5.106 +
   5.107 +      case Opcode.JmpLookup => {
   5.108 +          var defaultPos:Int = pc + 1 + pad4(pc + 1)
   5.109 +
   5.110 +          if (index == 0) pc + codeArray.getS4(defaultPos)
   5.111 +          else pc + codeArray.getS4(defaultPos + 2 * 4 + 4 + 8 * (index - 1))
   5.112 +        }
   5.113 +    }
   5.114 +  }
   5.115 +
   5.116 +  def getProducedDataSize():Int = {
   5.117 +    if (opcode.producedDataTypes == Opcode.UnknownType) {
   5.118 +      opcode.code match  {
   5.119 +        case Opcode.Ldc.code | Opcode.LdcW.code | Opcode.Baload.code =>  1
   5.120 +        case Opcode.Ldc2W.code | Opcode.Dup.code | Opcode.Swap.code =>  2
   5.121 +        case Opcode.DupX1.code => 3
   5.122 +        case Opcode.DupX2.code | Opcode.Dup2.code => 4
   5.123 +        case Opcode.Dup2X1.code => 5
   5.124 +        case Opcode.Dup2X2.code => 6
   5.125 +        case Opcode.Getstatic.code | Opcode.Getfield.code => {
   5.126 +          var entry : MemberReference = pool.reference(codeArray.getU2(pc + 1)).asInstanceOf[MemberReference] 
   5.127 +          entry.nameAndType.jtype.size
   5.128 +        }
   5.129 +
   5.130 +        case Opcode.Wide.code => {
   5.131 +            var op : Int = codeArray.getU1(pc + 1)
   5.132 +
   5.133 +            if (op >= Opcode.Iload.code && op <= Opcode.Aload.code) {
   5.134 +              var opcode2:Opcode = Opcode.Opcodes(op)
   5.135 +
   5.136 +              Type.getTotalSize(opcode2.producedDataTypes)
   5.137 +            } else 
   5.138 +              if (op >= Opcode.Istore.code && op <= Opcode.Astore.code) 
   5.139 +                0
   5.140 +              else 
   5.141 +                0
   5.142 +          }
   5.143 +
   5.144 +        case _ => 
   5.145 +          throw new Error(opcode.toString())
   5.146 +
   5.147 +      }
   5.148 +    } else 
   5.149 +      Type.getTotalSize(opcode.producedDataTypes)
   5.150 +
   5.151 +
   5.152 +  }
   5.153 +
   5.154 +  def getConsumedDataSize():Int = {
   5.155 +    if (opcode.consumedDataTypes != Opcode.UnknownType) 
   5.156 +      Type.getTotalSize(opcode.consumedDataTypes)
   5.157 +    else {
   5.158 +      opcode.code match  {
   5.159 +        case Opcode.Pop.code | Opcode.Dup.code =>  1
   5.160 +        case Opcode.Pop2.code | Opcode.Swap.code | Opcode.DupX1.code | Opcode.Dup2.code => 2
   5.161 +        case Opcode.DupX2.code | Opcode.Dup2X1.code => 3
   5.162 +        case Opcode.Dup2X2.code => 4
   5.163 +        case Opcode.Putstatic.code | Opcode.Putfield.code =>  {
   5.164 +          (pool.reference(codeArray.getU2(pc + 1)).asInstanceOf[MemberReference]).nameAndType.jtype.size;
   5.165 +        }
   5.166 +
   5.167 +        case Opcode.Invokevirtual.code | Opcode.Invokespecial.code | Opcode.Invokestatic.code | Opcode.Invokeinterface.code => {
   5.168 +            var entry : MemberReference = pool.reference(codeArray.getU2(pc + 1)).asInstanceOf[MemberReference] 
   5.169 +            var tp:MethodType = entry.nameAndType.jtype.asInstanceOf[MethodType] 
   5.170 +            tp.argsSize + (if (opcode == Opcode.Invokestatic) 0 else 1)
   5.171 +          }
   5.172 +
   5.173 +        case Opcode.Wide.code => {
   5.174 +            var op:Int = codeArray.getU1(pc + 1)
   5.175 +
   5.176 +            if (op >= Opcode.Iload.code && op <= Opcode.Aload.code)  0
   5.177 +            else 
   5.178 +              if (op >= Opcode.Istore.code && op <= Opcode.Astore.code) {
   5.179 +                var opcode2:Opcode = Opcode.Opcodes(op)
   5.180 +
   5.181 +                Type.getTotalSize(opcode2.consumedDataTypes)
   5.182 +              } else 0
   5.183 +          }
   5.184 +
   5.185 +        case Opcode.Multianewarray.code => 
   5.186 +          codeArray.getU1(pc + 3)
   5.187 +
   5.188 +        case _ => 
   5.189 +          throw new Error(opcode.toString())
   5.190 +
   5.191 +      }
   5.192 +    }
   5.193 +
   5.194 +  }
   5.195 +
   5.196 +  def producedDataTypesNumber():Int = {
   5.197 +    if (opcode.producedDataTypes != Opcode.UnknownType) 
   5.198 +      opcode.producedDataTypes.length
   5.199 +    else {
   5.200 +      opcode.code match  {
   5.201 +        case Opcode.Ldc.code | Opcode.LdcW.code | Opcode.Ldc2W.code | Opcode.Baload.code | Opcode.Getstatic.code | Opcode.Getfield.code => 
   5.202 +          1
   5.203 +
   5.204 +        case Opcode.Dup.code | Opcode.Swap.code => 
   5.205 +          2
   5.206 +
   5.207 +        case Opcode.DupX1.code => 
   5.208 +          3
   5.209 +
   5.210 +        case Opcode.Wide.code => 
   5.211 +          {
   5.212 +            var op:Int = codeArray.getU1(pc + 1)
   5.213 +
   5.214 +            if (op >= Opcode.Iload.code && op <= Opcode.Aload.code) 
   5.215 +              1
   5.216 +            else 
   5.217 +              if (op >= Opcode.Istore.code && op <= Opcode.Astore.code) 
   5.218 +                0
   5.219 +              else 
   5.220 +                0
   5.221 +          }
   5.222 +      }
   5.223 +    }
   5.224 +  }
   5.225 +
   5.226 +  protected def pad4(value:Int):Int = {
   5.227 +    padding(value % 4)
   5.228 +  }
   5.229 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/code/code.scala.broken	Wed Aug 13 09:54:58 2008 +0100
     6.3 @@ -0,0 +1,1208 @@
     6.4 +package classy.code; 
     6.5 +
     6.6 +import java.util._
     6.7 +import java.io._
     6.8 +import classy.util._
     6.9 +import opcodes._
    6.10 +import types._;
    6.11 +import Code._;
    6.12 +
    6.13 +class Code(val codeArray : ByteBuffer) {
    6.14 +  val exceptionHandlers : LinkedList[ExceptionHandler] = new LinkedList
    6.15 +  val offsetToPatch : ArrayList[OffsetToPatch] = new ArrayList
    6.16 +  var maxStackSize:Int = UNKNOWN_STACK_SIZE
    6.17 +  var stackProduction : Array[Int] = null
    6.18 +  var stackSizes : Array[Int] = null
    6.19 +
    6.20 +
    6.21 +  val attributes = new LinkedList[JAttribute]
    6.22 +  var lineNumbers : Array[Int] = null
    6.23 +
    6.24 +  def getPC:Int = codeArray.size
    6.25 +  def size:Int = codeArray.size
    6.26 +
    6.27 +  def getMaxStackSize:Int = {
    6.28 +    if (maxStackSize == UNKNOWN_STACK_SIZE) 
    6.29 +      maxStackSize = computeMaxStackSize
    6.30 +
    6.31 +    maxStackSize
    6.32 +  }
    6.33 +
    6.34 +  def addAttribute(attr:JAttribute){
    6.35 +    attributes.add(attr)
    6.36 +  }
    6.37 +
    6.38 +  def emit(opcode:Opcode){
    6.39 +    setStackProduction(getPC, opcode)
    6.40 +    codeArray.addU1(opcode.code)
    6.41 +  }
    6.42 +
    6.43 +  def nop = emit(Opcode.Nop )
    6.44 +  def aconstNull = emit(Opcode.AconstNull )
    6.45 +  def iconstM1 = emit(Opcode.IconstM1 )
    6.46 +  def iconst0 = emit(Opcode.Iconst0 )
    6.47 +  def iconst1 = emit(Opcode.Iconst1 )
    6.48 +  def iconst2 = emit(Opcode.Iconst2 )
    6.49 +  def iconst3 = emit(Opcode.Iconst3 )
    6.50 +  def iconst4 = emit(Opcode.Iconst4 )
    6.51 +  def iconst5 = emit(Opcode.Iconst5 )
    6.52 +  def lconst0 = emit(Opcode.Lconst0 )
    6.53 +  def lconst1 = emit(Opcode.Lconst1 )
    6.54 +  def fconst0 = emit(Opcode.Fconst0 )
    6.55 +  def fconst1 = emit(Opcode.Fconst1 )
    6.56 +  def fconst2 = emit(Opcode.Fconst2 )
    6.57 +  def dconst0 = emit(Opcode.Dconst0 )
    6.58 +  def dconst1 = emit(Opcode.Dconst1 )
    6.59 +  def bipush(b:Int) = emitU1(Opcode.Bipush , b)
    6.60 +  def sipush(s:Int) = emitU2(Opcode.Sipush , s)
    6.61 +  def push(value:boolean) : Unit = push(if (value) 1 else 0)
    6.62 +  def push(value:byte) : Unit = bipush(value)
    6.63 +  def push(value:Short) : Unit = sipush(value)
    6.64 +  def push(value:Char) : Unit = push(value.toInt)
    6.65 +  def push(value:Int){
    6.66 +    value match  {
    6.67 +      case -1 => iconstM1
    6.68 +      case 0 => iconst0
    6.69 +      case 1 => iconst1
    6.70 +      case 2 => iconst2
    6.71 +      case 3 => iconst3
    6.72 +      case 4 => iconst4
    6.73 +      case 5 => iconst5
    6.74 +      case _ => pushIndex(constantPool.addInteger(value))
    6.75 +    }
    6.76 +  }
    6.77 +
    6.78 +  def push(value:Long){
    6.79 +    if (value == 0L) 
    6.80 +      lconst0
    6.81 +    else 
    6.82 +      if (value == 1L) 
    6.83 +        lconst1
    6.84 +      else 
    6.85 +        ldc2w(value)
    6.86 +  }
    6.87 +
    6.88 +  def push(value:float){
    6.89 +    if (value == 0.0F) 
    6.90 +      fconst0
    6.91 +    else 
    6.92 +      if (value == 1.0F) 
    6.93 +        fconst1
    6.94 +      else 
    6.95 +        if (value == 2.0F) 
    6.96 +          fconst2
    6.97 +        else 
    6.98 +          pushIndex(constantPool.addFloat(value))
    6.99 +  }
   6.100 +
   6.101 +  def push(value:Double){
   6.102 +    if (value == 0.0) 
   6.103 +      dconst0
   6.104 +    else 
   6.105 +      if (value == 1.0) 
   6.106 +        dconst1
   6.107 +      else 
   6.108 +        ldc2w(value)
   6.109 +  }
   6.110 +
   6.111 +  def push(s:String) = pushIndex(constantPool.addString(s))
   6.112 +  def push(jtype:ReferenceType){
   6.113 +    assert (owner.owner.major >= 49)
   6.114 +    pushIndex(constantPool.addClass(jtype.descriptor))
   6.115 +  }
   6.116 +
   6.117 +  def pushIndex(index:Int){
   6.118 +    if (index <= 0xFF) 
   6.119 +      emitU1(Opcode.Ldc , index)
   6.120 +    else 
   6.121 +      emitU2(Opcode.LdcW , index)
   6.122 +  }
   6.123 +  def ldc(value:Int) = emitU1(Opcode.Ldc , constantPool.addInteger(value))
   6.124 +  def ldc(value:float) = emitU1(Opcode.Ldc , constantPool.addFloat(value))
   6.125 +  def ldc(value:String) = emitU1(Opcode.Ldc , constantPool.addString(value))
   6.126 +  def ldcw(value:Int) = emitU1(Opcode.LdcW , constantPool.addInteger(value))
   6.127 +  def ldcw(value:float) = emitU1(Opcode.LdcW , constantPool.addFloat(value))
   6.128 +  def ldcw(value:String) = emitU1(Opcode.LdcW , constantPool.addString(value))
   6.129 +  def ldc2w(value:Long) = emitU2(Opcode.Ldc2W , constantPool.addLong(value))
   6.130 +  def ldc2w(value:Double) = emitU2(Opcode.Ldc2W , constantPool.addDouble(value))
   6.131 +  def iload(index:Int) = emitU1(Opcode.Iload , index)
   6.132 +  def lload(index:Int) = emitU1(Opcode.Lload , index)
   6.133 +  def fload(index:Int) = emitU1(Opcode.Fload , index)
   6.134 +  def dload(index:Int) = emitU1(Opcode.Dload , index)
   6.135 +  def aload(index:Int) = emitU1(Opcode.Aload , index)
   6.136 +  def iload0 = emit(Opcode.Iload0 )
   6.137 +  def iload1 = emit(Opcode.Iload1 )
   6.138 +  def iload2 = emit(Opcode.Iload2 )
   6.139 +  def iload3 = emit(Opcode.Iload3 )
   6.140 +  def lload0 = emit(Opcode.Lload0 )
   6.141 +  def lload1 = emit(Opcode.Lload1 )
   6.142 +  def lload2 = emit(Opcode.Lload2 )
   6.143 +  def lload3 = emit(Opcode.Lload3 )
   6.144 +  def fload0 = emit(Opcode.Fload0 )
   6.145 +  def fload1 = emit(Opcode.Fload1 )
   6.146 +  def fload2 = emit(Opcode.Fload2 )
   6.147 +  def fload3 = emit(Opcode.Fload3 )
   6.148 +  def dload0 = emit(Opcode.Dload0 )
   6.149 +  def dload1 = emit(Opcode.Dload1 )
   6.150 +  def dload2 = emit(Opcode.Dload2 )
   6.151 +  def dload3 = emit(Opcode.Dload3 )
   6.152 +  def aload0 = emit(Opcode.Aload0 )
   6.153 +  def aload1 = emit(Opcode.Aload1 )
   6.154 +  def aload2 = emit(Opcode.Aload2 )
   6.155 +  def aload3 = emit(Opcode.Aload3 )
   6.156 +  def iaload = emit(Opcode.Iaload )
   6.157 +  def laload = emit(Opcode.Laload )
   6.158 +  def faload = emit(Opcode.Faload )
   6.159 +  def daload = emit(Opcode.Daload )
   6.160 +  def aaload = emit(Opcode.Aaload )
   6.161 +  def baload = emit(Opcode.Baload )
   6.162 +  def caload = emit(Opcode.Caload )
   6.163 +  def saload = emit(Opcode.Saload )
   6.164 +  def istore(index:Int) = emitU1(Opcode.Istore , index)
   6.165 +  def lstore(index:Int) = emitU1(Opcode.Lstore , index)
   6.166 +  def fstore(index:Int) = emitU1(Opcode.Fstore , index)
   6.167 +  def dstore(index:Int) = emitU1(Opcode.Dstore , index)
   6.168 +  def astore(index:Int) = emitU1(Opcode.Astore , index)
   6.169 +  def istore0 = emit(Opcode.Istore0 )
   6.170 +  def istore1 = emit(Opcode.Istore1 )
   6.171 +  def istore2 = emit(Opcode.Istore2 )
   6.172 +  def istore3 = emit(Opcode.Istore3 )
   6.173 +  def lstore0 = emit(Opcode.Lstore0 )
   6.174 +  def lstore1 = emit(Opcode.Lstore1 )
   6.175 +  def lstore2 = emit(Opcode.Lstore2 )
   6.176 +  def lstore3 = emit(Opcode.Lstore3 )
   6.177 +  def fstore0 = emit(Opcode.Fstore0 )
   6.178 +  def fstore1 = emit(Opcode.Fstore1 )
   6.179 +  def fstore2 = emit(Opcode.Fstore2 )
   6.180 +  def fstore3 = emit(Opcode.Fstore3 )
   6.181 +  def dstore0 = emit(Opcode.Dstore0 )
   6.182 +  def dstore1 = emit(Opcode.Dstore1 )
   6.183 +  def dstore2 = emit(Opcode.Dstore2 )
   6.184 +  def dstore3 = emit(Opcode.Dstore3 )
   6.185 +  def astore0 = emit(Opcode.Astore0 )
   6.186 +  def astore1 = emit(Opcode.Astore1 )
   6.187 +  def astore2 = emit(Opcode.Astore2 )
   6.188 +  def astore3 = emit(Opcode.Astore3 )
   6.189 +  def iastore = emit(Opcode.Iastore )
   6.190 +  def lastore = emit(Opcode.Lastore )
   6.191 +  def fastore = emit(Opcode.Fastore )
   6.192 +  def dastore = emit(Opcode.Dastore )
   6.193 +  def aastore = emit(Opcode.Aastore )
   6.194 +  def bastore = emit(Opcode.Bastore )
   6.195 +  def castore = emit(Opcode.Castore )
   6.196 +  def sastore = emit(Opcode.Sastore )
   6.197 +  def pop = emit(Opcode.Pop )
   6.198 +  def pop2 = emit(Opcode.Pop2 )
   6.199 +  def dup = emit(Opcode.Dup )
   6.200 +  def dupX1 = emit(Opcode.DupX1 )
   6.201 +  def dupX2 = emit(Opcode.DupX2 )
   6.202 +  def dup2 = emit(Opcode.Dup2 )
   6.203 +  def dup2_X1 = emit(Opcode.Dup2X1 )
   6.204 +  def dup2_X2 = emit(Opcode.Dup2X2 )
   6.205 +  def swap = emit(Opcode.Swap )
   6.206 +  def iadd = emit(Opcode.Iadd )
   6.207 +  def ladd = emit(Opcode.Ladd )
   6.208 +  def fadd = emit(Opcode.Fadd )
   6.209 +  def dadd = emit(Opcode.Dadd )
   6.210 +  def isub = emit(Opcode.Isub )
   6.211 +  def lsub = emit(Opcode.Lsub )
   6.212 +  def fsub = emit(Opcode.Fsub )
   6.213 +  def dsub = emit(Opcode.Dsub )
   6.214 +  def imul = emit(Opcode.Imul )
   6.215 +  def lmul = emit(Opcode.Lmul )
   6.216 +  def fmul = emit(Opcode.Fmul )
   6.217 +  def dmul = emit(Opcode.Dmul )
   6.218 +  def idiv = emit(Opcode.Idiv )
   6.219 +  def ldiv = emit(Opcode.Ldiv )
   6.220 +  def fdiv = emit(Opcode.Fdiv )
   6.221 +  def ddiv = emit(Opcode.Ddiv )
   6.222 +  def irem = emit(Opcode.Irem )
   6.223 +  def lrem = emit(Opcode.Lrem )
   6.224 +  def frem = emit(Opcode.Frem )
   6.225 +  def drem = emit(Opcode.Drem )
   6.226 +  def ineg = emit(Opcode.Ineg )
   6.227 +  def lneg = emit(Opcode.Lneg )
   6.228 +  def fneg = emit(Opcode.Fneg )
   6.229 +  def dneg = emit(Opcode.Dneg )
   6.230 +  def ishl = emit(Opcode.Ishl )
   6.231 +  def lshl = emit(Opcode.Lshl )
   6.232 +  def ishr = emit(Opcode.Ishr )
   6.233 +  def lshr = emit(Opcode.Lshr )
   6.234 +  def iushr = emit(Opcode.Iushr )
   6.235 +  def lushr = emit(Opcode.Lushr )
   6.236 +  def iand = emit(Opcode.Iand )
   6.237 +  def land = emit(Opcode.Land )
   6.238 +  def ior = emit(Opcode.Ior )
   6.239 +  def lor = emit(Opcode.Lor )
   6.240 +  def ixor = emit(Opcode.Ixor )
   6.241 +  def lxor = emit(Opcode.Lxor )
   6.242 +  def iinc(index:Int, increment:Int) = emitU1U1(Opcode.Iinc , index, increment)
   6.243 +  def i2l = emit(Opcode.I2l )
   6.244 +  def i2f = emit(Opcode.I2f )
   6.245 +  def i2d = emit(Opcode.I2d )
   6.246 +  def l2i = emit(Opcode.L2i )
   6.247 +  def l2f = emit(Opcode.L2f )
   6.248 +  def l2d = emit(Opcode.L2d )
   6.249 +  def f2i = emit(Opcode.F2i )
   6.250 +  def f2l = emit(Opcode.F2l )
   6.251 +  def f2d = emit(Opcode.F2d )
   6.252 +  def d2i = emit(Opcode.D2i )
   6.253 +  def d2l = emit(Opcode.D2l )
   6.254 +  def d2f = emit(Opcode.D2f )
   6.255 +  def i2b = emit(Opcode.I2b )
   6.256 +  def i2c = emit(Opcode.I2c )
   6.257 +  def i2s = emit(Opcode.I2s )
   6.258 +  def lcmp = emit(Opcode.Lcmp )
   6.259 +  def fcmpl = emit(Opcode.Fcmpl )
   6.260 +  def fcmpg = emit(Opcode.Fcmpg )
   6.261 +  def dcmpl = emit(Opcode.Dcmpl )
   6.262 +  def dcmpg = emit(Opcode.Dcmpg )
   6.263 +  def genericIf(opcode:Opcode, label:Label) = emitU2(opcode, label.getOffset16(getPC + 1, getPC))
   6.264 +  def ifeq(label:Label) = genericIf(Opcode.Ifeq , label)
   6.265 +  def ifeq(targetPC:Int) = emitU2(Opcode.Ifeq , targetPC - getPC)
   6.266 +  def ifeq = emitU2(Opcode.Ifeq , 0)
   6.267 +  def ifne(label:Label) = genericIf(Opcode.Ifne , label)
   6.268 +  def ifne(targetPC:Int) = emitU2(Opcode.Ifne , targetPC - getPC)
   6.269 +  def ifne = emitU2(Opcode.Ifne , 0)
   6.270 +  def iflt(label:Label) = genericIf(Opcode.Iflt , label)
   6.271 +  def iflt(targetPC:Int) = emitU2(Opcode.Iflt , targetPC - getPC)
   6.272 +  def iflt = emitU2(Opcode.Iflt , 0)
   6.273 +  def ifge(label:Label) = genericIf(Opcode.Ifge , label)
   6.274 +  def ifge(targetPC:Int) = emitU2(Opcode.Ifge , targetPC - getPC)
   6.275 +  def ifge = emitU2(Opcode.Ifge , 0)
   6.276 +  def ifgt(label:Label) = genericIf(Opcode.Ifgt , label)
   6.277 +  def ifgt(targetPC:Int) = emitU2(Opcode.Ifgt , targetPC - getPC)
   6.278 +  def ifgt = emitU2(Opcode.Ifgt , 0)
   6.279 +  def ifle(label:Label) = genericIf(Opcode.Ifle , label)
   6.280 +  def ifle(targetPC:Int) = emitU2(Opcode.Ifle , targetPC - getPC)
   6.281 +  def ifle = emitU2(Opcode.Ifle , 0)
   6.282 +  def ificmpeq(label:Label) = genericIf(Opcode.IfIcmpeq , label)
   6.283 +  def ificmpeq(targetPC:Int) = emitU2(Opcode.IfIcmpeq , targetPC - getPC)
   6.284 +  def ificmpeq = emitU2(Opcode.IfIcmpeq , 0)
   6.285 +  def ificmpne(label:Label) = genericIf(Opcode.IfIcmpne , label)
   6.286 +  def ificmpne(targetPC:Int) = emitU2(Opcode.IfIcmpne , targetPC - getPC)
   6.287 +  def ificmpne = emitU2(Opcode.IfIcmpne , 0)
   6.288 +  def ificmplt(label:Label) = genericIf(Opcode.IfIcmplt , label)
   6.289 +  def ificmplt(targetPC:Int) = emitU2(Opcode.IfIcmplt , targetPC - getPC)
   6.290 +  def ificmplt = emitU2(Opcode.IfIcmplt , 0)
   6.291 +  def ificmpge(label:Label) = genericIf(Opcode.IfIcmpge , label)
   6.292 +  def ificmpge(targetPC:Int) = emitU2(Opcode.IfIcmpge , targetPC - getPC)
   6.293 +  def ificmpge = emitU2(Opcode.IfIcmpge , 0)
   6.294 +  def ificmpgt(label:Label) = genericIf(Opcode.IfIcmpgt , label)
   6.295 +  def ificmpgt(targetPC:Int) = emitU2(Opcode.IfIcmpgt , targetPC - getPC)
   6.296 +  def ificmpgt = emitU2(Opcode.IfIcmpgt , 0)
   6.297 +  def ificmple(label:Label) = genericIf(Opcode.IfIcmple , label)
   6.298 +  def ificmple(targetPC:Int) = emitU2(Opcode.IfIcmple , targetPC - getPC)
   6.299 +  def ificmple = emitU2(Opcode.IfIcmple , 0)
   6.300 +  def ifacmpeq(label:Label) = genericIf(Opcode.IfAcmpeq , label)
   6.301 +  def ifacmpeq(targetPC:Int) = emitU2(Opcode.IfAcmpeq , targetPC - getPC)
   6.302 +  def ifacmpeq = emitU2(Opcode.IfAcmpeq , 0)
   6.303 +  def ifacmpne(label:Label) = genericIf(Opcode.IfAcmpne , label)
   6.304 +  def ifacmpne(targetPC:Int) = emitU2(Opcode.IfAcmpne , targetPC - getPC)
   6.305 +  def ifacmpne = emitU2(Opcode.IfAcmpne , 0)
   6.306 +  def ifnull(label:Label) = genericIf(Opcode.Ifnull , label)
   6.307 +  def ifnull(targetPC:Int) = emitU2(Opcode.Ifnull , targetPC - getPC)
   6.308 +  def ifnull = emitU2(Opcode.Ifnull , 0)
   6.309 +  def ifnonnull(label:Label) = genericIf(Opcode.Ifnonnull , label)
   6.310 +  def ifnonnull(targetPC:Int) = emitU2(Opcode.Ifnonnull , targetPC - getPC)
   6.311 +  def ifnonnull = emitU2(Opcode.Ifnonnull , 0)
   6.312 +  def goto(label:Label) = emitU2(Opcode.Goto , label.getOffset16(getPC + 1, getPC))
   6.313 +  def goto(targetPC:Int){
   6.314 +    var offset:Int = targetPC - getPC
   6.315 +    checkOffset16(offset)
   6.316 +    emitU2(Opcode.Goto , offset)
   6.317 +  }
   6.318 +  def goto = emitU2(Opcode.Goto , 0)
   6.319 +  def gotow(label:Label) = emitU4(Opcode.GotoW , label.getOffset32(getPC + 1, getPC))
   6.320 +  def gotow(targetPC:Int) = emitU4(Opcode.GotoW , targetPC - getPC)
   6.321 +  def gotow = emitU4(Opcode.GotoW , 0)
   6.322 +  def jsr(label:Label) = emitU2(Opcode.Jsr , label.getOffset16(getPC + 1, getPC))
   6.323 +  def jsr(targetPC:Int) = emitU2(Opcode.Jsr , targetPC - getPC)
   6.324 +  def jsr = emitU2(Opcode.Jsr , 0)
   6.325 +  def jsrw(label:Label) = emitU4(Opcode.JsrW , label.getOffset32(getPC + 1, getPC))
   6.326 +  def jsrw(targetPC:Int) = emitU4(Opcode.JsrW , targetPC - getPC)
   6.327 +  def jsrw = emitU4(Opcode.JsrW , 0)
   6.328 +  def ret(index:Int) : Unit = emitU1(Opcode.Ret , index)
   6.329 +/*  def ret(variable:JMethod#JLocalVariable) : Unit = ret(variable.index) */
   6.330 +
   6.331 +  def tableswitch(keys : Array[Int], branches : Array[Label], defaultBranch:Label){
   6.332 +    assert (keys.length == branches.length)
   6.333 +
   6.334 +    var low:Int = keys(0)
   6.335 +
   6.336 +    var high:Int = keys(keys.length - 1)
   6.337 +
   6.338 +    var instrPC:Int = getPC
   6.339 +
   6.340 +    setStackProduction(instrPC, Opcode.Tableswitch )
   6.341 +    codeArray.addU1(Opcode.Tableswitch.code)
   6.342 +
   6.343 +    while (getPC % 4 != 0) codeArray.addU1(0)
   6.344 +    codeArray.addU4(defaultBranch.getOffset32(getPC, instrPC))
   6.345 +    codeArray.addU4(low)
   6.346 +    codeArray.addU4(high)
   6.347 +    var i:Int = 0
   6.348 +
   6.349 +    while (i < branches.length) {
   6.350 +      assert (keys(i) == low + i)
   6.351 +      codeArray.addU4(branches(i).getOffset32(getPC, instrPC))
   6.352 +      i = i + 1
   6.353 +    }
   6.354 +  }
   6.355 +
   6.356 +  def lookupswitch(keys : Array[Int], branches : Array[Label], defaultBranch:Label){
   6.357 +    assert (keys.length == branches.length)
   6.358 +
   6.359 +    var instrPC:Int = getPC
   6.360 +
   6.361 +    setStackProduction(getPC, Opcode.Lookupswitch )
   6.362 +    codeArray.addU1(Opcode.Lookupswitch.code)
   6.363 +
   6.364 +    while (getPC % 4 != 0) codeArray.addU1(0)
   6.365 +
   6.366 +    codeArray.addU4(defaultBranch.getOffset32(getPC, instrPC))
   6.367 +    codeArray.addU4(branches.length)
   6.368 +
   6.369 +    var i:Int = 0
   6.370 +
   6.371 +    while (i < branches.length) {
   6.372 +      codeArray.addU4(keys(i));
   6.373 +      codeArray.addU4(branches(i).getOffset32(getPC, instrPC));
   6.374 +      i = i + 1
   6.375 +    }
   6.376 +  }
   6.377 +
   6.378 +  def ireturn = emit(Opcode.Ireturn )
   6.379 +  def lreturn = emit(Opcode.Lreturn )
   6.380 +  def freturn = emit(Opcode.Freturn )
   6.381 +  def dreturn = emit(Opcode.Dreturn )
   6.382 +  def areturn = emit(Opcode.Areturn )
   6.383 +  def _return = emit(Opcode.Return )
   6.384 +  def getstatic(className:String, name:String, jtype:Type){
   6.385 +    setStackProduction(getPC, jtype.size)
   6.386 +    var index:Int = constantPool.addFieldRef(className, name, jtype.signature)
   6.387 +
   6.388 +    emitU2(Opcode.Getstatic , index)
   6.389 +  }
   6.390 +  def putstatic(className:String, name:String, jtype:Type){
   6.391 +    setStackProduction(getPC, -jtype.size)
   6.392 +    var index:Int = constantPool.addFieldRef(className, name, jtype.signature)
   6.393 +
   6.394 +    emitU2(Opcode.Putstatic , index)
   6.395 +  }
   6.396 +  def getfield(className:String, name:String, jtype:Type){
   6.397 +    setStackProduction(getPC, jtype.size - 1)
   6.398 +    var index:Int = constantPool.addFieldRef(className, name, jtype.signature)
   6.399 +
   6.400 +    emitU2(Opcode.Getfield , index)
   6.401 +  }
   6.402 +
   6.403 +  def putfield(className:String, name:String, jtype:Type){
   6.404 +    setStackProduction(getPC, -(jtype.size + 1))
   6.405 +    var index:Int = constantPool.addFieldRef(className, name, jtype.signature)
   6.406 +
   6.407 +    emitU2(Opcode.Putfield , index)
   6.408 +  }
   6.409 +
   6.410 +  def invokevirtual(className:String, name:String, jtype:MethodType){
   6.411 +    setStackProduction(getPC, jtype.producedStack - 1)
   6.412 +    var index:Int = constantPool.addClassMethodRef(className, name, jtype.signature)
   6.413 +
   6.414 +    emitU2(Opcode.Invokevirtual , index)
   6.415 +  }
   6.416 +
   6.417 +  def invokespecial(className:String, name:String, jtype:MethodType){
   6.418 +    setStackProduction(getPC, jtype.producedStack - 1)
   6.419 +    var index:Int = constantPool.addClassMethodRef(className, name, jtype.signature)
   6.420 +
   6.421 +    emitU2(Opcode.Invokespecial , index)
   6.422 +  }
   6.423 +
   6.424 +  def invokestatic(className:String, name:String, jtype:MethodType){
   6.425 +    setStackProduction(getPC, jtype.producedStack)
   6.426 +    var index:Int = constantPool.addClassMethodRef(className, name, jtype.signature)
   6.427 +
   6.428 +    emitU2(Opcode.Invokestatic , index)
   6.429 +  }
   6.430 +
   6.431 +  def invokeinterface(className:String, name:String, jtype:MethodType){
   6.432 +    setStackProduction(getPC, jtype.producedStack - 1)
   6.433 +    var index:Int = constantPool.addInterfaceMethodRef(className, name, jtype.signature)
   6.434 +
   6.435 +    emitU2U1U1(Opcode.Invokeinterface , index, jtype.argsSize + 1, 0)
   6.436 +  }
   6.437 +
   6.438 +  def _new(className:String) = emitU2(Opcode.New , constantPool.addClass(className))
   6.439 +  def newarray(elemType:Type) = emitU1(Opcode.Newarray , elemType.tag)
   6.440 +  def anewarray(elemType:ReferenceType) = emitU2(Opcode.Anewarray , constantPool.addDescriptor(elemType))
   6.441 +  def multianewarray(elemType:ReferenceType, dimensions:Int) = {
   6.442 +    setStackProduction(getPC, -dimensions + 1)
   6.443 +    emitU2U1(Opcode.Multianewarray , constantPool.addDescriptor(elemType), dimensions)
   6.444 +  }
   6.445 +
   6.446 +  def arraylength = emit(Opcode.Arraylength )
   6.447 +  def athrow = emit(Opcode.Athrow )
   6.448 +  def checkcast(jtype:ReferenceType) = emitU2(Opcode.Checkcast , constantPool.addDescriptor(jtype))
   6.449 +  def instanceof(jtype:ReferenceType) = emitU2(Opcode.Instanceof , constantPool.addDescriptor(jtype))
   6.450 +  def monitorenter = emit(Opcode.Monitorenter )
   6.451 +  def monitorexit = emit(Opcode.Monitorexit )
   6.452 +
   6.453 +  def wide(opcode:Opcode, index:Int){
   6.454 +    assert (opcode.code == Opcode.Iload.code || opcode.code == Opcode.Lload.code || opcode.code == Opcode.Fload.code || opcode.code == Opcode.Dload.code || opcode.code == Opcode.Aload.code || opcode.code == Opcode.Istore.code || opcode.code == Opcode.Lstore.code || opcode.code == Opcode.Fstore.code || opcode.code == Opcode.Dstore.code || opcode.code == Opcode.Astore.code || opcode.code == Opcode.Ret.code)
   6.455 +
   6.456 +    setStackProduction(getPC, opcode)
   6.457 +    codeArray.addU1(Opcode.Wide .code)
   6.458 +    codeArray.addU1(opcode.code)
   6.459 +    codeArray.addU2(index)
   6.460 +  }
   6.461 +
   6.462 +  def wide(opcode:Opcode, index:Int, constant:Int){
   6.463 +    assert (opcode.code == Opcode.Iinc.code)
   6.464 +
   6.465 +    setStackProduction(getPC, opcode)
   6.466 +    codeArray.addU1(Opcode.Wide.code)
   6.467 +    codeArray.addU1(opcode.code)
   6.468 +    codeArray.addU2(index)
   6.469 +    codeArray.addU2(constant)
   6.470 +  }
   6.471 +
   6.472 +  def emitU1(opcode:Opcode, i1:Int){
   6.473 +    setStackProduction(getPC, opcode)
   6.474 +    codeArray.addU1(opcode.code)
   6.475 +    codeArray.addU1(i1)
   6.476 +  }
   6.477 +
   6.478 +  def emitU1U1(opcode:Opcode, i1:Int, i2:Int){
   6.479 +    setStackProduction(getPC, opcode)
   6.480 +    codeArray.addU1(opcode.code)
   6.481 +    codeArray.addU1(i1)
   6.482 +    codeArray.addU1(i2)
   6.483 +  }
   6.484 +
   6.485 +  def emitU2(opcode:Opcode, i1:Int){
   6.486 +    setStackProduction(getPC, opcode)
   6.487 +    codeArray.addU1(opcode.code)
   6.488 +    codeArray.addU2(i1)
   6.489 +  }
   6.490 +
   6.491 +  def emitU2U1(opcode:Opcode, i1:Int, i2:Int){
   6.492 +    setStackProduction(getPC, opcode)
   6.493 +    codeArray.addU1(opcode.code)
   6.494 +    codeArray.addU2(i1)
   6.495 +    codeArray.addU1(i2)
   6.496 +  }
   6.497 +
   6.498 +  def emitU2U1U1(opcode:Opcode, i1:Int, i2:Int, i3:Int){
   6.499 +    setStackProduction(getPC, opcode)
   6.500 +    codeArray.addU1(opcode.code)
   6.501 +    codeArray.addU2(i1)
   6.502 +    codeArray.addU1(i2)
   6.503 +    codeArray.addU1(i3)
   6.504 +  }
   6.505 +
   6.506 +  def emitU4(opcode:Opcode, i1:Int){
   6.507 +    setStackProduction(getPC, opcode)
   6.508 +    codeArray.addU1(opcode.code)
   6.509 +    codeArray.addU4(i1)
   6.510 +  }
   6.511 +
   6.512 +  def getU1(sourcePos:Int):Int = codeArray.getU1(sourcePos)
   6.513 +  def getU2(sourcePos:Int):Int = codeArray.getU2(sourcePos)
   6.514 +  def getU4(sourcePos:Int):Int = codeArray.getU4(sourcePos)
   6.515 +  def getS1(sourcePos:Int):Int = codeArray.getS1(sourcePos)
   6.516 +  def getS2(sourcePos:Int):Int = codeArray.getS2(sourcePos)
   6.517 +  def getS4(sourcePos:Int):Int = codeArray.getS4(sourcePos)
   6.518 +
   6.519 +  def getStackProduction(pc:Int):Int = {
   6.520 +    if (stackProduction == null || pc >= stackProduction.length) 
   6.521 +      UNKNOWN_STACK_SIZE
   6.522 +    else 
   6.523 +      stackProduction(pc)
   6.524 +  }
   6.525 +
   6.526 +  def setStackProduction(pc:Int, production:Int){
   6.527 +    if (stackProduction == null) {
   6.528 +      stackProduction = new Array[Int](256)
   6.529 +
   6.530 +      Arrays.fill(stackProduction, UNKNOWN_STACK_SIZE)
   6.531 +    } else {
   6.532 +
   6.533 +      while (pc >= stackProduction.length) {
   6.534 +        var newStackProduction : Array[Int] = new Array[Int](stackProduction.length * 2)
   6.535 +
   6.536 +        System.arraycopy(stackProduction, 0, newStackProduction, 0, stackProduction.length)
   6.537 +        Arrays.fill(newStackProduction, stackProduction.length, newStackProduction.length, UNKNOWN_STACK_SIZE)
   6.538 +        stackProduction = newStackProduction
   6.539 +
   6.540 +      }
   6.541 +    }
   6.542 +
   6.543 +    stackProduction(pc) = production
   6.544 +  }
   6.545 +
   6.546 +  def setStackProduction(pc:Int, opcode:Opcode){
   6.547 +    if (getStackProduction(pc) == UNKNOWN_STACK_SIZE) 
   6.548 +      setStackProduction(pc, opcode.getProducedDataSize - opcode.getConsumedDataSize)
   6.549 +  }
   6.550 +
   6.551 +  def computeMaxStackSize:Int = {
   6.552 +    if (stackSizes == null) {
   6.553 +      stackSizes = new Array[Int](this.size);
   6.554 +
   6.555 +      Arrays.fill(stackSizes, UNKNOWN_STACK_SIZE)
   6.556 +      stackSizes(0) = 0
   6.557 +
   6.558 +    }
   6.559 +
   6.560 +    var size:Int = computeMaxStackSize(0, 0, 0)
   6.561 +
   6.562 +    var exh:ExceptionHandler = null
   6.563 +
   6.564 +    var it = exceptionHandlers.iterator
   6.565 +
   6.566 +    while (it.hasNext) {
   6.567 +      exh = it.next.asInstanceOf[ExceptionHandler];
   6.568 +      var exhSize : Int = computeMaxStackSize(exh.handlerPC, 1, 1);
   6.569 +      if (size < exhSize) 
   6.570 +        size = exhSize
   6.571 +    }
   6.572 +    size
   6.573 +  }
   6.574 +
   6.575 +  def computeMaxStackSize(pc:Int, _stackSize:Int, _maxStackSize:Int):Int = {
   6.576 +    var maxStackSize = _stackSize;
   6.577 +    var stackSize = _stackSize;
   6.578 +    var iterator = new CodeIterator(this, pc)
   6.579 +
   6.580 +    while (true) {
   6.581 +      var successors:Int = iterator.getSuccessorCount
   6.582 +      if (successors == 0) 
   6.583 +        return maxStackSize
   6.584 +      else {
   6.585 +        assert (stackProduction(iterator.getPC) != UNKNOWN_STACK_SIZE)
   6.586 +
   6.587 +        stackSize += stackProduction(iterator.getPC)
   6.588 +        if (stackSize > maxStackSize) 
   6.589 +          maxStackSize = stackSize
   6.590 +
   6.591 +        var nextPC:Int = -1
   6.592 +
   6.593 +        var i:Int = 0
   6.594 +
   6.595 +        while (i < successors) {
   6.596 +          var sucC_PC:Int = iterator.getSuccessorPC(i)
   6.597 +          assert (sucC_PC >= 0 && sucC_PC < stackSizes.length)
   6.598 +          if (stackSizes(sucC_PC) == UNKNOWN_STACK_SIZE) {
   6.599 +            stackSizes(sucC_PC) = stackSize
   6.600 +
   6.601 +            if (nextPC == -1) 
   6.602 +              nextPC = sucC_PC
   6.603 +
   6.604 +            else 
   6.605 +              maxStackSize = computeMaxStackSize(sucC_PC, stackSize, maxStackSize)
   6.606 +          }
   6.607 +
   6.608 +          i = i + 1
   6.609 +        }
   6.610 +        if (nextPC == -1) 
   6.611 +          return maxStackSize
   6.612 +        else 
   6.613 +          iterator.moveTo(nextPC)
   6.614 +      }
   6.615 +    }
   6.616 +    error("Should never reach here");
   6.617 +  }
   6.618 +
   6.619 +  def load(index:Int, jtype:Type){
   6.620 +    var opcode:Opcode = null
   6.621 +    jtype.tag match  {
   6.622 +      case Type.TBoolean | Type.TByte | Type.TChar | Type.TShort | Type.TInt => index match  {
   6.623 +          case 0 => iload0; return
   6.624 +          case 1 => iload1; return
   6.625 +          case 2 => iload2; return
   6.626 +          case 3 => iload3; return
   6.627 +          case _ => opcode = Opcode.Iload 
   6.628 +        }
   6.629 +
   6.630 +      case Type.TFloat => index match  {
   6.631 +          case 0 => fload0; return
   6.632 +          case 1 => fload1; return
   6.633 +          case 2 => fload2; return
   6.634 +          case 3 => fload3; return
   6.635 +          case _ => opcode = Opcode.Fload 
   6.636 +        }
   6.637 +
   6.638 +      case Type.TLong => index match  {
   6.639 +          case 0 => lload0; return
   6.640 +          case 1 => lload1; return
   6.641 +          case 2 => lload2; return
   6.642 +          case 3 => lload3; return
   6.643 +          case _ => opcode = Opcode.Lload 
   6.644 +        }
   6.645 +
   6.646 +      case Type.TDouble => index match  {
   6.647 +          case 0 => dload0; return
   6.648 +          case 1 => dload1; return
   6.649 +          case 2 => dload2; return
   6.650 +          case 3 => dload3; return
   6.651 +          case _ => opcode = Opcode.Dload 
   6.652 +        }
   6.653 +
   6.654 +      case Type.TArray | Type.TObject => index match  {
   6.655 +          case 0 => aload0; return
   6.656 +          case 1 => aload1; return
   6.657 +          case 2 => aload2; return
   6.658 +          case 3 => aload3; return
   6.659 +          case _ => opcode = Opcode.Aload 
   6.660 +        }
   6.661 +
   6.662 +      case _ => throw new IllegalArgumentException("invalid type for load " + jtype)
   6.663 +    }
   6.664 +    if (index > 0xFF) 
   6.665 +      wide(opcode, index)
   6.666 +    else 
   6.667 +      emitU1(opcode, index)
   6.668 +  }
   6.669 +
   6.670 +/*  def load(variable:JMethod#JLocalVariable) { load(variable.index, variable.jtype) } */
   6.671 +
   6.672 +  def store(index:Int, jtype:Type){
   6.673 +    var opcode:Opcode = null
   6.674 +    jtype.tag match  {
   6.675 +      case Type.TBoolean | Type.TByte | Type.TChar | Type.TShort | Type.TInt => index match  {
   6.676 +          case 0 => istore0; return
   6.677 +          case 1 => istore1; return
   6.678 +          case 2 => istore2; return
   6.679 +          case 3 => istore3; return
   6.680 +          case _ => opcode = Opcode.Istore 
   6.681 +        }
   6.682 +
   6.683 +      case Type.TFloat => index match  {
   6.684 +          case 0 => fstore0; return
   6.685 +          case 1 => fstore1; return
   6.686 +          case 2 => fstore2; return
   6.687 +          case 3 => fstore3; return
   6.688 +          case _ => opcode = Opcode.Fstore 
   6.689 +        }
   6.690 +
   6.691 +      case Type.TLong => index match  {
   6.692 +          case 0 => lstore0; return
   6.693 +          case 1 => lstore1; return
   6.694 +          case 2 => lstore2; return
   6.695 +          case 3 => lstore3; return
   6.696 +          case _ =>  opcode = Opcode.Lstore 
   6.697 +        }
   6.698 +
   6.699 +      case Type.TDouble => index match  {
   6.700 +          case 0 => dstore0; return
   6.701 +          case 1 => dstore1; return
   6.702 +          case 2 => dstore2; return
   6.703 +          case 3 => dstore3; return
   6.704 +          case _ => opcode = Opcode.Dstore 
   6.705 +        }
   6.706 +
   6.707 +      case Type.TArray | Type.TObject | Type.TAddress => index match  {
   6.708 +          case 0 => astore0; return
   6.709 +          case 1 => astore1; return
   6.710 +          case 2 => astore2; return
   6.711 +          case 3 => astore3; return
   6.712 +          case _ => opcode = Opcode.Astore 
   6.713 +        }
   6.714 +
   6.715 +      case _ => throw new IllegalArgumentException("invalid type for store " + jtype)
   6.716 +
   6.717 +    }
   6.718 +
   6.719 +    if (index > 0xFF) 
   6.720 +      wide(opcode, index)
   6.721 +    else 
   6.722 +      emitU1(opcode, index)
   6.723 +  }
   6.724 +
   6.725 +
   6.726 +/*  def store(variable:JMethod#JLocalVariable){
   6.727 +    store(variable.index, variable.jtype)
   6.728 +  } */
   6.729 +
   6.730 +  def aload(jtype:Type){
   6.731 +    jtype.tag match  {
   6.732 +      case Type.TBoolean | Type.TByte => baload
   6.733 +      case Type.TChar => caload
   6.734 +      case Type.TShort => saload
   6.735 +      case Type.TInt => iaload
   6.736 +      case Type.TFloat => faload
   6.737 +      case Type.TLong => laload
   6.738 +      case Type.TDouble => daload
   6.739 +      case Type.TArray | Type.TObject => aaload
   6.740 +      case _ => throw new IllegalArgumentException("invalid type for aload " + jtype)
   6.741 +    }
   6.742 +  }
   6.743 +
   6.744 +  def astore(jtype:Type){
   6.745 +    jtype.tag match  {
   6.746 +      case Type.TBoolean | Type.TByte => bastore
   6.747 +      case Type.TChar => castore
   6.748 +      case Type.TShort => sastore
   6.749 +      case Type.TInt => iastore
   6.750 +      case Type.TFloat => fastore
   6.751 +      case Type.TLong => lastore
   6.752 +      case Type.TDouble => dastore
   6.753 +      case Type.TArray | Type.TObject => aastore
   6.754 +      case _ => throw new IllegalArgumentException("invalid type for astore " + jtype)
   6.755 +    }
   6.756 +  }
   6.757 +
   6.758 +  def _return(jtype:Type){
   6.759 +    import Type._
   6.760 +    jtype match {
   6.761 +      case Void => _return;
   6.762 +      case Boolean | Byte | Char | Short | Int => ireturn
   6.763 +      case Float => freturn
   6.764 +      case Long => lreturn
   6.765 +      case Double => dreturn
   6.766 +      case _ => areturn;
   6.767 +    }
   6.768 +  }
   6.769 +
   6.770 +  def add(jtype:Type){
   6.771 +    import Type._;
   6.772 +    jtype match  {
   6.773 +      case Boolean | Byte | Char | Short | Int => iadd
   6.774 +      case Float => fadd
   6.775 +      case Long => ladd
   6.776 +      case Double => dadd
   6.777 +    }
   6.778 +  }
   6.779 +
   6.780 +  def t2t(fromType:Type, toType:Type){
   6.781 +    assert (fromType.tag >= Type.TBoolean && fromType.tag <= Type.TLong && toType.tag >= Type.TBoolean && toType.tag <= Type.TLong)
   6.782 +
   6.783 +    var conv : Array[Opcode] = typeConversions(fromType.tag - 4)(toType.tag - 4)
   6.784 +
   6.785 +    if (conv == forbidden) {
   6.786 +      throw new Error("inconvertible types : " + fromType.toString + " -> " + toType.toString)
   6.787 +    } else 
   6.788 +      if (conv != nothingToDo) {
   6.789 +        var i:Int = 0
   6.790 +
   6.791 +        while (i < conv.length) {
   6.792 +          emit(conv(i))
   6.793 +          i = i + 1
   6.794 +        }
   6.795 +      }
   6.796 +  }
   6.797 +  
   6.798 +  def _if(cond:Int, label:Label){
   6.799 +    assert (cond >= COND_EQ && cond <= COND_LE)
   6.800 +    emitU2(Opcode.Opcodes(153 + cond), label.getOffset16(getPC + 1, getPC))
   6.801 +  }
   6.802 +  
   6.803 +  def _if(cond:Int, targetPC:Int){
   6.804 +    var offset:Int = targetPC - getPC
   6.805 +
   6.806 +    emitU2(Opcode.Opcodes(153 + cond), offset)
   6.807 +  }
   6.808 +  
   6.809 +  def _if(cond:Int){
   6.810 +    _if(cond, 0)
   6.811 +  }
   6.812 +  
   6.813 +  def ifcmp(cond:Int, label:Label){
   6.814 +    assert (cond >= COND_EQ && cond <= COND_LE)
   6.815 +
   6.816 +    emitU2(Opcode.Opcodes(159 + cond), label.getOffset16(getPC + 1, getPC))
   6.817 +  }
   6.818 +  
   6.819 +  def ifcmp(cond:Int, targetPC:Int){
   6.820 +    var offset:Int = targetPC - getPC
   6.821 +    emitU2(Opcode.Opcodes(159 + cond), offset)
   6.822 +  }
   6.823 +  
   6.824 +  def ifcmp(cond:Int){
   6.825 +    ifcmp(cond, 0)
   6.826 +  }
   6.827 +  
   6.828 +  def ifacmp(cond:Int, label:Label){
   6.829 +    assert (cond == COND_EQ || cond == COND_NE)
   6.830 +
   6.831 +    emitU2(Opcode.Opcodes(165 + cond), label.getOffset16(getPC + 1, getPC))
   6.832 +  }
   6.833 +  
   6.834 +  def ifacmp(cond:Int, targetPC:Int){
   6.835 +    var offset:Int = targetPC - getPC
   6.836 +
   6.837 +    emitU2(Opcode.Opcodes(165 + cond), offset)
   6.838 +  }
   6.839 +  
   6.840 +  def ifacmp(cond:Int){
   6.841 +    ifacmp(cond, 0)
   6.842 +  }
   6.843 +
   6.844 +  def gotoMaybeW(label:Label, defaultToWide:boolean){
   6.845 +    if (label.anchored) gotoMaybeW(label.targetPC)
   6.846 +    else if (defaultToWide) gotow(label)
   6.847 +    else goto(label)
   6.848 +  }
   6.849 +
   6.850 +  def gotoMaybeW(targetPC:Int){
   6.851 +    var offset:Int = targetPC - getPC + 1
   6.852 +
   6.853 +    if (offset < Math.MIN_SHORT || offset > Math.MAX_SHORT) gotow(targetPC)
   6.854 +    else goto(targetPC)
   6.855 +  }
   6.856 +
   6.857 +  def switch(keySets : Array[Array[Int]], branches : Array[Label], defaultBranch:Label, minDensity:Double){
   6.858 +    assert (keySets.length == branches.length)
   6.859 +
   6.860 +    var flatSize:Int = 0
   6.861 +
   6.862 +    var i:Int = 0
   6.863 +
   6.864 +    while (i < keySets.length) {
   6.865 +      flatSize += keySets(i).length
   6.866 +      i = i + 1
   6.867 +    }
   6.868 +    var flatKeys : Array[Int] = new Array[Int](flatSize);
   6.869 +
   6.870 +    var flatBranches : Array[Label] = new Array[Label](flatSize);
   6.871 +
   6.872 +    var flatI:Int = 0
   6.873 +
   6.874 +    i = 0
   6.875 +
   6.876 +    while (i < keySets.length) {
   6.877 +      var branch:Label = branches(i)
   6.878 +      var keys : Array[Int] = keySets(i)
   6.879 +      var j:Int = 0
   6.880 +
   6.881 +      while (j < keys.length) {
   6.882 +        flatKeys(flatI) = keys(j)
   6.883 +        flatBranches(flatI) = branch
   6.884 +
   6.885 +        j = j + 1
   6.886 +      }
   6.887 +
   6.888 +      flatI = flatI + 1
   6.889 +      i = i + 1
   6.890 +    }
   6.891 +    assert (flatI == flatSize)
   6.892 +
   6.893 +    switch(flatKeys, flatBranches, defaultBranch, minDensity)
   6.894 +  }
   6.895 +
   6.896 +  def switch(keys : Array[Int], branches : Array[Label], defaultBranch:Label, minDensity:Double){
   6.897 +    assert (keys.length == branches.length)
   6.898 +
   6.899 +    var i:Int = 1
   6.900 +
   6.901 +    while (i < keys.length) {
   6.902 +      var j:Int = 1
   6.903 +
   6.904 +      while (j <= keys.length - i) {
   6.905 +        if (keys(j) < keys(j - 1)) {
   6.906 +          var tmp:Int = keys(j)
   6.907 +
   6.908 +          keys(j) = keys(j - 1)
   6.909 +
   6.910 +          keys(j - 1) = tmp
   6.911 +
   6.912 +          var tmp_l:Label = branches(j)
   6.913 +
   6.914 +          branches(j) = branches(j - 1)
   6.915 +
   6.916 +          branches(j - 1) = tmp_l
   6.917 +
   6.918 +        }
   6.919 +
   6.920 +        j = j + 1
   6.921 +      }
   6.922 +      i = i + 1
   6.923 +    }
   6.924 +    var keyMin:Int = keys(0)
   6.925 +
   6.926 +    var keyMax:Int = keys(keys.length - 1)
   6.927 +
   6.928 +    var keyRange:Int = keyMax - keyMin + 1
   6.929 +
   6.930 +    if (keys.length.asInstanceOf[Double]  / keyRange.asInstanceOf[Double]  >= minDensity) {
   6.931 +      var newKeys : Array[Int] = new Array[Int](keyRange)
   6.932 +
   6.933 +      var newBranches : Array[Label] = new Array[Label](keyRange);
   6.934 +
   6.935 +      var oldPos:Int = 0
   6.936 +
   6.937 +      var i:Int = 0
   6.938 +
   6.939 +      while (i < keyRange) {
   6.940 +        var key:Int = keyMin + i
   6.941 +        newKeys(i) = key
   6.942 +        if (keys(oldPos) == key) {
   6.943 +          newBranches(i) = branches(oldPos)
   6.944 +
   6.945 +          oldPos = oldPos + 1
   6.946 +        } else 
   6.947 +          newBranches(i) = defaultBranch
   6.948 +
   6.949 +        i = i + 1
   6.950 +      }
   6.951 +      assert (oldPos == keys.length)
   6.952 +
   6.953 +      tableswitch(newKeys, newBranches, defaultBranch)
   6.954 +    } else 
   6.955 +      lookupswitch(keys, branches, defaultBranch)
   6.956 +
   6.957 +  }
   6.958 +
   6.959 +/*
   6.960 +  def invoke(method:JMethod){
   6.961 +    var mName:String = method.name
   6.962 +
   6.963 +    var cName:String = method.owner.name
   6.964 +
   6.965 +    var mType:MethodType = method.jtype.asInstanceOf[MethodType] 
   6.966 +
   6.967 +    if (method.isStatic) 
   6.968 +      invokestatic(cName, mName, mType)
   6.969 +    else 
   6.970 +      if (method.owner.isInterface) 
   6.971 +        invokeinterface(cName, mName, mType)
   6.972 +      else 
   6.973 +        invokevirtual(cName, mName, mType)
   6.974 +
   6.975 +  }
   6.976 +*/
   6.977 +  
   6.978 +  def checkOffset16(offset:Int){
   6.979 +      throw new OffsetTooBigException("offset too big to fit" + " in 16 bits: " + offset)
   6.980 +  }
   6.981 +
   6.982 +  def newLabel:Label = {
   6.983 +    new Label
   6.984 +  }
   6.985 +
   6.986 +  def newLabels(count:Int) : Array[Label] = {
   6.987 +    var labels : Array[Label] = new Array[Label](count);
   6.988 +
   6.989 +    var i:Int = 0
   6.990 +
   6.991 +    while (i < labels.length) {
   6.992 +      labels(i) = newLabel
   6.993 +      i = i + 1
   6.994 +    }
   6.995 +    labels
   6.996 +  }
   6.997 +
   6.998 +  def recordOffsetToPatch(offsetPC:Int, size:Int, instrPC:Int, label:Label){
   6.999 +    offsetToPatch.add(new OffsetToPatch(offsetPC, size, instrPC, label))
  6.1000 +  }
  6.1001 +
  6.1002 +  
  6.1003 +  def patchAllOffset{
  6.1004 +    var offsetIt = offsetToPatch.iterator
  6.1005 +
  6.1006 +    while (offsetIt.hasNext) {
  6.1007 +      var offset = offsetIt.next
  6.1008 +
  6.1009 +      var offsetValue:Int = offset.label.getAnchor - offset.instrPC
  6.1010 +
  6.1011 +      if (offset.size == 16) {
  6.1012 +        checkOffset16(offsetValue)
  6.1013 +        codeArray.putU2(offset.pc, offsetValue)
  6.1014 +      } else 
  6.1015 +        codeArray.putU4(offset.pc, offsetValue)
  6.1016 +
  6.1017 +    }
  6.1018 +  }
  6.1019 +
  6.1020 +  def addExceptionHandler(handler:ExceptionHandler){
  6.1021 +    exceptionHandlers.add(handler)
  6.1022 +  }
  6.1023 +
  6.1024 +  def addExceptionHandler(startPC:Int, endPC:Int, handlerPC:Int, catchType:String){
  6.1025 +    addExceptionHandler(new ExceptionHandler(startPC, endPC, handlerPC, catchType))
  6.1026 +  }
  6.1027 +
  6.1028 +  def addFinallyHandler(startPC:Int, endPC:Int, handlerPC:Int){
  6.1029 +    addExceptionHandler(startPC, endPC, handlerPC, null)
  6.1030 +  }
  6.1031 +
  6.1032 +  def ensureLineNumberCapacity(endPC:Int){
  6.1033 +    if (lineNumbers == null) {
  6.1034 +      lineNumbers = new Array[Int](endPC)
  6.1035 +    } else 
  6.1036 +      if (lineNumbers.length < endPC) {
  6.1037 +        var newLN : Array[Int] = new Array[Int](Math.max(endPC, lineNumbers.length * 2))
  6.1038 +
  6.1039 +        Array.copy(lineNumbers, 0, newLN, 0, lineNumbers.length)
  6.1040 +        lineNumbers = newLN
  6.1041 +
  6.1042 +      }
  6.1043 +  }
  6.1044 +
  6.1045 +  def setLineNumber(startPC:Int, endPC:Int, line:Int){
  6.1046 +    ensureLineNumberCapacity(endPC)
  6.1047 +    Arrays.fill(lineNumbers, startPC, endPC, line)
  6.1048 +  }
  6.1049 +
  6.1050 +  def setLineNumber(instrPC:Int, line:Int){
  6.1051 +    setLineNumber(instrPC, instrPC + 1, line)
  6.1052 +  }
  6.1053 +
  6.1054 +  def completeLineNumber(startPC:Int, endPC:Int, line:Int){
  6.1055 +    ensureLineNumberCapacity(endPC)
  6.1056 +    var pc:Int = startPC
  6.1057 +
  6.1058 +    while (pc < endPC) {}
  6.1059 +
  6.1060 +  }
  6.1061 +
  6.1062 +  class Label {
  6.1063 +    def anchorToNext{
  6.1064 +      assert (!anchored)
  6.1065 +
  6.1066 +      this.targetPC = getPC
  6.1067 +      anchored = true
  6.1068 +
  6.1069 +    }
  6.1070 +
  6.1071 +    def getAnchor:Int = {
  6.1072 +      assert (anchored)
  6.1073 +
  6.1074 +      targetPC
  6.1075 +    }
  6.1076 +
  6.1077 +    
  6.1078 +    def getOffset16(pc:Int, instrPC:Int):Int = {
  6.1079 +      if (anchored) {
  6.1080 +        var offset:Int = targetPC - instrPC
  6.1081 +
  6.1082 +        checkOffset16(offset)
  6.1083 +        offset
  6.1084 +      } else {
  6.1085 +        recordOffsetToPatch(pc, 16, instrPC, this)
  6.1086 +        0
  6.1087 +      }
  6.1088 +
  6.1089 +    }
  6.1090 +
  6.1091 +    def getOffset32(pc:Int, instrPC:Int):Int = {
  6.1092 +      if (anchored) 
  6.1093 +        targetPC - instrPC
  6.1094 +      else {
  6.1095 +        recordOffsetToPatch(pc, 32, instrPC, this)
  6.1096 +        0
  6.1097 +      }
  6.1098 +
  6.1099 +    }
  6.1100 +    var anchored:boolean = false
  6.1101 +
  6.1102 +    var targetPC:Int = 0
  6.1103 +  }
  6.1104 +
  6.1105 +  class OffsetToPatch (val pc:Int, val size:Int, val instrPC:Int, val label:Label) {
  6.1106 +  }
  6.1107 +
  6.1108 +  def readExceptionHandler(stream : DataInputStream) = {
  6.1109 +    val startPC = stream.readShort;
  6.1110 +    val endPC = stream.readShort;
  6.1111 +    val handlerPC = stream.readShort;
  6.1112 +    val catchTypeIndex = stream.readShort;
  6.1113 +    val catchType = if (catchTypeIndex == 0) null else constantPool.lookupClass(catchTypeIndex);
  6.1114 +    new ExceptionHandler(startPC, endPC, handlerPC, catchType);
  6.1115 +  }
  6.1116 +
  6.1117 +  class ExceptionHandler(var startPC : Int, 
  6.1118 +                           var endPC : Int,
  6.1119 +                       var handlerPC : Int, 
  6.1120 +                       var catchType : String) {
  6.1121 +    def this(catchType:String) = {
  6.1122 +      this(0, 0, 0, catchType)
  6.1123 +    }
  6.1124 +    exceptionHandlers.add(this);
  6.1125 +
  6.1126 +    val catchTypeIndex = if (catchType == null) 0 else constantPool.addClass(catchType)
  6.1127 +
  6.1128 +    @throws(classOf[IOException])
  6.1129 +    def writeTo(stream:DataOutputStream){
  6.1130 +      stream.writeShort(startPC)
  6.1131 +      stream.writeShort(endPC)
  6.1132 +      stream.writeShort(handlerPC)
  6.1133 +      stream.writeShort(catchTypeIndex)
  6.1134 +    }
  6.1135 +  }
  6.1136 +}
  6.1137 +
  6.1138 +object Code {
  6.1139 +  val forbidden : Array[Opcode] = new Array[Opcode](0)
  6.1140 +  val nothingToDo : Array[Opcode] = new Array[Opcode](0)
  6.1141 +
  6.1142 +  val typeConversions : Array[Array[Array[Opcode]]] = 
  6.1143 +    Array(Array(nothingToDo, forbidden, forbidden, forbidden, forbidden, forbidden, forbidden, forbidden), 
  6.1144 +          Array(forbidden, 
  6.1145 +                nothingToDo, 
  6.1146 +                Array(Opcode.I2f ), 
  6.1147 +                Array(Opcode.I2d ), 
  6.1148 +                Array(Opcode.I2b ), 
  6.1149 +                Array(Opcode.I2s ), 
  6.1150 +                nothingToDo, 
  6.1151 +                Array(Opcode.I2l )), 
  6.1152 +          Array(forbidden, 
  6.1153 +                Array(Opcode.F2i , Opcode.I2c ), 
  6.1154 +                nothingToDo, 
  6.1155 +                Array(Opcode.F2d ), 
  6.1156 +                Array(Opcode.F2i , Opcode.I2b ), 
  6.1157 +                Array(Opcode.F2i , Opcode.I2s ), 
  6.1158 +                Array(Opcode.F2i ), 
  6.1159 +                Array(Opcode.F2l )), 
  6.1160 +          Array(forbidden, 
  6.1161 +                Array (Opcode.D2i , Opcode.I2c ), 
  6.1162 +                Array(Opcode.D2f ), 
  6.1163 +                nothingToDo, 
  6.1164 +                Array(Opcode.D2i , Opcode.I2b ), 
  6.1165 +                Array(Opcode.D2i , Opcode.I2s ), 
  6.1166 +                Array(Opcode.D2i ), 
  6.1167 +                Array(Opcode.D2l )), 
  6.1168 +          Array(forbidden, 
  6.1169 +                Array(Opcode.I2c ), 
  6.1170 +                Array(Opcode.I2f ), 
  6.1171 +                Array(Opcode.I2d ), 
  6.1172 +                nothingToDo, 
  6.1173 +                nothingToDo, 
  6.1174 +                nothingToDo, 
  6.1175 +                Array(Opcode.I2l )), 
  6.1176 +          Array(forbidden, 
  6.1177 +                nothingToDo, 
  6.1178 +                Array(Opcode.I2f ), 
  6.1179 +                Array(Opcode.I2d ), 
  6.1180 +                Array(Opcode.I2b ), 
  6.1181 +                nothingToDo, 
  6.1182 +                nothingToDo, 
  6.1183 +                Array(Opcode.I2l )), 
  6.1184 +          Array(forbidden, 
  6.1185 +                Array(Opcode.I2c ), 
  6.1186 +                Array(Opcode.I2f ), 
  6.1187 +                Array(Opcode.I2d ), 
  6.1188 +                Array(Opcode.I2b ), 
  6.1189 +                Array(Opcode.I2s ), 
  6.1190 +                nothingToDo, 
  6.1191 +                Array(Opcode.I2l )), 
  6.1192 +          Array(forbidden, 
  6.1193 +                Array(Opcode.L2i , Opcode.I2c ), 
  6.1194 +                Array(Opcode.L2f ), 
  6.1195 +                Array(Opcode.L2d ), 
  6.1196 +                Array(Opcode.L2i , Opcode.I2b ), 
  6.1197 +                Array(Opcode.L2i , Opcode.I2s ), 
  6.1198 +                Array(Opcode.L2i ), 
  6.1199 +                nothingToDo))
  6.1200 +
  6.1201 +  class OffsetTooBigException(message : String) extends Exception(message) {
  6.1202 +  }
  6.1203 +
  6.1204 +  var UNKNOWN_STACK_SIZE:Int = Integer.MIN_VALUE
  6.1205 +  val COND_EQ:Int = 0
  6.1206 +  val COND_NE:Int = 1
  6.1207 +  val COND_LT:Int = 2
  6.1208 +  val COND_GE:Int = 3
  6.1209 +  val COND_GT:Int = 4
  6.1210 +  val COND_LE:Int = 5
  6.1211 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/tools/Dependencies.scala	Wed Aug 13 09:54:58 2008 +0100
     7.3 @@ -0,0 +1,40 @@
     7.4 +package classy.tools;
     7.5 +
     7.6 +import classy.Format._;
     7.7 +
     7.8 +case class Dependencies(sourceFile : Option[String], classes : List[String]);
     7.9 +
    7.10 +object DependencyFinder{
    7.11 +  def dependenciesOf(c : classy.Class) = {
    7.12 +    import ConstantPool._;
    7.13 +    implicit def cp = c.constantPool;
    7.14 +//    cp.contents.zipWithIndex.foreach{case (c, i) => println(i.toInt + ": " + c)}
    7.15 +    val sourceFile = attributes.SourceFileAttribute(c) match {
    7.16 +      case Nil => None;
    7.17 +      case List(x) => Some(x)
    7.18 +    }
    7.19 +    val classes = (for(ClassIndex(i) <- cp.contents) yield cp.getUTF(i)).toList;
    7.20 +    Dependencies(sourceFile, classes);
    7.21 +  } 
    7.22 +
    7.23 +  def main(args : Array[String]){
    7.24 +    val Array(dir) = args;
    7.25 +
    7.26 +    import java.io._;
    7.27 +    import scalax.io.Implicits._
    7.28 +    import sbinary._;    
    7.29 +  
    7.30 +    for (file <- new File(dir).tree){
    7.31 +      if (file.extension == Some("class")){
    7.32 +        val d = dependenciesOf(Operations.fromFile[classy.Class](file))
    7.33 +        print(file.getName);
    7.34 +        println(" (" + d.sourceFile + ")");        
    7.35 +        print("  Depends on:")
    7.36 +  
    7.37 +        for (c <- d.classes){
    7.38 +          println("    " + c);
    7.39 +        }
    7.40 +      }
    7.41 +    }
    7.42 +  }
    7.43 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/util/bytes.scala	Wed Aug 13 09:54:58 2008 +0100
     8.3 @@ -0,0 +1,218 @@
     8.4 +package classy.util.bytes; 
     8.5 +
     8.6 +import java.io._
     8.7 +
     8.8 +import sbinary.Instances._;
     8.9 +import sbinary._;
    8.10 +import java.io.{OutputStream, ByteArrayOutputStream}
    8.11 +
    8.12 +import ByteBuffer._;
    8.13 +
    8.14 +class ByteBuffer {
    8.15 +  protected var data:Array[Array[Byte]] = Array(new Array[Byte](BYTE_BLOCK_SIZE))
    8.16 +  protected var pos:Int = 0
    8.17 +
    8.18 +  def this(bytes : ByteString) = { this(); bytes.foreach(addByte(_)); }
    8.19 +
    8.20 +  def nextBytePosition():Int = {
    8.21 +    pos
    8.22 +  }
    8.23 +
    8.24 +  def size = pos;
    8.25 +
    8.26 +  protected def addNewBlock():Unit = {
    8.27 +    var nextBlockPos:Int = pos >>> BYTE_BLOCK_BITS
    8.28 +
    8.29 +    if (nextBlockPos == data.length) {
    8.30 +      var newData : Array[Array[byte]] = new Array[Array[Byte]](data.length * 2, 0)
    8.31 +
    8.32 +      System.arraycopy(data, 0, newData, 0, data.length)
    8.33 +      data = newData
    8.34 +
    8.35 +    }
    8.36 +
    8.37 +    assert (data(nextBlockPos) == null)
    8.38 +
    8.39 +    data(nextBlockPos) = new Array[byte](BYTE_BLOCK_SIZE)
    8.40 +
    8.41 +  }
    8.42 +
    8.43 +  protected def addByte(b:Int):Unit = {
    8.44 +    if ((pos & BYTE_BLOCK_MASK) == 0 && pos > 0) 
    8.45 +      addNewBlock()
    8.46 +
    8.47 +
    8.48 +    var currPos : Int = pos;
    8.49 +    pos = pos + 1
    8.50 +
    8.51 +    data(currPos >>> BYTE_BLOCK_BITS)(currPos & BYTE_BLOCK_MASK) = b.asInstanceOf[byte] 
    8.52 +  }
    8.53 +
    8.54 +  def addU1(i:Int):Unit = {
    8.55 +    assert (i <= 0xFF)
    8.56 +
    8.57 +    addByte(i)
    8.58 +  }
    8.59 +
    8.60 +  def addU2(i:Int):Unit = {
    8.61 +    assert (i <= 0xFFFF)
    8.62 +
    8.63 +    addByte(i >>> 8)
    8.64 +    addByte(i & 0xFF)
    8.65 +  }
    8.66 +
    8.67 +  def addU4(i:Int):Unit = {
    8.68 +    addByte(i >>> 24)
    8.69 +    addByte(i >>> 16 & 0xFF)
    8.70 +    addByte(i >>> 8 & 0xFF)
    8.71 +    addByte(i & 0xFF)
    8.72 +  }
    8.73 +
    8.74 +  def putByte(targetPos:Int, b:Int):Unit = {
    8.75 +    assert (targetPos < pos)
    8.76 +
    8.77 +    data(targetPos >>> BYTE_BLOCK_BITS)(targetPos & BYTE_BLOCK_MASK) = b.asInstanceOf[byte] 
    8.78 +  }
    8.79 +
    8.80 +  def putU2(targetPos:Int, i:Int):Unit = {
    8.81 +    assert (i < 0xFFFF)
    8.82 +
    8.83 +    putByte(targetPos, i >>> 8)
    8.84 +    putByte(targetPos + 1, i & 0xFF)
    8.85 +  }
    8.86 +
    8.87 +  def putU4(targetPos:Int, i:Int):Unit = {
    8.88 +    putByte(targetPos, i >>> 24)
    8.89 +    putByte(targetPos + 1, i >>> 16 & 0xFF)
    8.90 +    putByte(targetPos + 2, i >>> 8 & 0xFF)
    8.91 +    putByte(targetPos + 3, i & 0xFF)
    8.92 +  }
    8.93 +
    8.94 +  def getU1(sourcePos:Int):Int = {
    8.95 +    assert (sourcePos < pos)
    8.96 +
    8.97 +    data(sourcePos >>> BYTE_BLOCK_BITS)(sourcePos & BYTE_BLOCK_MASK) & 0xFF
    8.98 +  }
    8.99 +
   8.100 +  def getU2(sourcePos:Int) : Char= 
   8.101 +    (getU1(sourcePos) << 8 | getU1(sourcePos + 1)).toChar
   8.102 +
   8.103 +  def getU4(sourcePos:Int):Int = {
   8.104 +    getU2(sourcePos) << 16 | getU2(sourcePos + 2)
   8.105 +  }
   8.106 +
   8.107 +  def getS1(sourcePos:Int):Int = {
   8.108 +    assert (sourcePos < pos)
   8.109 +
   8.110 +    data(sourcePos >>> BYTE_BLOCK_BITS)(sourcePos & BYTE_BLOCK_MASK)
   8.111 +  }
   8.112 +
   8.113 +  def getS2(sourcePos:Int):Int = {
   8.114 +    getS1(sourcePos) << 8 | getU1(sourcePos + 1)
   8.115 +  }
   8.116 +
   8.117 +  def getS4(sourcePos:Int):Int = {
   8.118 +    getS2(sourcePos) << 16 | getU2(sourcePos + 2)
   8.119 +  }
   8.120 +
   8.121 +  @throws(classOf[IOException])
   8.122 +  def writeTo(stream:OutputStream):Unit = {
   8.123 +    var i:Int = 0
   8.124 +
   8.125 +    while (i < data.length && data(i) != null) {
   8.126 +      var len:Int = Math.min(BYTE_BLOCK_SIZE, pos - (i << BYTE_BLOCK_BITS))
   8.127 +      stream.write(data(i), 0, len)
   8.128 +      i = i + 1
   8.129 +    }
   8.130 +  }
   8.131 +
   8.132 +  def toArray= {
   8.133 +    val out = new ByteArrayOutputStream();
   8.134 +    writeTo(out);
   8.135 +    out.toByteArray;
   8.136 +  }
   8.137 +}
   8.138 +
   8.139 +object ByteBuffer {
   8.140 +  val BYTE_BLOCK_BITS:Int = 8
   8.141 +  val BYTE_BLOCK_SIZE:Int = 1 << BYTE_BLOCK_BITS
   8.142 +  val BYTE_BLOCK_MASK:Int = BYTE_BLOCK_SIZE - 1
   8.143 +}
   8.144 +
   8.145 +class ByteString private[bytes] (var bytes : Array[Byte], private var start : Int, val length : Int) extends Iterable[Byte]{
   8.146 +  private[this] def oob(messages : Any*) = throw new IndexOutOfBoundsException(messages.mkString(", "));
   8.147 +
   8.148 +  private def this(bytes : Array[Byte]) = this(bytes, 0, bytes.length);
   8.149 +
   8.150 +  if (start < 0 || start + length > bytes.length) oob(start, length);
   8.151 +  if (length < 0.3 * bytes.length) {
   8.152 +    bytes = bytes.slice(start, start + length);
   8.153 +    start = 0;
   8.154 +  }  
   8.155 +
   8.156 +  def apply(i : Int) = if (i < 0 || i >= length) oob(i); else bytes(start + i);
   8.157 +
   8.158 +  def elements = (start until (start + length)).map(bytes(_)).elements
   8.159 +
   8.160 +  override val hashCode = {
   8.161 +    var h = 0;
   8.162 +    var i = start;
   8.163 +    val end = start + length;
   8.164 +    while (i < end){
   8.165 +      h = 31 * h + bytes(i);
   8.166 +      i += 1;
   8.167 +    }
   8.168 +    h;
   8.169 +  } 
   8.170 +
   8.171 +  override def equals(that : Any) : Boolean = that match {
   8.172 +    case (that : ByteString) => {
   8.173 +      if (this eq that) true
   8.174 +      else if (this.length != that.length) false;
   8.175 +      else if (this.hashCode != that.hashCode) false;
   8.176 +      else if (this.bytes == that.bytes && this.start == that.start) true 
   8.177 +      else {
   8.178 +        var i = 0;
   8.179 +
   8.180 +        while (i < length){
   8.181 +          if (this.bytes(start + i) != that.bytes(that.start + i)) return false;
   8.182 +          i += 1;
   8.183 +        }
   8.184 +        true;
   8.185 +      }
   8.186 +    }
   8.187 +    case _ => false; 
   8.188 +  }
   8.189 +
   8.190 +  override def toString = toString("UTF-8");
   8.191 +
   8.192 +  def toString(encoding : String) = new String(bytes, start, length, encoding);
   8.193 +
   8.194 +  def toArray : Array[Byte] = bytes.slice(start, start + length);
   8.195 +
   8.196 +  def writeTo(out : OutputStream) = out.write(bytes, start, length);
   8.197 +  def inputStream = new ByteArrayInputStream(bytes, start, length); 
   8.198 +
   8.199 +  def to[V](implicit bin : Binary[V]) = sbinary.Operations.wrapInputStream(inputStream).read[V];
   8.200 +
   8.201 +  def substring(from : Int, until : Int) = 
   8.202 +    if (from < start || until > length) oob(from, until);
   8.203 +    else new ByteString(bytes, start + from, until - start);
   8.204 +}
   8.205 +
   8.206 +object ByteString{
   8.207 +  def fromArray(array : Array[Byte]) = new ByteString(Array(array :_*));
   8.208 +  def fromString(content : String, encoding : String) : ByteString = new ByteString(content.getBytes(encoding));
   8.209 +  def fromString(content : String) : ByteString = fromString("UTF-8");
   8.210 +
   8.211 +  def concat(strings : Iterable[ByteString]) = {
   8.212 +    val out = new ByteArrayOutputStream;
   8.213 +    strings.foreach(_.writeTo(out));
   8.214 +    new ByteString(out.toByteArray);
   8.215 +  }
   8.216 +  
   8.217 +  implicit val ByteStringIsBinary : Binary[ByteString] = new Binary[ByteString]{
   8.218 +    def reads(input : Input) = new ByteString(input.read[Array[Byte]])
   8.219 +    def writes(bytes : ByteString)(output : Output) = output.writeBytes(bytes.bytes, bytes.start, bytes.length);
   8.220 +  }
   8.221 +}
     9.1 --- a/src/util/bytestring.scala	Tue Jun 17 10:34:55 2008 +0100
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,78 +0,0 @@
     9.4 -package classy.util.bytestring;
     9.5 -
     9.6 -import sbinary.Instances._;
     9.7 -import sbinary._;
     9.8 -import java.io.{OutputStream, ByteArrayOutputStream}
     9.9 -
    9.10 -class ByteString private[bytestring] (var bytes : Array[Byte], private var start : Int, val length : Int){
    9.11 -  private[this] def oob(messages : Any*) = throw new IndexOutOfBoundsException(messages.mkString(", "));
    9.12 -
    9.13 -  private def this(bytes : Array[Byte]) = this(bytes, 0, bytes.length);
    9.14 -
    9.15 -  if (start < 0 || start + length > bytes.length) oob(start, length);
    9.16 -  if (length < 0.3 * bytes.length) {
    9.17 -    bytes = bytes.slice(start, start + length);
    9.18 -    start = 0;
    9.19 -  }  
    9.20 -
    9.21 -  def apply(i : Int) = if (i < 0 || i >= length) oob(i); else bytes(start + i);
    9.22 -
    9.23 -  override val hashCode = {
    9.24 -    var h = 0;
    9.25 -    var i = start;
    9.26 -    val end = start + length;
    9.27 -    while (i < end){
    9.28 -      h = 31 * h + bytes(i);
    9.29 -      i += 1;
    9.30 -    }
    9.31 -    h;
    9.32 -  } 
    9.33 -
    9.34 -  override def equals(that : Any) : Boolean = that match {
    9.35 -    case (that : ByteString) => {
    9.36 -      if (this eq that) true
    9.37 -      else if (this.length != that.length) false;
    9.38 -      else if (this.hashCode != that.hashCode) false;
    9.39 -      else if (this.bytes == that.bytes && this.start == that.start) true 
    9.40 -      else {
    9.41 -        var i = 0;
    9.42 -
    9.43 -        while (i < length){
    9.44 -          if (this.bytes(start + i) != that.bytes(that.start + i)) return false;
    9.45 -          i += 1;
    9.46 -        }
    9.47 -        true;
    9.48 -      }
    9.49 -    }
    9.50 -    case _ => false; 
    9.51 -  }
    9.52 -
    9.53 -  override def toString = toString("UTF-8");
    9.54 -
    9.55 -  def toString(encoding : String) = new String(bytes, start, length, encoding);
    9.56 -
    9.57 -  def toArray : Array[Byte] = bytes.slice(start, start + length);
    9.58 -
    9.59 -  def writeTo(out : OutputStream) = out.write(bytes, start, length);
    9.60 -
    9.61 -  def substring(from : Int, until : Int) = 
    9.62 -    if (from < start || until > length) oob(from, until);
    9.63 -    else new ByteString(bytes, start + from, until - start);
    9.64 -}
    9.65 -
    9.66 -object ByteString{
    9.67 -  def fromArray(array : Array[Byte]) = new ByteString(Array(array :_*));
    9.68 -  def fromString(content : String, encoding : String) : ByteString = new ByteString(content.getBytes(encoding));
    9.69 -  def fromString(content : String) : ByteString = fromString("UTF-8");
    9.70 -
    9.71 -  def concat(strings : Iterable[ByteString]) = {
    9.72 -    val out = new ByteArrayOutputStream;
    9.73 -    strings.foreach(_.writeTo(out));
    9.74 -    new ByteString(out.toByteArray);
    9.75 -  }
    9.76 -  
    9.77 -  implicit val ByteStringIsBinary : Binary[ByteString] = new Binary[ByteString]{
    9.78 -    def reads(input : Input) = new ByteString(input.read[Array[Byte]])
    9.79 -    def writes(bytes : ByteString)(output : Output) = output.writeBytes(bytes.bytes, bytes.start, bytes.length);
    9.80 -  }
    9.81 -}