diff options
author | Paul Phillips <paulp@improving.org> | 2011-05-09 19:07:40 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-05-09 19:07:40 +0000 |
commit | 1a92fb60e6853fca4b4e5bd0d03f913c300100ae (patch) | |
tree | b287e88e828d2dd788d6b9c1bb0242ae4f03c21b | |
parent | 41ac77599ce022087ec595b6da4874b39472019b (diff) | |
download | scala-1a92fb60e6853fca4b4e5bd0d03f913c300100ae.tar.gz scala-1a92fb60e6853fca4b4e5bd0d03f913c300100ae.tar.bz2 scala-1a92fb60e6853fca4b4e5bd0d03f913c300100ae.zip |
Another round of optimization.
exciting as the original, but not a bad way to spend a rainy afternoon.
Most changes involve files and paths, which are we find exercised rather
heavily at startup. This patch takes about 15 seconds off my time to
build quick. No review.
-rw-r--r-- | src/compiler/scala/tools/nsc/io/AbstractFile.scala | 26 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/Path.scala | 17 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Definitions.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/ClassPath.scala | 42 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/StringBuilder.scala | 11 | ||||
-rwxr-xr-x | src/library/scala/reflect/generic/Flags.scala | 39 |
6 files changed, 99 insertions, 38 deletions
diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala index 12a632fca6..059ca9bd9e 100644 --- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala +++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala @@ -19,7 +19,7 @@ import scala.collection.mutable.ArrayBuffer */ object AbstractFile { /** Returns "getFile(new File(path))". */ - def getFile(path: String): AbstractFile = getFile(Path(path)) + def getFile(path: String): AbstractFile = getFile(File(path)) def getFile(path: Path): AbstractFile = getFile(path.toFile) /** @@ -42,7 +42,7 @@ object AbstractFile { */ def getDirectory(file: File): AbstractFile = if (file.isDirectory) new PlainFile(file) - else if (file.isFile && Path.isJarOrZip(file)) ZipArchive fromFile file + else if (file.isFile && Path.isExtensionJarOrZip(file.jfile)) ZipArchive fromFile file else null /** @@ -54,7 +54,7 @@ object AbstractFile { * @return ... */ def getURL(url: URL): AbstractFile = { - if (url == null || !Path.isJarOrZip(url.getPath)) null + if (url == null || !Path.isExtensionJarOrZip(url.getPath)) null else ZipArchive fromURL url } } @@ -92,7 +92,8 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { def path: String /** Checks extension case insensitively. */ - def hasExtension(other: String) = Path(path) hasExtension other + def hasExtension(other: String) = extension == other.toLowerCase + private lazy val extension: String = Path.extension(name) /** The absolute file, if this is a relative file. */ def absolute: AbstractFile @@ -102,7 +103,6 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { /** Returns the underlying File if any and null otherwise. */ def file: JFile - def sfile = Option(file) map (x => File(x)) // XXX /** An underlying source, if known. Mostly, a zip/jar file. */ def underlyingSource: Option[AbstractFile] = None @@ -111,7 +111,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { def exists: Boolean = (file eq null) || file.exists /** Does this abstract file represent something which can contain classfiles? */ - def isClassContainer = isDirectory || (sfile exists (Path isJarOrZip _)) + def isClassContainer = isDirectory || (file != null && (extension == "jar" || extension == "zip")) /** Create a file on disk, if one does not exist already. */ def create(): Unit @@ -217,13 +217,23 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { file } + private def fileOrSubdirectoryNamed(name: String, isDir: Boolean): AbstractFile = { + val lookup = lookupName(name, isDir) + if (lookup != null) lookup + else { + val jfile = new JFile(file, name) + if (isDir) jfile.mkdirs() else jfile.createNewFile() + new PlainFile(jfile) + } + } + /** * Get the file in this directory with the given name, * creating an empty file if it does not already existing. */ def fileNamed(name: String): AbstractFile = { assert(isDirectory, "Tried to find '%s' in '%s' but it is not a directory".format(name, path)) - Option(lookupName(name, false)) getOrElse new PlainFile((sfile.get / name).createFile()) + fileOrSubdirectoryNamed(name, false) } /** @@ -232,7 +242,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { */ def subdirectoryNamed(name: String): AbstractFile = { assert (isDirectory, "Tried to find '%s' in '%s' but it is not a directory".format(name, path)) - Option(lookupName(name, true)) getOrElse new PlainFile((sfile.get / name).createDirectory()) + fileOrSubdirectoryNamed(name, true) } protected def unsupported(): Nothing = unsupported(null) diff --git a/src/compiler/scala/tools/nsc/io/Path.scala b/src/compiler/scala/tools/nsc/io/Path.scala index beae4b8647..86839437f4 100644 --- a/src/compiler/scala/tools/nsc/io/Path.scala +++ b/src/compiler/scala/tools/nsc/io/Path.scala @@ -28,6 +28,19 @@ import scala.util.Random.alphanumeric */ object Path { + def isExtensionJarOrZip(jfile: JFile): Boolean = isExtensionJarOrZip(jfile.getName) + def isExtensionJarOrZip(name: String): Boolean = { + val ext = extension(name) + ext == "jar" || ext == "zip" + } + def extension(name: String): String = { + var i = name.length - 1 + while (i >= 0 && name.charAt(i) != '.') + i -= 1 + + if (i < 0) "" + else name.substring(i + 1).toLowerCase + } def isJarOrZip(f: Path, examineFile: Boolean = true) = Jar.isJarOrZip(f, examineFile) // not certain these won't be problematic, but looks good so far @@ -173,8 +186,8 @@ class Path private[io] (val jfile: JFile) { // } // compares against extensions in a CASE INSENSITIVE way. def hasExtension(ext: String, exts: String*) = { - val xs = (ext +: exts) map (_.toLowerCase) - xs contains extension.toLowerCase + val lower = extension.toLowerCase + ext.toLowerCase == lower || exts.exists(_.toLowerCase == lower) } // returns the filename without the extension. def stripExtension: String = name stripSuffix ("." + extension) diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 005a3c87ed..6b419c629d 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -316,7 +316,7 @@ trait Definitions extends reflect.generic.StandardDefinitions { lazy val TraversableClass = getClass("scala.collection.Traversable") lazy val ListModule = getModule("scala.collection.immutable.List") - def List_apply = getMember(ListModule, nme.apply) + lazy val List_apply = getMember(ListModule, nme.apply) lazy val NilModule = getModule("scala.collection.immutable.Nil") lazy val SeqModule = getModule("scala.collection.Seq") diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index e1cf6e55d9..c3731150c4 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -8,7 +8,7 @@ package scala.tools.nsc package util import java.net.URL -import scala.collection.mutable +import scala.collection.{ mutable, immutable } import io.{ File, Directory, Path, Jar, AbstractFile, ClassAndJarInfo } import scala.tools.util.StringOps.splitWhere import Jar.isJarOrZip @@ -103,8 +103,10 @@ object ClassPath { /** Expand dir out to contents, a la extdir */ def expandDir(extdir: String): List[String] = { - val dir = Option(AbstractFile getDirectory extdir) getOrElse (return Nil) - dir filter (_.isClassContainer) map (dir.sfile.get / _.name path) toList + AbstractFile getDirectory extdir match { + case null => Nil + case dir => dir filter (_.isClassContainer) map (x => new java.io.File(dir.file, x.name) getPath) toList + } } /** A useful name filter. */ @@ -298,7 +300,10 @@ abstract class ClassPath[T] { class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends ClassPath[T] { def name = dir.name override def origin = dir.underlyingSource map (_.path) - def asURLs = dir.sfile.toList map (_.toURL) + def asURLs = dir.file match { + case null => Nil + case file => File(file).toURL :: Nil + } def asClasspathString = dir.path val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq(dir) @@ -321,19 +326,30 @@ class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[AbstractFile]) extends ClassPath[AbstractFile] { def name = dir.name override def origin = dir.underlyingSource map (_.path) - def asURLs = dir.sfile.toList map (_.toURL) + def asURLs = dir.file match { + case null => Nil + case file => File(file).toURL :: Nil + } def asClasspathString = dir.path val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq() - lazy val classes: IndexedSeq[ClassRep] = dir flatMap { f => - if (f.isDirectory || !validClassFile(f.name)) Nil - else List(ClassRep(Some(f), None)) - } toIndexedSeq + lazy val classes: IndexedSeq[ClassRep] = { + val buf = immutable.Vector.newBuilder[ClassRep] + dir foreach { f => + if (!f.isDirectory && validClassFile(f.name)) + buf += ClassRep(Some(f), None) + } + buf.result + } - lazy val packages: IndexedSeq[DirectoryClassPath] = dir flatMap { f => - if (f.isDirectory && validPackage(f.name)) List(new DirectoryClassPath(f, context)) - else Nil - } toIndexedSeq + lazy val packages: IndexedSeq[DirectoryClassPath] = { + val buf = immutable.Vector.newBuilder[DirectoryClassPath] + dir foreach { f => + if (f.isDirectory && validPackage(f.name)) + buf += new DirectoryClassPath(f, context) + } + buf.result + } override def toString() = "directory classpath: "+ dir } diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index edd59a8221..8d7ed8bcd2 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -171,6 +171,17 @@ final class StringBuilder(private val underlying: JavaStringBuilder) */ def +=(x: Char): this.type = { append(x); this } + /** Optimization. + */ + def ++=(s: String): this.type = { + underlying append s + this + } + def appendAll(xs: String): StringBuilder = { + underlying append xs + this + } + /** !!! This should create a new sequence. */ def +(x: Char): this.type = { +=(x); this } diff --git a/src/library/scala/reflect/generic/Flags.scala b/src/library/scala/reflect/generic/Flags.scala index d7c8ff9296..3291047831 100755 --- a/src/library/scala/reflect/generic/Flags.scala +++ b/src/library/scala/reflect/generic/Flags.scala @@ -102,7 +102,7 @@ class Flags extends ModifierFlags { final val PickledFlags: Long = 0xFFFFFFFFL - private val rawPickledCorrespondence = List( + private def rawPickledCorrespondence = Array( (IMPLICIT, IMPLICIT_PKL), (FINAL, FINAL_PKL), (PRIVATE, PRIVATE_PKL), @@ -116,20 +116,31 @@ class Flags extends ModifierFlags { (MODULE, MODULE_PKL), (INTERFACE, INTERFACE_PKL) ) - private def mkCorrespondenceArray(correspondence: List[(Int, Int)]) = { - def f(flags: Int): Int = { - correspondence.foldLeft(0) { - case (result, (oldFlag, newFlag)) => - if ((flags & oldFlag) != 0) result | newFlag - else result - } + private val rawFlags: Array[Int] = rawPickledCorrespondence map (_._1) + private val pickledFlags: Array[Int] = rawPickledCorrespondence map (_._2) + + private def r2p(flags: Int): Int = { + var result = 0 + var i = 0 + while (i < rawFlags.length) { + if ((flags & rawFlags(i)) != 0) + result |= pickledFlags(i) + + i += 1 + } + result + } + private def p2r(flags: Int): Int = { + var result = 0 + var i = 0 + while (i < rawFlags.length) { + if ((flags & pickledFlags(i)) != 0) + result |= rawFlags(i) + + i += 1 } - 0 to PKL_MASK map f toArray + result } - /** A map from the raw to pickled flags, and vice versa. - */ - private val r2p = mkCorrespondenceArray(rawPickledCorrespondence) - private val p2r = mkCorrespondenceArray(rawPickledCorrespondence map (_.swap)) // Generated by mkFlagToStringMethod() at Mon Oct 11 10:07:29 PDT 2010 @annotation.switch override def flagToString(flag: Long): String = flag match { @@ -232,7 +243,7 @@ class Flags extends ModifierFlags { // List of the raw flags, in pickled order protected val pickledListOrder: List[Long] = { val all = 0 to 62 map (1L << _) - val front = rawPickledCorrespondence map (_._1.toLong) + val front = rawFlags map (_.toLong) front.toList ++ (all filterNot (front contains _)) } |