diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2006-08-15 09:25:53 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2006-08-15 09:25:53 +0000 |
commit | 6d236c4abdfbb0af8867a64461f69b9eecbeb279 (patch) | |
tree | b0cdfd5c3d3684a2da86f8e86b1b5074ff5a6f1c /src | |
parent | 6f141280bf6d375151f497e6e4ee0ff601d53ac0 (diff) | |
download | scala-6d236c4abdfbb0af8867a64461f69b9eecbeb279.tar.gz scala-6d236c4abdfbb0af8867a64461f69b9eecbeb279.tar.bz2 scala-6d236c4abdfbb0af8867a64461f69b9eecbeb279.zip |
Added InnerClasses attribute in classfiles
Diffstat (limited to 'src')
4 files changed, 336 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 20d948b6ab..e5cf77b68b 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -208,6 +208,9 @@ trait Members requires ICodes { symbol.owner.hasFlag(Flags.INTERFACE) ); + def isStatic: Boolean = + symbol.hasFlag(Flags.STATIC) || symbol.hasFlag(Flags.STATICMEMBER) || symbol.owner.isImplClass; + override def toString() = symbol.fullNameString; } @@ -222,5 +225,4 @@ trait Members requires ICodes { override def toString(): String = sym.toString(); } - } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 8f45d4f777..ac7aaa0760 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -10,7 +10,7 @@ package scala.tools.nsc.backend.jvm; import java.io.File; import java.nio.ByteBuffer; -import scala.collection.mutable.{Map, HashMap}; +import scala.collection.mutable.{Map, HashMap, Set, HashSet}; import scala.tools.nsc.symtab._; import scala.tools.nsc.util.Position; @@ -83,6 +83,8 @@ abstract class GenJVM extends SubComponent { var jmethod: JMethod = _; var jcode: JExtendedCode = _; + var innerClasses: Set[Symbol] = new HashSet; // referenced inner classes + val fjbgContext = if (settings.target.value == "jvm-1.5") new FJBGContext(49, 0) else new FJBGContext(); val emitSource = settings.debuginfo.level >= 1; @@ -107,6 +109,8 @@ abstract class GenJVM extends SubComponent { } if (!(jclass.getName().endsWith("$") && sym.isModuleClass)) addScalaAttr(if (isTopLevelModule(sym)) sym.sourceModule else sym); + addInnerClasses; + val outfile = getFile(jclass, ".class"); jclass.writeTo(outfile); val file = scala.tools.nsc.io.AbstractFile.getFile(outfile); @@ -122,6 +126,8 @@ abstract class GenJVM extends SubComponent { if (settings.debug.value) log("Generating class " + c.symbol + " flags: " + Flags.flagsToString(c.symbol.flags)); clasz = c; + innerClasses.clear; + var parents = c.symbol.info.parents; var ifaces = JClass.NO_INTERFACES; val name = javaName(c.symbol); @@ -321,6 +327,21 @@ abstract class GenJVM extends SubComponent { jmember.addAttribute(attr) } + def addInnerClasses: Unit = { + // add inner classes which might not have been referenced yet + atPhase(currentRun.erasurePhase) { + for (val sym <- clasz.symbol.info.decls.elements; sym.isClass) + innerClasses += sym; + } + + val innerClassesAttr = jclass.getInnerClasses(); + for (val innerSym <- innerClasses) + innerClassesAttr.addEntry(javaName(innerSym), + javaName(innerSym.rawowner), + innerSym.rawname.toString(), + javaFlags(innerSym)); + } + def isTopLevelModule(sym: Symbol): Boolean = atPhase (currentRun.refchecksPhase) { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass @@ -1002,6 +1023,14 @@ abstract class GenJVM extends SubComponent { jcode.emitT2T(javaType(INT), javaType(kind)); } + case Comparison(op, kind) => Pair(op, kind) match { + case Pair(CMP, LONG) => jcode.emitLCMP(); + case Pair(CMPL, FLOAT) => jcode.emitFCMPL(); + case Pair(CMPG, FLOAT) => jcode.emitFCMPG(); + case Pair(CMPL, DOUBLE) => jcode.emitDCMPL(); + case Pair(CMPG, DOUBLE) => jcode.emitDCMPL(); + } + case Conversion(src, dst) => if (settings.debug.value) log("Converting from: " + src + " to: " + dst); @@ -1144,6 +1173,9 @@ abstract class GenJVM extends SubComponent { else if (sym == definitions.AllRefClass) return "scala.AllRef$"; + if (sym.isClass && !sym.rawowner.isPackageClass) + innerClasses += sym; + (if (sym.isClass || (sym.isModule && !sym.isMethod)) sym.fullNameString('/') else @@ -1179,7 +1211,10 @@ abstract class GenJVM extends SubComponent { var jf: Int = 0; val f = sym.flags; jf = jf | (if (sym hasFlag Flags.SYNTHETIC) ACC_SYNTHETIC else 0); - jf = jf | (if (sym hasFlag Flags.PRIVATE) ACC_PRIVATE else ACC_PUBLIC); +/* jf = jf | (if (sym hasFlag Flags.PRIVATE) ACC_PRIVATE else + if (sym hasFlag Flags.PROTECTED) ACC_PROTECTED else ACC_PUBLIC); +*/ + jf = jf | (if (sym hasFlag Flags.PRIVATE) ACC_PRIVATE else ACC_PUBLIC); jf = jf | (if ((sym hasFlag Flags.ABSTRACT) || (sym hasFlag Flags.DEFERRED)) ACC_ABSTRACT else 0); jf = jf | (if (sym hasFlag Flags.INTERFACE) ACC_INTERFACE else 0); diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala index 3c5d94485a..ca7cd768a5 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala @@ -60,4 +60,238 @@ object ClassfileConstants { final val VOID_TAG = 'V' final val ANNOTATION_TAG = '@' + // tags describing the type of newarray + final val T_BOOLEAN = 4 + final val T_CHAR = 5 + final val T_FLOAT = 6 + final val T_DOUBLE = 7 + final val T_BYTE = 8 + final val T_SHORT = 9 + final val T_INT = 10 + final val T_LONG = 11 + + // JVM mnemonics + final val nop = 0x00 + final val aconst_null = 0x01 + final val iconst_m1 = 0x02 + + final val iconst_0 = 0x03 + final val iconst_1 = 0x04 + final val iconst_2 = 0x05 + final val iconst_3 = 0x06 + final val iconst_4 = 0x07 + final val iconst_5 = 0x08 + + final val lconst_0 = 0x09 + final val lconst_1 = 0x0a + final val fconst_0 = 0x0b + final val fconst_1 = 0x0c + final val fconst_2 = 0x0d + final val dconst_0 = 0x0e + final val dconst_1 = 0x0f + + final val bipush = 0x10 + final val sipush = 0x11 + final val ldc = 0x12 + final val ldc_w = 0x13 + final val ldc2_w = 0x14 + + final val iload = 0x15 + final val lload = 0x16 + final val fload = 0x17 + final val dload = 0x18 + final val aload = 0x19 + + final val iload_0 = 0x1a + final val iload_1 = 0x1b + final val iload_2 = 0x1c + final val iload_3 = 0x1d + final val lload_0 = 0x1e + final val lload_1 = 0x1f + final val lload_2 = 0x20 + final val lload_3 = 0x21 + final val fload_0 = 0x22 + final val fload_1 = 0x23 + final val fload_2 = 0x24 + final val fload_3 = 0x25 + final val dload_0 = 0x26 + final val dload_1 = 0x27 + final val dload_2 = 0x28 + final val dload_3 = 0x29 + final val aload_0 = 0x2a + final val aload_1 = 0x2b + final val aload_2 = 0x2c + final val aload_3 = 0x2d + final val iaload = 0x2e + final val laload = 0x2f + final val faload = 0x30 + final val daload = 0x31 + final val aaload = 0x32 + final val baload = 0x33 + final val caload = 0x34 + final val saload = 0x35 + + final val istore = 0x36 + final val lstore = 0x37 + final val fstore = 0x38 + final val dstore = 0x39 + final val astore = 0x3a + final val istore_0 = 0x3b + final val istore_1 = 0x3c + final val istore_2 = 0x3d + final val istore_3 = 0x3e + final val lstore_0 = 0x3f + final val lstore_1 = 0x40 + final val lstore_2 = 0x41 + final val lstore_3 = 0x42 + final val fstore_0 = 0x43 + final val fstore_1 = 0x44 + final val fstore_2 = 0x45 + final val fstore_3 = 0x46 + final val dstore_0 = 0x47 + final val dstore_1 = 0x48 + final val dstore_2 = 0x49 + final val dstore_3 = 0x4a + final val astore_0 = 0x4b + final val astore_1 = 0x4c + final val astore_2 = 0x4d + final val astore_3 = 0x4e + final val iastore = 0x4f + final val lastore = 0x50 + final val fastore = 0x51 + final val dastore = 0x52 + final val aastore = 0x53 + final val bastore = 0x54 + final val castore = 0x55 + final val sastore = 0x56 + + final val pop = 0x57 + final val pop2 = 0x58 + final val dup = 0x59 + final val dup_x1 = 0x5a + final val dup_x2 = 0x5b + final val dup2 = 0x5c + final val dup2_x1 = 0x5d + final val dup2_x2 = 0x5e + final val swap = 0x5f + + final val iadd = 0x60 + final val ladd = 0x61 + final val fadd = 0x62 + final val dadd = 0x63 + final val isub = 0x64 + final val lsub = 0x65 + final val fsub = 0x66 + final val dsub = 0x67 + final val imul = 0x68 + final val lmul = 0x69 + final val fmul = 0x6a + final val dmul = 0x6b + final val idiv = 0x6c + final val ldiv = 0x6d + final val fdiv = 0x6e + final val ddiv = 0x6f + final val irem = 0x70 + final val lrem = 0x71 + final val frem = 0x72 + final val drem = 0x73 + + final val ineg = 0x74 + final val lneg = 0x75 + final val fneg = 0x76 + final val dneg = 0x77 + + final val ishl = 0x78 + final val lshl = 0x79 + final val ishr = 0x7a + final val lshr = 0x7b + final val iushr = 0x7c + final val lushr = 0x7d + final val iand = 0x7e + final val land = 0x7f + final val ior = 0x80 + final val lor = 0x81 + final val ixor = 0x82 + final val lxor = 0x83 + final val iinc = 0x84 + + final val i2l = 0x85 + final val i2f = 0x86 + final val i2d = 0x87 + final val l2i = 0x88 + final val l2f = 0x89 + final val l2d = 0x8a + final val f2i = 0x8b + final val f2l = 0x8c + final val f2d = 0x8d + final val d2i = 0x8e + final val d2l = 0x8f + final val d2f = 0x90 + final val i2b = 0x91 + final val i2c = 0x92 + final val i2s = 0x93 + + final val lcmp = 0x94 + final val fcmpl = 0x95 + final val fcmpg = 0x96 + final val dcmpl = 0x97 + final val dcmpg = 0x98 + + final val ifeq = 0x99 + final val ifne = 0x9a + final val iflt = 0x9b + final val ifge = 0x9c + final val ifgt = 0x9d + final val ifle = 0x9e + final val if_icmpeq = 0x9f + final val if_icmpne = 0xa0 + final val if_icmplt = 0xa1 + final val if_icmpge = 0xa2 + final val if_icmpgt = 0xa3 + final val if_icmple = 0xa4 + final val if_acmpeq = 0xa5 + final val if_acmpne = 0xa6 + final val goto = 0xa7 + final val jsr = 0xa8 + final val ret = 0xa9 + final val tableswitch = 0xaa + final val lookupswitch = 0xab + final val ireturn = 0xac + final val lreturn = 0xad + final val freturn = 0xae + final val dreturn = 0xaf + final val areturn = 0xb0 + final val return_ = 0xb1 + + final val gestatic = 0xb2 + final val putstatic = 0xb3 + final val getfield = 0xb4 + final val putfield = 0xb5 + + final val invokevirtual = 0xb6 + final val invokespecial = 0xb7 + final val invokestatic = 0xb8 + final val invokeinterface = 0xb9 + final val xxxunusedxxxx = 0xba + + final val new_ = 0xbb + final val newarray = 0xbc + final val anewarray = 0xbd + final val arraylength = 0xbe + final val athrow = 0xbf + final val checkcast = 0xc0 + final val instanceof = 0xc1 + final val monitorenter = 0xc2 + final val monitorexit = 0xc3 + final val wide = 0xc4 + final val multianewarray = 0xc5 + final val ifnull = 0xc6 + final val ifnonnull = 0xc7 + final val goto_w = 0xc8 + final val jsr_w = 0xc9 + + // reserved opcodes + final val breakpoint = 0xca + final val impdep1 = 0xfe + final val impdep2 = 0xff } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index a9e0daae5d..34f68f9f67 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -37,18 +37,18 @@ abstract class ClassfileParser { import ClassfileConstants._ import Flags._ - private var in: AbstractFileReader = _ // the class file - private var clazz: Symbol = _ // the class symbol containing dynamic members - private var staticModule: Symbol = _ // the module symbol containing static members - private var instanceDefs: Scope = _ // the scope of all instance definitions - private var staticDefs: Scope = _ // the scope of all static definitions - private var pool: ConstantPool = _ // the classfile's constant pool - private var isScala: boolean = _ // does class file describe a scala class? - private var hasMeta: boolean = _ // does class file contain jaco meta attribute?s - private var busy: boolean = false // lock to detect recursive reads - private var classTParams: Map[Name,Symbol] = + protected var in: AbstractFileReader = _ // the class file reader + protected var clazz: Symbol = _ // the class symbol containing dynamic members + protected var staticModule: Symbol = _ // the module symbol containing static members + protected var instanceDefs: Scope = _ // the scope of all instance definitions + protected var staticDefs: Scope = _ // the scope of all static definitions + protected var pool: ConstantPool = _ // the classfile's constant pool + protected var isScala: boolean = _ // does class file describe a scala class? + protected var hasMeta: boolean = _ // does class file contain jaco meta attribute?s + protected var busy: boolean = false // lock to detect recursive reads + protected var classTParams: Map[Name,Symbol] = collection.immutable.ListMap.Empty[Name,Symbol] - private val fresh = new scala.tools.nsc.util.FreshNameCreator + protected val fresh = new scala.tools.nsc.util.FreshNameCreator private object metaParser extends MetaParser { val global: ClassfileParser.this.global.type = ClassfileParser.this.global @@ -65,6 +65,10 @@ abstract class ClassfileParser { } assert(!busy) busy = true + if (root.isInstanceOf[ClassSymbol]) { + root.asInstanceOf[ClassSymbol].classFile = file + } + this.in = new AbstractFileReader(file) if (root.isModule) { this.clazz = root.linkedClass @@ -86,7 +90,7 @@ abstract class ClassfileParser { busy = false } - private def statics: Symbol = staticModule.moduleClass + protected def statics: Symbol = staticModule.moduleClass private def parseHeader: unit = { val magic = in.nextInt @@ -168,6 +172,44 @@ abstract class ClassfileParser { c } + def getMemberSymbol(index: Int, static: Boolean): Symbol = { + if (index <= 0 || len <= index) errorBadIndex(index) + var f = values(index).asInstanceOf[Symbol] + if (f == null) { + val start = starts(index) + if (in.buf(start) != CONSTANT_FIELDREF && + in.buf(start) != CONSTANT_METHODREF && + in.buf(start) != CONSTANT_INTFMETHODREF) errorBadTag(start) + val cls = getClassSymbol(in.getChar(start + 1)) + val Pair(name, tpe) = getNameAndType(in.getChar(start + 3), cls); + f = ((if (static) cls.linkedModule.moduleClass else cls) + .info.decl(name).suchThat(s => s.tpe =:= tpe)); + assert(f != NoSymbol, "Could not find symbol for " + name + ": " + tpe + " in " + cls); + values(index) = f + } + f + } + + def getNameAndType(index: Int, ownerClass: Symbol): Pair[Name, Type] = { + if (index <= 0 || len <= index) errorBadIndex(index) + var p = values(index).asInstanceOf[Pair[Name, Type]] + if (p == null) { + val start = starts(index) + if (in.buf(start) != CONSTANT_NAMEANDTYPE) errorBadTag(start) + val name = getName(in.getChar(start + 1)) + var tpe = getType(in.getChar(start + 3)) + if (name == nme.CONSTRUCTOR) + tpe match { + case MethodType(formals, restpe) => + assert(restpe.symbol == definitions.UnitClass) + tpe = MethodType(formals, ownerClass.tpe) + } + + p = Pair(name, tpe) + } + p + } + def getType(index: int): Type = sigToType(getExternalName(index)) @@ -200,7 +242,7 @@ abstract class ClassfileParser { /** Throws an exception signaling a bad constant index. */ private def errorBadIndex(index: int) = - throw new RuntimeException("bad constant pool index: " + index) + throw new RuntimeException("bad constant pool index: " + index + " at pos: " + in.bp) /** Throws an exception signaling a bad tag at given address. */ private def errorBadTag(start: int) = @@ -211,7 +253,7 @@ abstract class ClassfileParser { var index = 0 val end = name.length def objToAny(tp: Type): Type = - if (tp.symbol == definitions.ObjectClass) definitions.AnyClass.tpe + if (!global.phase.erasedTypes && tp.symbol == definitions.ObjectClass) definitions.AnyClass.tpe else tp def paramsigs2types: List[Type] = if (name(index) == ')') { index = index + 1; List() } @@ -482,6 +524,7 @@ abstract class ClassfileParser { def parseAttribute(): unit = { val attrName = pool.getName(in.nextChar) val attrLen = in.nextInt + val oldpb = in.bp; attrName match { case nme.SignatureATTR => if (global.settings.Xgenerics.value) { @@ -508,9 +551,10 @@ abstract class ClassfileParser { if (c1 != null) sym.setInfo(ConstantType(c1)) else System.out.println("failure to convert "+c+" to "+symtype);//debug case nme.InnerClassesATTR => - parseInnerClasses() + if (!isScala) parseInnerClasses() else in.skip(attrLen) case nme.ScalaSignatureATTR => unpickler.unpickle(in.buf, in.bp, clazz, staticModule, in.file.toString()) + in.skip(attrLen); this.isScala = true case nme.JacoMetaATTR => val meta = pool.getName(in.nextChar).toString().trim() @@ -617,13 +661,13 @@ abstract class ClassfileParser { } } - private def getOwner(flags: int): Symbol = + protected def getOwner(flags: int): Symbol = if ((flags & JAVA_ACC_STATIC) != 0) statics else clazz - private def getScope(flags: int): Scope = + protected def getScope(flags: int): Scope = if ((flags & JAVA_ACC_STATIC) != 0) staticDefs else instanceDefs - private def transFlags(flags: int): long = { + protected def transFlags(flags: int): long = { var res = 0l if ((flags & JAVA_ACC_PRIVATE) != 0) res = res | PRIVATE |