summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2006-08-15 09:25:53 +0000
committerIulian Dragos <jaguarul@gmail.com>2006-08-15 09:25:53 +0000
commit6d236c4abdfbb0af8867a64461f69b9eecbeb279 (patch)
treeb0cdfd5c3d3684a2da86f8e86b1b5074ff5a6f1c
parent6f141280bf6d375151f497e6e4ee0ff601d53ac0 (diff)
downloadscala-6d236c4abdfbb0af8867a64461f69b9eecbeb279.tar.gz
scala-6d236c4abdfbb0af8867a64461f69b9eecbeb279.tar.bz2
scala-6d236c4abdfbb0af8867a64461f69b9eecbeb279.zip
Added InnerClasses attribute in classfiles
-rw-r--r--lib/fjbg.jar.desired.sha12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala39
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala234
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala80
5 files changed, 337 insertions, 22 deletions
diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1
index cb6e38726d..b8280737c4 100644
--- a/lib/fjbg.jar.desired.sha1
+++ b/lib/fjbg.jar.desired.sha1
@@ -1 +1 @@
-3f279fef71e48b40092b68f5154392fceb10b351 ?fjbg.jar
+d2d42638b37667d365da5ae5be1db85fc03a177e ?fjbg.jar
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