Skip to content

Commit 720b8a6

Browse files
committed
Avoid temporary strings during classpath lookup
Index the JAR metadata by dotted package name to avoid converting a dotted name to path on each lookup. (cherry picked from commit 6b3f320)
1 parent fdb1000 commit 720b8a6

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ trait ZipArchiveFileLookup[FileEntryType <: ClassRepresentation] extends ClassPa
6868
}
6969

7070
private def findDirEntry(pkg: String): Option[archive.DirEntry] = {
71-
val dirName = FileUtils.dirPath(pkg) + "/"
72-
archive.allDirs.get(dirName)
71+
archive.allDirsByDottedName.get(pkg)
7372
}
7473

7574
protected def createFileEntry(file: FileZipArchive#Entry): FileEntryType

src/reflect/scala/reflect/io/ZipArchive.scala

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,25 @@ object ZipArchive {
6262
if (front) path.substring(0, idx + 1)
6363
else path.substring(idx + 1)
6464
}
65+
def pathToDotted(path: String): String = {
66+
if (path == "/") ""
67+
else {
68+
val slashEnd = path.endsWith("/")
69+
val len = path.length - (if (slashEnd) 1 else 0)
70+
val result = new Array[Char](len)
71+
var i = 0
72+
while (i < len) {
73+
val char = path.charAt(i)
74+
result(i) = if (char == '/') '.' else char
75+
i += 1
76+
}
77+
new String(result)
78+
}
79+
}
80+
def dottedToPath(dotted: String): String = {
81+
val sb = new java.lang.StringBuilder(dotted.length)
82+
dotted.replace('.', '/') + "/"
83+
}
6584
}
6685
import ZipArchive._
6786
/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */
@@ -101,7 +120,7 @@ abstract class ZipArchive(override val file: JFile, release: Option[String]) ext
101120
}
102121
}
103122

104-
private def ensureDir(dirs: mutable.Map[String, DirEntry], path: String, zipEntry: ZipEntry): DirEntry =
123+
private def ensureDir(dirs: mutable.Map[String, DirEntry], path: String, zipEntry: ZipEntry): DirEntry = {
105124
//OPT inlined from getOrElseUpdate; saves ~50K closures on test run.
106125
// was:
107126
// dirs.getOrElseUpdate(path, {
@@ -110,15 +129,17 @@ abstract class ZipArchive(override val file: JFile, release: Option[String]) ext
110129
// parent.entries(baseName(path)) = dir
111130
// dir
112131
// })
113-
dirs get path match {
132+
val dotted = pathToDotted(path)
133+
dirs get dotted match {
114134
case Some(v) => v
115135
case None =>
116136
val parent = ensureDir(dirs, dirName(path), null)
117-
val dir = new DirEntry(path)
137+
val dir = new DirEntry(path)
118138
parent.entries(baseName(path)) = dir
119-
dirs(path) = dir
139+
dirs(dotted) = dir
120140
dir
121141
}
142+
}
122143

123144
protected def getDir(dirs: mutable.Map[String, DirEntry], entry: ZipEntry): DirEntry = {
124145
if (entry.isDirectory) ensureDir(dirs, entry.getName, entry)
@@ -171,9 +192,9 @@ final class FileZipArchive(file: JFile, release: Option[String]) extends ZipArch
171192
override def sizeOption: Option[Int] = Some(zipEntry.getSize.toInt)
172193
}
173194

174-
lazy val (root, allDirs) = {
195+
lazy val (root, allDirsByDottedName) = {
175196
val root = new DirEntry("/")
176-
val dirs = mutable.HashMap[String, DirEntry]("/" -> root)
197+
val dirs = mutable.HashMap[String, DirEntry]("" -> root)
177198
val zipFile = openZipFile()
178199
val enum = zipFile.entries()
179200

@@ -206,6 +227,9 @@ final class FileZipArchive(file: JFile, release: Option[String]) extends ZipArch
206227
(root, dirs)
207228
}
208229

230+
@deprecated("Use allDirsByDottedName after converting keys from relative paths to dotted names", "2.13")
231+
lazy val allDirs: mutable.HashMap[String, DirEntry] = allDirsByDottedName.map { case (k, v) => (dottedToPath(k), v) }
232+
209233
def iterator: Iterator[Entry] = root.iterator
210234

211235
def name = file.getName

0 commit comments

Comments
 (0)