summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
-rw-r--r--src/library/scala/collection/mutable/HashMap.scala31
-rw-r--r--src/library/scala/concurrent/SyncVar.scala4
-rw-r--r--src/library/scala/sys/process/ProcessBuilderImpl.scala14
-rw-r--r--src/library/scala/sys/process/ProcessImpl.scala34
-rw-r--r--src/reflect/scala/reflect/internal/util/SourceFile.scala23
6 files changed, 74 insertions, 34 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index c73ea54c3d..8f0625e58c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -60,7 +60,7 @@ trait Contexts { self: Analyzer =>
private lazy val allImportInfos =
mutable.Map[CompilationUnit, List[ImportInfo]]() withDefaultValue Nil
- def warnUnusedImports(unit: CompilationUnit) = {
+ def warnUnusedImports(unit: CompilationUnit) = if (!unit.isJava) {
for (imps <- allImportInfos.remove(unit)) {
for (imp <- imps.reverse.distinct) {
val used = allUsedSelectors(imp)
diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala
index eab4202353..11ff1f0893 100644
--- a/src/library/scala/collection/mutable/HashMap.scala
+++ b/src/library/scala/collection/mutable/HashMap.scala
@@ -72,6 +72,37 @@ extends AbstractMap[A, B]
else Some(e.value)
}
+ override def getOrElseUpdate(key: A, defaultValue: => B): B = {
+ val i = index(elemHashCode(key))
+ val entry = findEntry(key, i)
+ if (entry != null) entry.value
+ else addEntry(createNewEntry(key, defaultValue), i)
+ }
+
+ /* inlined HashTable.findEntry0 to preserve its visibility */
+ private[this] def findEntry(key: A, h: Int): Entry = {
+ var e = table(h).asInstanceOf[Entry]
+ while (notFound(key, e))
+ e = e.next
+ e
+ }
+ private[this] def notFound(key: A, e: Entry): Boolean = (e != null) && !elemEquals(e.key, key)
+
+ /* inlined HashTable.addEntry0 to preserve its visibility */
+ private[this] def addEntry(e: Entry, h: Int): B = {
+ if (tableSize >= threshold) addEntry(e)
+ else addEntry0(e, h)
+ e.value
+ }
+
+ /* extracted to make addEntry inlinable */
+ private[this] def addEntry0(e: Entry, h: Int) {
+ e.next = table(h).asInstanceOf[Entry]
+ table(h) = e
+ tableSize += 1
+ nnSizeMapAdd(h)
+ }
+
override def put(key: A, value: B): Option[B] = {
val e = findOrAddEntry(key, value)
if (e eq null) None
diff --git a/src/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala
index 5fabf553bd..0e534a9b22 100644
--- a/src/library/scala/concurrent/SyncVar.scala
+++ b/src/library/scala/concurrent/SyncVar.scala
@@ -91,7 +91,7 @@ class SyncVar[A] {
// [Heather] the reason why: it doesn't take into consideration
// whether or not the SyncVar is already defined. So, set has been
// deprecated in order to eventually be able to make "setting" private
- @deprecated("use `put` instead, as `set` is potentially error-prone", "2.10.0")
+ @deprecated("use `put` to ensure a value cannot be overwritten without a corresponding `take`", "2.10.0")
// NOTE: Used by SBT 0.13.0-M2 and below
def set(x: A): Unit = setVal(x)
@@ -111,7 +111,7 @@ class SyncVar[A] {
// [Heather] the reason why: it doesn't take into consideration
// whether or not the SyncVar is already defined. So, unset has been
// deprecated in order to eventually be able to make "unsetting" private
- @deprecated("use `take` instead, as `unset` is potentially error-prone", "2.10.0")
+ @deprecated("use `take` to ensure a value is never discarded", "2.10.0")
// NOTE: Used by SBT 0.13.0-M2 and below
def unset(): Unit = synchronized {
isDefined = false
diff --git a/src/library/scala/sys/process/ProcessBuilderImpl.scala b/src/library/scala/sys/process/ProcessBuilderImpl.scala
index eef140c16a..0df2e648e0 100644
--- a/src/library/scala/sys/process/ProcessBuilderImpl.scala
+++ b/src/library/scala/sys/process/ProcessBuilderImpl.scala
@@ -53,12 +53,14 @@ private[process] trait ProcessBuilderImpl {
override def run(io: ProcessIO): Process = {
val success = new SyncVar[Boolean]
- success put false
- val t = Spawn({
- runImpl(io)
- success.put(true)
- }, io.daemonizeThreads)
-
+ def go(): Unit = {
+ var ok = false
+ try {
+ runImpl(io)
+ ok = true
+ } finally success.put(ok)
+ }
+ val t = Spawn(go(), io.daemonizeThreads)
new ThreadProcess(t, success)
}
}
diff --git a/src/library/scala/sys/process/ProcessImpl.scala b/src/library/scala/sys/process/ProcessImpl.scala
index 6da0dee056..8a0002b316 100644
--- a/src/library/scala/sys/process/ProcessImpl.scala
+++ b/src/library/scala/sys/process/ProcessImpl.scala
@@ -86,17 +86,20 @@ private[process] trait ProcessImpl {
private[process] abstract class CompoundProcess extends BasicProcess {
def isAlive() = processThread.isAlive()
def destroy() = destroyer()
- def exitValue() = getExitValue._2() getOrElse scala.sys.error("No exit code: process destroyed.")
- def start() = getExitValue
+ def exitValue() = futureValue() getOrElse scala.sys.error("No exit code: process destroyed.")
+ def start() = { futureThread ;() }
- protected lazy val (processThread, getExitValue, destroyer) = {
+ protected lazy val (processThread, (futureThread, futureValue), destroyer) = {
val code = new SyncVar[Option[Int]]()
- code.put(None)
- val thread = Spawn(code.put(runAndExitValue()))
+ val thread = Spawn {
+ var value: Option[Int] = None
+ try value = runAndExitValue()
+ finally code.put(value)
+ }
(
thread,
- Future { thread.join(); code.get },
+ Future(code.get), // thread.join()
() => thread.interrupt()
)
}
@@ -215,13 +218,15 @@ private[process] trait ProcessImpl {
}
/** A thin wrapper around a java.lang.Process. `ioThreads` are the Threads created to do I/O.
- * The implementation of `exitValue` waits until these threads die before returning. */
+ * The implementation of `exitValue` waits until these threads die before returning.
+ */
private[process] class DummyProcess(action: => Int) extends Process {
- private[this] val exitCode = Future(action)
- override def isAlive() = exitCode._1.isAlive()
- override def exitValue() = exitCode._2()
+ private[this] val (thread, value) = Future(action)
+ override def isAlive() = thread.isAlive()
+ override def exitValue() = value()
override def destroy() { }
}
+
/** A thin wrapper around a java.lang.Process. `outputThreads` are the Threads created to read from the
* output and error streams of the process. `inputThread` is the Thread created to write to the input stream of
* the process.
@@ -245,11 +250,8 @@ private[process] trait ProcessImpl {
}
}
private[process] final class ThreadProcess(thread: Thread, success: SyncVar[Boolean]) extends Process {
- override def isAlive() = thread.isAlive()
- override def exitValue() = {
- thread.join()
- if (success.get) 0 else 1
- }
- override def destroy() { thread.interrupt() }
+ override def isAlive() = thread.isAlive()
+ override def exitValue() = if (success.get) 0 else 1 // thread.join()
+ override def destroy() = thread.interrupt()
}
}
diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala
index a2642628a4..64b6972298 100644
--- a/src/reflect/scala/reflect/internal/util/SourceFile.scala
+++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala
@@ -154,18 +154,23 @@ class BatchSourceFile(val file : AbstractFile, content0: Array[Char]) extends So
case _ => false
}
- def calculateLineIndices(cs: Array[Char]) = {
- val buf = new ArrayBuffer[Int]
- buf += 0
- for (i <- 0 until cs.length) if (isAtEndOfLine(i)) buf += i + 1
- buf += cs.length // sentinel, so that findLine below works smoother
- buf.toArray
+ private lazy val lineIndices: Array[Int] = {
+ def calculateLineIndices(cs: Array[Char]) = {
+ val buf = new ArrayBuffer[Int]
+ buf += 0
+ for (i <- 0 until cs.length) if (isAtEndOfLine(i)) buf += i + 1
+ buf += cs.length // sentinel, so that findLine below works smoother
+ buf.toArray
+ }
+ calculateLineIndices(content)
}
- private lazy val lineIndices: Array[Int] = calculateLineIndices(content)
- def lineToOffset(index : Int): Int = lineIndices(index)
+ def lineToOffset(index: Int): Int = {
+ val offset = lineIndices(index)
+ if (offset < length) offset else throw new IndexOutOfBoundsException(index.toString)
+ }
- private var lastLine = 0
+ private[this] var lastLine = 0
/** Convert offset to line in this source file.
* Lines are numbered from 0.