diff options
author | Paul Phillips <paulp@improving.org> | 2011-02-08 08:47:29 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-02-08 08:47:29 +0000 |
commit | 3467ad57e4c2b56cdd02ce0c75af4716b5631a10 (patch) | |
tree | af5d632276e79a449e9971e94c25bec0c1fc73e4 /src/compiler/scala/tools/nsc/CompileServer.scala | |
parent | c89ea6e3ae82d9b6bacda25dceb74a958d2fa4f6 (diff) | |
download | scala-3467ad57e4c2b56cdd02ce0c75af4716b5631a10.tar.gz scala-3467ad57e4c2b56cdd02ce0c75af4716b5631a10.tar.bz2 scala-3467ad57e4c2b56cdd02ce0c75af4716b5631a10.zip |
Working on fsc.
for me anyway, with this commit scripts will occasionally reuse a
compiler instance, instead of never. Since any tests I write will fail
on platforms which aren't mine, there are no tests. I might have to
start a platform-specific testing area to break some ice around these
huge untested zones. No review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/CompileServer.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/CompileServer.scala | 96 |
1 files changed, 59 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index 5296432519..e33545d3c9 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -6,11 +6,10 @@ package scala.tools.nsc import java.io.{ BufferedOutputStream, FileOutputStream, PrintStream, File => JFile } -import io.File - import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import scala.tools.nsc.util.FakePos //Position import scala.tools.util.SocketServer +import settings.FscSettings /** * The server part of the fsc offline compiler. It awaits compilation @@ -29,9 +28,9 @@ class StandardCompileServer extends SocketServer { val MaxCharge = 0.8 - var shutDown: Boolean = false - private var compiler: Global = null + var reporter: ConsoleReporter = _ + var shutdown = false private def exit(code: Int): Nothing = { System.err.close() @@ -42,8 +41,6 @@ class StandardCompileServer extends SocketServer { private val runtime = Runtime.getRuntime() import runtime.{ totalMemory, freeMemory, maxMemory } - var reporter: ConsoleReporter = _ - /** Create a new compiler instance */ def newGlobal(settings: Settings, reporter: Reporter) = new Global(settings, reporter) { @@ -69,11 +66,29 @@ class StandardCompileServer extends SocketServer { protected def newOfflineCompilerCommand(arguments: List[String], settings: Settings) = new OfflineCompilerCommand(arguments, settings) + /** Problematically, Settings are only considered equal if every setting + * is exactly equal. In fsc this immediately breaks down because the randomly + * chosen temporary outdirs differ between client and server. Among other + * things. Long term we could use a meaningful equality; short term I'm just + * ignoring options which I can see causing a new compiler instance every time + * and which do not interestingly influence compilation products. + */ + def unequalSettings(s1: Settings, s2: Settings): Set[Settings#Setting] = { + val ignoreSettings = Set("-d", "-encoding", "-verbose") + def trim (s: Settings): Set[Settings#Setting] = ( + s.userSetSettings.toSet[Settings#Setting] filterNot (ss => ignoreSettings exists (ss respondsTo _)) + ) + val ss1 = trim(s1) + val ss2 = trim(s2) + + (ss1 union ss2) -- (ss1 intersect ss2) + } + def session() { printMemoryStats() - val password = compileSocket getPassword port + val password = compileSocket getPassword port val guessedPassword = in.readLine() - val input = in.readLine() + val input = in.readLine() def fscError(msg: String): Unit = out println ( FakePos("fsc"), @@ -83,13 +98,17 @@ class StandardCompileServer extends SocketServer { return val args = input.split("\0", -1).toList - val command = newOfflineCompilerCommand(args, new Settings(fscError)) - - if (command.fscShutdown.value) { - shutDown = true + val settings = new FscSettings(fscError) + def logVerbose(msg: String) = + if (settings.verbose.value) + out println msg + + val command = newOfflineCompilerCommand(args, settings) + if (settings.shutdown.value) { + shutdown = true return out.println("[Compile server exited]") } - if (command.fscReset.value) { + if (settings.reset.value) { compiler = null return out.println("[Compile server was reset]") } @@ -98,45 +117,48 @@ class StandardCompileServer extends SocketServer { // disable prompts, so that compile server cannot block override def displayPrompt = () } + def isCompilerReusable: Boolean = { + if (compiler == null) { + logVerbose("[Creating compiler instance for compile server.]") + return false + } + val unequal = unequalSettings(command.settings, compiler.settings) + if (unequal.nonEmpty) { + logVerbose("[Replacing compiler with new instance because settings are unequal.]") + logVerbose("[Asymmetric settings: " + unequal.mkString(", ") + "]") + } + unequal.isEmpty + } if (command.shouldStopWithInfo) reporter.info(null, command.getInfoMessage(newGlobal(command.settings, reporter)), true) else if (command.files.isEmpty) reporter.info(null, command.usageMsg, true) else { - try { - if (compiler != null && command.settings == compiler.settings) { - compiler.settings = command.settings - compiler.reporter = reporter - } - else { - if (command.verbose) { - val reason = if (compiler == null) "compiler is null" else "settings not equal" - out.println("[Starting new compile server instance because %s]".format(reason)) - } - compiler = newGlobal(command.settings, reporter) - } - val c = compiler - val run = new c.Run() - run compile command.files + if (isCompilerReusable) { + compiler.settings = command.settings + compiler.reporter = reporter } + else { + compiler = newGlobal(command.settings, reporter) + } + val c = compiler + val run = new c.Run() + try run compile command.files catch { case ex @ FatalError(msg) => - if (command.debug) - ex.printStackTrace(out) - reporter.error(null, "fatal error: " + msg) compiler = null - case ex: Throwable => - ex.printStackTrace(out); - reporter.error(null, "fatal error (server aborted): " + ex.getMessage()) - shutDown = true + case ex => + shutdown = true + throw ex } } - reporter.printSummary() - if (isMemoryFullEnough) + if (isMemoryFullEnough) { + logVerbose("Nulling out compiler due to memory utilization.") compiler = null + } } } |