Skip to content

Commit

Permalink
Avoid using Names for fully qualified class names
Browse files Browse the repository at this point in the history
There is no good reason for these dotted names to be
Names and stick around in the name table. Let's use
short lived strings instead.

Reduces the name table by 5% in terms of entries and 10%
in terms of characters when compiling src/scalap/**/*.scala
  • Loading branch information
retronym committed Mar 1, 2019
1 parent ed8d95e commit ae18049
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 94 deletions.
3 changes: 3 additions & 0 deletions src/compiler/scala/tools/nsc/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,9 @@ class Global(var currentSettings: Settings, reporter0: LegacyReporter)

reporting.summarizeErrors()

// val allNamesArray: Array[String] = allNames().map(_.toString).toArray.sorted
// allNamesArray.foreach(println(_))

if (traceSymbolActivity)
units map (_.body) foreach (traceSymbols recordSymbolsInTree _)

Expand Down
80 changes: 41 additions & 39 deletions src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
protected var isScala: Boolean = _ // does class file describe a scala class?
protected var isScalaRaw: Boolean = _ // this class file is a scala class with no pickled info
protected var busy: Symbol = _ // lock to detect recursive reads
protected var currentClass: Name = _ // JVM name of the current class
protected var currentClass: String = _ // JVM name of the current class
protected var classTParams = Map[Name,Symbol]()
protected var srcfile0 : Option[AbstractFile] = None
protected def moduleClass: Symbol = staticModule.moduleClass
Expand Down Expand Up @@ -177,9 +177,9 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
}
}

def getClassSymbol(name: Name): Symbol = {
def getClassSymbol(name: String): Symbol = {
name match {
case name if nme.isModuleName(name) => rootMirror getModuleByName name.dropModule
case name if name.endsWith(nme.MODULE_SUFFIX_STRING) => rootMirror getModuleByName newTermName(name).dropModule
case name => classNameToSymbol(name)
}
}
Expand Down Expand Up @@ -252,7 +252,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
values(index) match {
case sym: Symbol => sym
case _ =>
val result = ClassfileParser.this.getClassSymbol(getClassName(index).name)
val result = ClassfileParser.this.getClassSymbol(getClassName(index).value)
recordAtIndex(result, index)
}
}
Expand Down Expand Up @@ -303,7 +303,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
val name = getClassName(index)
name.value.charAt(0) match {
case ARRAY_TAG => recordAtIndex(sigToType(null, name.value), index)
case _ => recordAtIndex(classNameToSymbol(name.name), index).tpe_*
case _ => recordAtIndex(classNameToSymbol(name.value), index).tpe_*
}
}
}
Expand Down Expand Up @@ -404,13 +404,13 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
NoSymbol.newStubSymbol(name.toTypeName, msg)
}

private def lookupClass(name: Name) = try {
private def lookupClass(name: String) = try {
def lookupTopLevel = {
if (name containsChar '.')
if (name contains '.')
rootMirror getClassByName name
else
// FIXME - we shouldn't be doing ad hoc lookups in the empty package, getClassByName should return the class
definitions.getMember(rootMirror.EmptyPackageClass, name.toTypeName)
definitions.getMember(rootMirror.EmptyPackageClass, newTypeName(name))
}

// For inner classes we usually don't get here: `classNameToSymbol` already returns the symbol
Expand All @@ -421,21 +421,23 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
// what the logic below is for (see PR #5822 / scala/bug#9937).
val split = if (isScalaRaw) -1 else name.lastIndexOf('$')
if (split > 0 && split < name.length) {
val outerName = name.subName(0, split)
val innerName = name.subName(split + 1, name.length).toTypeName
val outerName = name.substring(0, split)
val innerName = name.substring(split + 1, name.length)
val outerSym = classNameToSymbol(outerName)

// If the outer class C cannot be found, look for a top-level class C$D
if (outerSym.isInstanceOf[StubSymbol]) lookupTopLevel
else {
val innerNameAsName = newTypeName(innerName)

// We have a java-defined class name C$D and look for a member D of C. But we don't know if
// D is declared static or not, so we have to search both in class C and its companion.
val r = if (outerSym == clazz)
staticScope.lookup(innerName) orElse
instanceScope.lookup(innerName)
staticScope.lookup(innerNameAsName) orElse
instanceScope.lookup(innerNameAsName)
else
lookupMemberAtTyperPhaseIfPossible(outerSym, innerName) orElse
lookupMemberAtTyperPhaseIfPossible(outerSym.companionModule, innerName)
lookupMemberAtTyperPhaseIfPossible(outerSym, innerNameAsName) orElse
lookupMemberAtTyperPhaseIfPossible(outerSym.companionModule, innerNameAsName)
r orElse lookupTopLevel
}
} else
Expand All @@ -451,11 +453,11 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
// definitions.getMember can throw a FatalError, for example in pos/t5165b
if (settings.debug)
ex.printStackTrace()
stubClassSymbol(name)
stubClassSymbol(newTypeName(name))
}

/** Return the class symbol of the given name. */
def classNameToSymbol(name: Name): Symbol = {
def classNameToSymbol(name: String): Symbol = {
if (innerClasses contains name)
innerClasses innerSymbol name
else
Expand All @@ -467,10 +469,10 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {

val jflags = readClassFlags()
val classNameIndex = u2
currentClass = pool.getClassName(classNameIndex).name
currentClass = pool.getClassName(classNameIndex).value

// Ensure that (top-level) classfiles are in the correct directory
val isTopLevel = !(currentClass containsChar '$') // Java class name; *don't* try to to use Scala name decoding (scala/bug#7532)
val isTopLevel = !(currentClass contains '$') // Java class name; *don't* try to to use Scala name decoding (scala/bug#7532)
if (isTopLevel) {
val c = pool.getClassSymbol(classNameIndex)
// scala-dev#248: when a type alias (in a package object) shadows a class symbol, getClassSymbol returns a stub
Expand Down Expand Up @@ -633,10 +635,10 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
assert(sig.charAt(index) == ch, (sig.charAt(index), ch))
index += 1
}
def subName(isDelimiter: Char => Boolean): Name = {
def subName(isDelimiter: Char => Boolean): String = {
val start = index
while (!isDelimiter(sig.charAt(index))) { index += 1 }
newTermName(sigChars, start, index - start)
new String(sigChars, start, index - start)
}
def sig2type(tparams: immutable.Map[Name,Symbol], skiptvs: Boolean): Type = {
val tag = sig.charAt(index); index += 1
Expand Down Expand Up @@ -708,7 +710,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
var tpe = processClassType(processInner(classSym.tpe_*))
while (sig.charAt(index) == '.') {
accept('.')
val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName
val name = newTypeName(subName(c => c == ';' || c == '<' || c == '.'))
val clazz = tpe.member(name)
val dummyArgs = Nil // the actual arguments are added in processClassType
val inner = typeRef(pre = tpe, sym = clazz, args = dummyArgs)
Expand Down Expand Up @@ -745,7 +747,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
sig2type(tparams, skiptvs)
JavaMethodType(sym.newSyntheticValueParams(paramtypes.toList), restype)
case 'T' =>
val n = subName(';'.==).toTypeName
val n = newTypeName(subName(';'.==))
index += 1
if (skiptvs) AnyTpe
else tparams(n).typeConstructor
Expand All @@ -769,15 +771,15 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
index += 1
val start = index
while (sig.charAt(index) != '>') {
val tpname = subName(':'.==).toTypeName
val tpname = newTypeName(subName(':'.==))
val s = sym.newTypeParameter(tpname)
tparams = tparams + (tpname -> s)
sig2typeBounds(tparams, skiptvs = true)
newTParams += s
}
index = start
while (sig.charAt(index) != '>') {
val tpname = subName(':'.==).toTypeName
val tpname = newTypeName(subName(':'.==))
val s = tparams(tpname)
s.setInfo(sig2typeBounds(tparams, skiptvs = false))
}
Expand Down Expand Up @@ -999,8 +1001,8 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
* and implicitly current class' superclasses.
*/
private def enterOwnInnerClasses(): Unit = {
def className(name: Name): Name =
name.subName(name.lastPos('.') + 1, name.length)
def className(name: String): String =
name.substring(name.lastIndexOf('.') + 1, name.length)

def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile): Unit = {
def jflags = entry.jflags
Expand Down Expand Up @@ -1048,8 +1050,8 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
decls unlink e
}

val cName = className(entry.externalName)
unlinkIfPresent(cName.toTermName)
val cName = newTermName(className(entry.externalName))
unlinkIfPresent(cName)
unlinkIfPresent(cName.toTypeName)
}

Expand Down Expand Up @@ -1195,15 +1197,15 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {

/** An entry in the InnerClasses attribute of this class file. */
case class InnerClassEntry(external: NameOrString, outer: NameOrString, name: NameOrString, jflags: JavaAccFlags) {
def externalName = external.name
def outerName = outer.name
def externalName = external.value
def outerName = outer.value
def originalName = name.name
def isModule = originalName.isTermName
def scope = if (jflags.isStatic) staticScope else instanceScope
def enclosing = if (jflags.isStatic) enclModule else enclClass

// The name of the outer class, without its trailing $ if it has one.
private def strippedOuter = outerName.dropModule
private def strippedOuter = outerName.stripSuffix(nme.MODULE_SUFFIX_STRING)
private def isInner = innerClasses contains strippedOuter
private def enclClass = if (isInner) innerClasses innerSymbol strippedOuter else classNameToSymbol(strippedOuter)
private def enclModule = enclClass.companionModule
Expand All @@ -1215,10 +1217,10 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
* If the given name is not an inner class, it returns the symbol found in `definitions`.
*/
object innerClasses {
private val inners = mutable.HashMap[Name, InnerClassEntry]()
private val inners = mutable.HashMap[String, InnerClassEntry]()

def contains(name: Name) = inners contains name
def getEntry(name: Name) = inners get name
def contains(name: String) = inners contains name
def getEntry(name: String) = inners get name
def entries = inners.values

def add(entry: InnerClassEntry): Unit = {
Expand All @@ -1228,7 +1230,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
}
inners(entry.externalName) = entry
}
def innerSymbol(externalName: Name): Symbol = this getEntry externalName match {
def innerSymbol(externalName: String): Symbol = this getEntry externalName match {
case Some(entry) => innerSymbol(entry)
case _ => NoSymbol
}
Expand Down Expand Up @@ -1270,8 +1272,8 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
private final class ClassTypeCompleter(name: Name, jflags: JavaAccFlags, parent: NameOrString, ifaces: List[NameOrString]) extends JavaTypeCompleter {
override def complete(sym: symbolTable.Symbol): Unit = {
val info = if (sig != null) sigToType(sym, sig) else {
val superTpe = if (parent == null) definitions.AnyClass.tpe_* else getClassSymbol(parent.name).tpe_*
var ifacesTypes = ifaces.filterNot(_ eq null).map(x => getClassSymbol(x.name).tpe_*)
val superTpe = if (parent == null) definitions.AnyClass.tpe_* else getClassSymbol(parent.value).tpe_*
var ifacesTypes = ifaces.filterNot(_ eq null).map(x => getClassSymbol(x.value).tpe_*)
ClassInfoType(superTpe :: ifacesTypes, instanceScope, clazz)
}
sym.setInfo(info)
Expand All @@ -1280,7 +1282,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {

private final class MemberTypeCompleter(name: Name, jflags: JavaAccFlags, descriptor: String) extends JavaTypeCompleter {
override def isJavaVarargsMethod: Boolean = jflags.isVarargs
override def javaThrownExceptions: List[Symbol] = exceptions.map(e => classNameToSymbol(e.name))
override def javaThrownExceptions: List[Symbol] = exceptions.map(e => classNameToSymbol(e.value))
override def complete(sym: symbolTable.Symbol): Unit = {
def descriptorInfo = sigToType(sym, descriptor)
val hasOuterParam = (name == nme.CONSTRUCTOR) && (descriptorInfo match {
Expand Down Expand Up @@ -1337,7 +1339,7 @@ abstract class ClassfileParser(reader: ReusableInstance[ReusableDataReader]) {
for (e <- exceptions) {
// we call initialize due to the fact that we call Symbol.isMonomorphicType in addThrowsAnnotation
// and that method requires Symbol to be forced to give the right answers, see scala/bug#7107 for details
val cls = getClassSymbol(e.name)
val cls = getClassSymbol(e.value)
sym withAnnotation AnnotationInfo.lazily {
val throwableTpe = cls.tpe_*
AnnotationInfo(appliedType(ThrowsClass, throwableTpe), List(Literal(Constant(throwableTpe))), Nil)
Expand Down
20 changes: 10 additions & 10 deletions src/reflect/scala/reflect/internal/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,11 @@ trait Definitions extends api.StandardDefinitions {

// It becomes tricky to create dedicated objects for other symbols because
// of initialization order issues.
lazy val JavaLangPackage = getPackage(TermName("java.lang"))
lazy val JavaLangPackage = getPackage("java.lang")
lazy val JavaLangPackageClass = JavaLangPackage.moduleClass.asClass
lazy val ScalaPackage = getPackage(TermName("scala"))
lazy val ScalaPackage = getPackage("scala")
lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClass
lazy val RuntimePackage = getPackage(TermName("scala.runtime"))
lazy val RuntimePackage = getPackage("scala.runtime")
lazy val RuntimePackageClass = RuntimePackage.moduleClass.asClass

def javaTypeToValueClass(jtype: Class[_]): Symbol = jtype match {
Expand Down Expand Up @@ -290,7 +290,7 @@ trait Definitions extends api.StandardDefinitions {
// top types
lazy val AnyClass = enterNewClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT) markAllCompleted
lazy val AnyRefClass = newAlias(ScalaPackageClass, tpnme.AnyRef, ObjectTpe) markAllCompleted
lazy val ObjectClass = getRequiredClass(sn.Object.toString)
lazy val ObjectClass = getRequiredClass("java.lang.Object")

// Cached types for core monomorphic classes
lazy val AnyRefTpe = AnyRefClass.tpe
Expand Down Expand Up @@ -341,12 +341,12 @@ trait Definitions extends api.StandardDefinitions {

// exceptions and other throwables
lazy val ClassCastExceptionClass = requiredClass[ClassCastException]
lazy val IndexOutOfBoundsExceptionClass = getClassByName(sn.IOOBException)
lazy val InvocationTargetExceptionClass = getClassByName(sn.InvTargetException)
lazy val IndexOutOfBoundsExceptionClass = getClassByName("java.lang.IndexOutOfBoundsException")
lazy val InvocationTargetExceptionClass = getClassByName("java.lang.reflect.InvocationTargetException")
lazy val MatchErrorClass = requiredClass[MatchError]
lazy val NonLocalReturnControlClass = requiredClass[scala.runtime.NonLocalReturnControl[_]]
lazy val NullPointerExceptionClass = getClassByName(sn.NPException)
lazy val ThrowableClass = getClassByName(sn.Throwable)
lazy val NullPointerExceptionClass = getClassByName("java.lang.NullPointerException")
lazy val ThrowableClass = getClassByName("java.lang.Throwable")
lazy val UninitializedErrorClass = requiredClass[UninitializedFieldError]
lazy val RuntimeExceptionClass = requiredClass[RuntimeException]
lazy val IllegalArgExceptionClass = requiredClass[IllegalArgumentException]
Expand Down Expand Up @@ -497,7 +497,7 @@ trait Definitions extends api.StandardDefinitions {

// reflection / structural types
lazy val SoftReferenceClass = requiredClass[java.lang.ref.SoftReference[_]]
lazy val MethodClass = getClassByName(sn.MethodAsObject)
lazy val MethodClass = getClassByName("java.lang.reflect.Method")
lazy val EmptyMethodCacheClass = requiredClass[scala.runtime.EmptyMethodCache]
lazy val MethodCacheClass = requiredClass[scala.runtime.MethodCache]
def methodCache_find = getMemberMethod(MethodCacheClass, nme.find_)
Expand Down Expand Up @@ -1310,7 +1310,7 @@ trait Definitions extends api.StandardDefinitions {
// Trying to allow for deprecated locations
sym.isAliasType && isMetaAnnotation(sym.info.typeSymbol)
)
lazy val metaAnnotations: Set[Symbol] = getPackage(TermName("scala.annotation.meta")).info.members filter (_ isSubClass StaticAnnotationClass) toSet
lazy val metaAnnotations: Set[Symbol] = getPackage("scala.annotation.meta").info.members filter (_ isSubClass StaticAnnotationClass) toSet

// According to the scala.annotation.meta package object:
// * By default, annotations on (`val`-, `var`- or plain) constructor parameters
Expand Down
Loading

0 comments on commit ae18049

Please sign in to comment.