Skip to content

Add a compiler option to write .sig files to disk #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 9 additions & 58 deletions src/compiler/scala/tools/nsc/PipelineMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import java.lang.Thread.UncaughtExceptionHandler
import java.nio.file.attribute.FileTime
import java.nio.file.{Files, Path, Paths}
import java.time.Instant
import java.util.concurrent.ConcurrentHashMap
import java.util.{Collections, Locale}
import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger}

Expand Down Expand Up @@ -44,10 +45,13 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
val root = file.getRoot
// An empty component on Unix, just the drive letter on Windows
val validRootPathComponent = root.toString.replaceAllLiterally("/", "").replaceAllLiterally(":", "")
changeExtension(pickleCache.resolve(validRootPathComponent).resolve(root.relativize(file)).normalize(), newExtension)
val result = changeExtension(pickleCache.resolve(validRootPathComponent).resolve(root.relativize(file)).normalize(), newExtension)
if (useJars) Files.createDirectories(result.getParent)
strippedAndExportedClassPath.put(file.toRealPath().normalize(), result)
result
}

private val strippedAndExportedClassPath = mutable.HashMap[Path, Path]()
private val strippedAndExportedClassPath = new ConcurrentHashMap[Path, Path]().asScala

/** Forward errors to the (current) reporter. */
protected def scalacError(msg: String): Unit = {
Expand All @@ -73,51 +77,6 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
p.getParent.resolve(changedFileName)
}

def registerPickleClassPath[G <: Global](output: Path, data: mutable.AnyRefMap[G#Symbol, PickleBuffer]): Unit = {
val jarPath = cachePath(output)
val root = RootPath(jarPath, writable = true)
Files.createDirectories(root.root)

val dirs = mutable.Map[G#Symbol, Path]()
def packageDir(packSymbol: G#Symbol): Path = {
if (packSymbol.isEmptyPackageClass) root.root
else if (dirs.contains(packSymbol)) dirs(packSymbol)
else if (packSymbol.owner.isRoot) {
val subDir = root.root.resolve(packSymbol.encodedName)
Files.createDirectories(subDir)
dirs.put(packSymbol, subDir)
subDir
} else {
val base = packageDir(packSymbol.owner)
val subDir = base.resolve(packSymbol.encodedName)
Files.createDirectories(subDir)
dirs.put(packSymbol, subDir)
subDir
}
}
val written = new java.util.IdentityHashMap[AnyRef, Unit]()
try {
for ((symbol, pickle) <- data) {
if (!written.containsKey(pickle)) {
val base = packageDir(symbol.owner)
val primary = base.resolve(symbol.encodedName + ".sig")
val writer = new BufferedOutputStream(Files.newOutputStream(primary))
try {
writer.write(pickle.bytes, 0, pickle.writeIndex)
} finally {
writer.close()
}
written.put(pickle, ())
}
}
} finally {
root.close()
}
Files.setLastModifiedTime(jarPath, FileTime.from(Instant.now()))
strippedAndExportedClassPath.put(output.toRealPath().normalize(), jarPath)
}


def writeDotFile(logDir: Path, dependsOn: mutable.LinkedHashMap[Task, List[Dependency]]): Unit = {
val builder = new java.lang.StringBuilder()
builder.append("digraph projects {\n")
Expand Down Expand Up @@ -375,7 +334,6 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
if (p.outlineTimer.durationMicros > 0d) {
val desc = if (strategy == OutlineTypePipeline) "outline-type" else "parser-to-pickler"
events += durationEvent(p.label, desc, p.outlineTimer)
events += durationEvent(p.label, "pickle-export", p.pickleExportTimer)
}
for ((g, ix) <- p.groups.zipWithIndex) {
if (g.timer.durationMicros > 0d)
Expand Down Expand Up @@ -453,7 +411,6 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
val isGrouped = groups.size > 1

val outlineTimer = new Timer()
val pickleExportTimer = new Timer
val javaTimer = new Timer()

var outlineCriticalPathMs = 0d
Expand Down Expand Up @@ -491,14 +448,11 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
command.settings.Youtline.value = true
command.settings.stopAfter.value = List("pickler")
command.settings.Ymacroexpand.value = command.settings.MacroExpand.None
command.settings.YpickleWrite.value = cachePath(command.settings.outputDirs.getSingleOutput.get.file.toPath).toAbsolutePath.toString
val run1 = new compiler.Run()
run1 compile files
outlineTimer.stop()
log(f"scalac outline: done ${outlineTimer.durationMs}%.0f ms")
pickleExportTimer.start()
registerPickleClassPath(command.settings.outputDirs.getSingleOutput.get.file.toPath, run1.symData)
pickleExportTimer.stop()
log(f"scalac: exported pickles ${pickleExportTimer.durationMs}%.0f ms")
reporter.finish()
if (reporter.hasErrors) {
log("scalac outline: failed")
Expand All @@ -518,6 +472,7 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
command.settings.Youtline.value = false
command.settings.stopAfter.value = Nil
command.settings.Ymacroexpand.value = command.settings.MacroExpand.Normal
command.settings.YpickleWrite.value = ""

val groupCount = groups.size
for ((group, ix) <- groups.zipWithIndex) {
Expand Down Expand Up @@ -552,18 +507,14 @@ class PipelineMainClass(argFiles: Seq[Path], pipelineSettings: PipelineMain.Pipe
assert(groups.size == 1)
val group = groups.head
log("scalac: start")
command.settings.YpickleWrite.value = cachePath(command.settings.outputDirs.getSingleOutput.get.file.toPath).toString
outlineTimer.start()
try {
val run2 = new compiler.Run() {

override def advancePhase(): Unit = {
if (compiler.phase == this.picklerPhase) {
outlineTimer.stop()
log(f"scalac outline: done ${outlineTimer.durationMs}%.0f ms")
pickleExportTimer.start()
registerPickleClassPath(command.settings.outputDirs.getSingleOutput.get.file.toPath, symData)
pickleExportTimer.stop()
log(f"scalac: exported pickles ${pickleExportTimer.durationMs}%.0f ms")
outlineDone.complete(Success(()))
group.timer.start()
}
Expand Down
Loading