summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-06-10 15:01:13 +0000
committerPaul Phillips <paulp@improving.org>2011-06-10 15:01:13 +0000
commit28e6744e2305f523d16458a9d8c748903e33aca5 (patch)
tree23ecfffb8c26dcb509e1bff21580b7dbf9403af3 /src/compiler
parent68808e80c4574e419a440c31d24ad206870e28b3 (diff)
downloadscala-28e6744e2305f523d16458a9d8c748903e33aca5.tar.gz
scala-28e6744e2305f523d16458a9d8c748903e33aca5.tar.bz2
scala-28e6744e2305f523d16458a9d8c748903e33aca5.zip
A somewhat more realistic attempt to fix the bu...
A somewhat more realistic attempt to fix the build, no review. This introduces a repl command line option -Yrepl-sync to inhibit the asynchronous path which makes repl startup seem so snappy. And then it uses it in the repl tests.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala22
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala44
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala21
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
4 files changed, 57 insertions, 31 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index d4a15b6eb9..7f1066ec97 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -43,6 +43,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
var settings: Settings = _
var intp: IMain = _
+ def isAsync = !settings.Yreplsync.value
lazy val power = {
val g = intp.global
Power[g.type](this, g)
@@ -530,8 +531,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
// return false if repl should exit
def processLine(line: String): Boolean = {
- awaitInitialized()
- runThunks()
+ if (isAsync) {
+ awaitInitialized()
+ runThunks()
+ }
if (line eq null) false // assume null means EOF
else command(line) match {
case Result(false, _) => false
@@ -616,10 +619,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
if (isReplPower) "Already in power mode."
else enablePowerMode(false)
}
- def enablePowerMode(isAsync: Boolean) = {
+ def enablePowerMode(isDuringInit: Boolean) = {
replProps.power setValue true
power.unleash()
- if (isAsync) asyncMessage(power.banner)
+ if (isDuringInit) asyncMessage(power.banner)
else echo(power.banner)
}
@@ -806,11 +809,18 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
// our best to look ready. The interlocking lazy vals tend to
// inter-deadlock, so we break the cycle with a single asynchronous
// message to an actor.
- intp initialize initializedCallback()
+ if (isAsync) {
+ intp initialize initializedCallback()
+ createAsyncListener() // listens for signal to run postInitialization
+ }
+ else {
+ intp.initializeSynchronous()
+ postInitialization()
+ }
printWelcome()
try loop()
- // catch AbstractOrMissingHandler()
+ catch AbstractOrMissingHandler()
finally closeInterpreter()
true
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
index a8fb619f97..f2171ad732 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
@@ -61,6 +61,10 @@ trait ILoopInit {
}
private val initLock = new java.util.concurrent.locks.ReentrantLock()
+ private val initCompilerCondition = initLock.newCondition() // signal the compiler is initialized
+ private val initLoopCondition = initLock.newCondition() // signal the whole repl is initialized
+ private val initStart = System.nanoTime
+
private def withLock[T](body: => T): T = {
initLock.lock()
try body
@@ -68,41 +72,45 @@ trait ILoopInit {
}
// a condition used to ensure serial access to the compiler.
@volatile private var initIsComplete = false
- private val initCompilerCondition = initLock.newCondition() // signal the compiler is initialized
- private val initLoopCondition = initLock.newCondition() // signal the whole repl is initialized
- private val initStart = System.nanoTime
private def elapsed() = "%.3f".format((System.nanoTime - initStart).toDouble / 1000000000L)
- // Receives a single message once the interpreter is initialized.
- private val initializedReactor = io.spawn {
- withLock(initCompilerCondition.await())
- asyncMessage("[info] compiler init time: " + elapsed() + " s.")
- postInitialization()
- }
-
// the method to be called when the interpreter is initialized.
// Very important this method does nothing synchronous (i.e. do
// not try to use the interpreter) because until it returns, the
// repl's lazy val `global` is still locked.
protected def initializedCallback() = withLock(initCompilerCondition.signal())
+ // Spins off a thread which awaits a single message once the interpreter
+ // has been initialized.
+ protected def createAsyncListener() = {
+ io.spawn {
+ withLock(initCompilerCondition.await())
+ asyncMessage("[info] compiler init time: " + elapsed() + " s.")
+ postInitialization()
+ }
+ }
+
// called from main repl loop
protected def awaitInitialized() {
if (!initIsComplete)
withLock { while (!initIsComplete) initLoopCondition.await() }
}
+ protected def postInitThunks = List[Option[() => Unit]](
+ Some(intp.setContextClassLoader _),
+ if (isReplPower) Some(() => enablePowerMode(true)) else None,
+ // do this last to avoid annoying uninterruptible startups
+ Some(installSigIntHandler _)
+ ).flatten
// called once after init condition is signalled
protected def postInitialization() {
- addThunk(intp.setContextClassLoader())
- if (isReplPower)
- addThunk(enablePowerMode(true))
- // do this last to avoid annoying uninterruptible startups
- addThunk(installSigIntHandler())
-
+ postInitThunks foreach (f => addThunk(f()))
runThunks()
initIsComplete = true
- asyncMessage("[info] total init time: " + elapsed() + " s.")
- withLock(initLoopCondition.signal())
+
+ if (isAsync) {
+ asyncMessage("[info] total init time: " + elapsed() + " s.")
+ withLock(initLoopCondition.signal())
+ }
}
// code to be executed only after the interpreter is initialized
// and the lazy val `global` can be accessed without risk of deadlock.
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index f39cbd0d14..5c8679a93c 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -128,18 +128,25 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
result
}
}
+ def initializeSynchronous(): Unit = {
+ if (!isInitializeComplete)
+ _initialize()
+ }
def isInitializeComplete = _initializeComplete
/** the public, go through the future compiler */
lazy val global: Global = {
- // If init hasn't been called yet you're on your own.
- if (_isInitialized == null) {
- repldbg("Warning: compiler accessed before init set up. Assuming no postInit code.")
- initialize(())
+ if (isInitializeComplete) _compiler
+ else {
+ // If init hasn't been called yet you're on your own.
+ if (_isInitialized == null) {
+ repldbg("Warning: compiler accessed before init set up. Assuming no postInit code.")
+ initialize(())
+ }
+ // blocks until it is ; false means catastrophic failure
+ if (_isInitialized()) _compiler
+ else null
}
- // blocks until it is ; false means catastrophic failure
- if (_isInitialized()) _compiler
- else null
}
@deprecated("Use `global` for access to the compiler instance.", "2.9.0")
lazy val compiler: global.type = global
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index b896883e38..2ab933f5ba 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -143,6 +143,7 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignments.")
val Yinferdebug = BooleanSetting ("-Yinfer-debug", "Trace type inference and implicit search.")
val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.")
+ val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") .
withPostSetHook(_ => interpreter.replProps.debug setValue true)
val Ycompletion = BooleanSetting ("-Ycompletion-debug", "Trace all tab completion activity.")