summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-07-27 01:38:44 -0700
committerGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-07-27 14:09:39 -0700
commitced7214959c05eb5fcf55b79f4a6691d2d8dc987 (patch)
tree766061115a22d03f76c017a42c5abff0713ee2b3 /src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
parent56b7c0f8fa6c1037905867aec88520476dbd3baa (diff)
downloadscala-ced7214959c05eb5fcf55b79f4a6691d2d8dc987.tar.gz
scala-ced7214959c05eb5fcf55b79f4a6691d2d8dc987.tar.bz2
scala-ced7214959c05eb5fcf55b79f4a6691d2d8dc987.zip
Move ICodeReader-specific logic out of ClassfileParser.
ClassfileParser contained some ICodeReader-specific logic like `forceMangledName` and `getMemberSymbol` methods. The `getMemberSymbol` method was defined in ConstantPool class because it must access some internal state of ConstantPool. In order to move that method to ICodeReader we had two options: 1. Make all internal state accessible from outside of ConstantPool class so getMemberSymbol could be implemented outside of ConstantPool hierarchy 2. Make it possible to subclass ConstantPool in ICodeReader so getMemberSymbol can be implemented in a subclass and can access internal state of ConstantPool Given the fact that getMemberSymbol mutates ConstantPool's internal state I decided that subclassing is a cleaner approach. It required significant refactoring because we had to make sure that we create an instance of proper class when initializing the `pool` variable. I ended up introducing `ConstantPoolManager` class which is essentially a mutable variable that can be reset multiple times. This change makes ClassfileParser independent from the ICodeReader and its implementation details.
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala110
1 files changed, 16 insertions, 94 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 4c0c16690f..e8abeb7674 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -30,12 +30,15 @@ abstract class ClassfileParser {
import scala.reflect.internal.ClassfileConstants._
import Flags._
+ protected type ThisConstantPool <: ConstantPool
+ protected def newConstantPool: ThisConstantPool
+
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 instanceScope: Scope = _ // the scope of all instance definitions
protected var staticScope: Scope = _ // the scope of all static definitions
- protected var pool: ConstantPool = _ // the classfile's constant pool
+ protected var pool: ThisConstantPool = _ // the classfile's constant pool
protected var isScala: Boolean = _ // does class file describe a scala class?
protected var isScalaAnnot: Boolean = _ // does class file describe a scala class with its pickled info in an annotation?
protected var isScalaRaw: Boolean = _ // this class file is a scala class with no pickled info
@@ -119,7 +122,7 @@ abstract class ClassfileParser {
this.isScala = false
parseHeader()
- this.pool = new ConstantPool
+ this.pool = newConstantPool
parseClass()
}
}
@@ -134,11 +137,14 @@ abstract class ClassfileParser {
abort(s"class file ${in.file} has unknown version $major.$minor, should be at least $JAVA_MAJOR_VERSION.$JAVA_MINOR_VERSION")
}
- class ConstantPool {
- private val len = u2
- private val starts = new Array[Int](len)
- private val values = new Array[AnyRef](len)
- private val internalized = new Array[Name](len)
+ /**
+ * Constructor of this class should not be called directly, use `newConstantPool` instead.
+ */
+ protected class ConstantPool {
+ protected val len = u2
+ protected val starts = new Array[Int](len)
+ protected val values = new Array[AnyRef](len)
+ protected val internalized = new Array[Name](len)
{ var i = 1
while (i < starts.length) {
@@ -212,76 +218,13 @@ abstract class ClassfileParser {
getExternalName((in getChar start).toInt)
}
- /** Return the symbol of the class member at `index`.
- * The following special cases exist:
- * - If the member refers to special `MODULE$` static field, return
- * the symbol of the corresponding module.
- * - If the member is a field, and is not found with the given name,
- * another try is made by appending `nme.LOCAL_SUFFIX_STRING`
- * - If no symbol is found in the right tpe, a new try is made in the
- * companion class, in case the owner is an implementation class.
- */
- def getMemberSymbol(index: Int, static: Boolean): Symbol = {
- if (index <= 0 || len <= index) errorBadIndex(index)
- var f = values(index).asInstanceOf[Symbol]
- if (f eq null) {
- val start = starts(index)
- val first = in.buf(start).toInt
- if (first != CONSTANT_FIELDREF &&
- first != CONSTANT_METHODREF &&
- first != CONSTANT_INTFMETHODREF) errorBadTag(start)
- val ownerTpe = getClassOrArrayType(in.getChar(start + 1).toInt)
- debuglog("getMemberSymbol(static: " + static + "): owner type: " + ownerTpe + " " + ownerTpe.typeSymbol.originalName)
- val (name0, tpe0) = getNameAndType(in.getChar(start + 3).toInt, ownerTpe)
- debuglog("getMemberSymbol: name and tpe: " + name0 + ": " + tpe0)
-
- forceMangledName(tpe0.typeSymbol.name, module = false)
- val (name, tpe) = getNameAndType(in.getChar(start + 3).toInt, ownerTpe)
- if (name == nme.MODULE_INSTANCE_FIELD) {
- val index = in.getChar(start + 1).toInt
- val name = getExternalName(in.getChar(starts(index).toInt + 1).toInt)
- //assert(name.endsWith("$"), "Not a module class: " + name)
- f = forceMangledName(name dropRight 1, module = true)
- if (f == NoSymbol)
- f = rootMirror.getModuleByName(name dropRight 1)
- } else {
- val origName = nme.unexpandedName(name)
- val owner = if (static) ownerTpe.typeSymbol.linkedClassOfClass else ownerTpe.typeSymbol
- f = owner.info.findMember(origName, 0, 0, stableOnly = false).suchThat(_.tpe.widen =:= tpe)
- if (f == NoSymbol)
- f = owner.info.findMember(newTermName(origName + nme.LOCAL_SUFFIX_STRING), 0, 0, stableOnly = false).suchThat(_.tpe =:= tpe)
- if (f == NoSymbol) {
- // if it's an impl class, try to find it's static member inside the class
- if (ownerTpe.typeSymbol.isImplClass) {
- f = ownerTpe.findMember(origName, 0, 0, stableOnly = false).suchThat(_.tpe =:= tpe)
- } else {
- log("Couldn't find " + name + ": " + tpe + " inside: \n" + ownerTpe)
- f = tpe match {
- case MethodType(_, _) => owner.newMethod(name.toTermName, owner.pos)
- case _ => owner.newVariable(name.toTermName, owner.pos)
- }
- f setInfo tpe
- log("created fake member " + f.fullName)
- }
- }
- }
- assert(f != NoSymbol,
- s"could not find $name: $tpe in $ownerTpe" + (
- if (settings.debug.value) ownerTpe.members.mkString(", members are:\n ", "\n ", "") else ""
- )
- )
- values(index) = f
- }
- f
- }
-
/** Return a name and a type at the given index. If the type is a method
* type, a dummy symbol is created in `ownerTpe`, which is used as the
* owner of its value parameters. This might lead to inconsistencies,
* if a symbol of the given name already exists, and has a different
* type.
*/
- private def getNameAndType(index: Int, ownerTpe: Type): (Name, Type) = {
+ protected def getNameAndType(index: Int, ownerTpe: Type): (Name, Type) = {
if (index <= 0 || len <= index) errorBadIndex(index)
values(index) match {
case p: ((Name @unchecked, Type @unchecked)) => p
@@ -381,35 +324,14 @@ abstract class ClassfileParser {
}
/** Throws an exception signaling a bad constant index. */
- private def errorBadIndex(index: Int) =
+ protected def errorBadIndex(index: Int) =
abort(s"bad constant pool index: $index at pos: ${in.bp}")
/** Throws an exception signaling a bad tag at given address. */
- private def errorBadTag(start: Int) =
+ protected def errorBadTag(start: Int) =
abort("bad constant pool tag ${in.buf(start)} at byte $start")
}
- /** Try to force the chain of enclosing classes for the given name. Otherwise
- * flatten would not lift classes that were not referenced in the source code.
- */
- def forceMangledName(name: Name, module: Boolean): Symbol = {
- val parts = name.decode.toString.split(Array('.', '$'))
- var sym: Symbol = rootMirror.RootClass
-
- // was "at flatten.prev"
- enteringFlatten {
- for (part0 <- parts; if !(part0 == ""); part = newTermName(part0)) {
- val sym1 = enteringIcode {
- sym.linkedClassOfClass.info
- sym.info.decl(part.encode)
- }//.suchThat(module == _.isModule)
-
- sym = sym1 orElse sym.info.decl(part.encode.toTypeName)
- }
- }
- sym
- }
-
private def loadClassSymbol(name: Name): Symbol = {
val file = global.classPath findSourceFile ("" +name) getOrElse {
// SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented