Scala classfile manipulation library
changeset 9:eb3efd8e664e
Working on a dependency analysis tool and supporting code.
It doesn't really work at the moment.
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 -}
