summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Driver.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Main.scala6
-rw-r--r--src/compiler/scala/tools/nsc/MainBench.scala48
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala7
-rw-r--r--src/library/scala/Double.scala3
-rw-r--r--src/library/scala/Float.scala3
-rw-r--r--src/library/scala/concurrent/BlockContext.scala35
-rw-r--r--src/library/scala/concurrent/Future.scala6
-rw-r--r--src/library/scala/concurrent/default/SchedulerImpl.scala.disabled44
-rw-r--r--src/library/scala/concurrent/default/TaskImpl.scala.disabled313
-rw-r--r--src/library/scala/concurrent/impl/ExecutionContextImpl.scala10
-rw-r--r--src/library/scala/concurrent/impl/Future.scala24
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala2
-rw-r--r--src/library/scala/concurrent/package.scala76
-rw-r--r--src/partest/scala/tools/partest/nest/DirectRunner.scala6
-rw-r--r--src/reflect/scala/reflect/api/StandardNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala20
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala202
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolLoaders.scala4
-rw-r--r--test/files/jvm/future-spec/FutureTests.scala6
-rw-r--r--test/files/jvm/future-spec/PromiseTests.scala9
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala20
-rw-r--r--test/files/pos/t6047.flags1
-rw-r--r--test/files/pos/t6047.scala20
-rw-r--r--test/files/run/reflection-magicsymbols-repl.check39
-rw-r--r--test/files/run/reflection-magicsymbols-repl.scala23
-rw-r--r--test/files/run/reflection-magicsymbols-vanilla.check8
-rw-r--r--test/files/run/reflection-magicsymbols-vanilla.scala20
-rw-r--r--test/files/run/reflection-magicsymbols.check22
-rw-r--r--test/files/run/reflection-magicsymbols.scala11
-rw-r--r--test/files/run/t6086-repl.check12
-rw-r--r--test/files/run/t6086-repl.scala8
-rw-r--r--test/files/run/t6086-vanilla.check1
-rw-r--r--test/files/run/t6086-vanilla.scala6
41 files changed, 471 insertions, 587 deletions
diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala
index 0051c3bdec..15e2929ff1 100644
--- a/src/compiler/scala/tools/nsc/Driver.scala
+++ b/src/compiler/scala/tools/nsc/Driver.scala
@@ -1,10 +1,12 @@
package scala.tools.nsc
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
-import Properties.{ versionString, copyrightString }
+import Properties.{ versionString, copyrightString, residentPromptString }
import scala.reflect.internal.util.{ BatchSourceFile, FakePos }
abstract class Driver {
+
+ val prompt = residentPromptString
val versionMsg = "Scala compiler " +
versionString + " -- " +
diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala
index 19c872b6d3..8b7e76e994 100644
--- a/src/compiler/scala/tools/nsc/Main.scala
+++ b/src/compiler/scala/tools/nsc/Main.scala
@@ -12,15 +12,13 @@ import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager }
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position}
-import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath }
+import Properties.msilLibPath
/** The main class for NSC, a compiler for the programming
- * language Scala.
+ * language Scala.
*/
object Main extends Driver with EvalLoop {
- val prompt = residentPromptString
-
def resident(compiler: Global) {
loop { line =>
val args = line.split(' ').toList
diff --git a/src/compiler/scala/tools/nsc/MainBench.scala b/src/compiler/scala/tools/nsc/MainBench.scala
new file mode 100644
index 0000000000..0037de7b94
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/MainBench.scala
@@ -0,0 +1,48 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+
+import java.io.File
+import File.pathSeparator
+
+import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager }
+import scala.tools.nsc.io.AbstractFile
+import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
+import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position}
+import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath }
+import scala.reflect.internal.util.Statistics
+
+/** The main class for NSC, a compiler for the programming
+ * language Scala.
+ */
+object MainBench extends Driver with EvalLoop {
+
+ lazy val theCompiler = Global(settings, reporter)
+
+ override def newCompiler() = theCompiler
+
+ val NIter = 50
+ val NBest = 10
+
+ override def main(args: Array[String]) = {
+ val times = new Array[Long](NIter)
+ var start = System.nanoTime()
+ for (i <- 0 until NIter) {
+ if (i == NIter-1) {
+ theCompiler.settings.Ystatistics.value = true
+ Statistics.enabled = true
+ }
+ process(args)
+ val end = System.nanoTime()
+ val duration = (end-start)/1000000
+ println(s"${duration}ms")
+ times(i) = duration
+ start = end
+ }
+ val avg = times.sorted.take(NBest).sum / NBest
+ println(s"avg shortest $NBest times ${avg}ms")
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 0c988ceae4..9b4e793241 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -34,8 +34,7 @@ abstract class SymbolLoaders {
/** Enter class with given `name` into scope of `root`
* and give them `completer` as type.
*/
- def enterClass(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = root.ownerOfNewSymbols
+ def enterClass(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
val clazz = owner.newClass(newTypeName(name))
clazz setInfo completer
enterIfNew(owner, clazz, completer)
@@ -44,8 +43,7 @@ abstract class SymbolLoaders {
/** Enter module with given `name` into scope of `root`
* and give them `completer` as type.
*/
- def enterModule(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = root.ownerOfNewSymbols
+ def enterModule(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
val module = owner.newModule(newTermName(name))
module setInfo completer
module.moduleClass setInfo moduleClassLoader
@@ -217,15 +215,18 @@ abstract class SymbolLoaders {
root.setInfo(new PackageClassInfoType(newScope, root))
val sourcepaths = classpath.sourcepaths
- for (classRep <- classpath.classes if platform.doLoad(classRep)) {
- initializeFromClassPath(root, classRep)
+ if (!root.isRoot) {
+ for (classRep <- classpath.classes if platform.doLoad(classRep)) {
+ initializeFromClassPath(root, classRep)
+ }
}
+ if (!root.isEmptyPackageClass) {
+ for (pkg <- classpath.packages) {
+ enterPackage(root, pkg.name, new PackageLoader(pkg))
+ }
- for (pkg <- classpath.packages) {
- enterPackage(root, pkg.name, new PackageLoader(pkg))
+ openPackageModule(root)
}
-
- openPackageModule(root)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 7318538de7..3518316fbb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -119,7 +119,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
// those with the DEFAULTPARAM flag, and infer the methods. Looking for the methods
// directly requires inspecting the parameter list of every one. That modification
// shaved 95% off the time spent in this method.
- val defaultGetters = clazz.info.findMember(nme.ANYNAME, 0L, DEFAULTPARAM, false).alternatives
+ val defaultGetters = clazz.info.findMembers(0L, DEFAULTPARAM)
val defaultMethodNames = defaultGetters map (sym => nme.defaultGetterToMethod(sym.name))
defaultMethodNames.distinct foreach { name =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a570cd74d6..9371af4848 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4509,6 +4509,8 @@ trait Typers extends Modes with Adaptations with Tags {
assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
errorContainer = tree
}
+
+ val fingerPrint: Long = name.fingerPrint
var defSym: Symbol = tree.symbol // the directly found symbol
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
@@ -4547,7 +4549,10 @@ trait Typers extends Modes with Adaptations with Tags {
var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
pre = cx.enclClass.prefix
- defEntry = cx.scope.lookupEntry(name)
+ defEntry = {
+ val scope = cx.scope
+ if ((fingerPrint & scope.fingerPrints) != 0) scope.lookupEntry(name) else null
+ }
if ((defEntry ne null) && qualifies(defEntry.sym)) {
// Right here is where SI-1987, overloading in package objects, can be
// seen to go wrong. There is an overloaded symbol, but when referring
diff --git a/src/library/scala/Double.scala b/src/library/scala/Double.scala
index 2ff46c433d..510de92a2a 100644
--- a/src/library/scala/Double.scala
+++ b/src/library/scala/Double.scala
@@ -370,9 +370,6 @@ object Double extends AnyValCompanion {
final val PositiveInfinity = java.lang.Double.POSITIVE_INFINITY
final val NegativeInfinity = java.lang.Double.NEGATIVE_INFINITY
- @deprecated("use Double.MinPositiveValue instead", "2.9.0")
- final val Epsilon = MinPositiveValue
-
/** The negative number with the greatest (finite) absolute value which is representable
* by a Double. Note that it differs from [[java.lang.Double.MIN_VALUE]], which
* is the smallest positive value representable by a Double. In Scala that number
diff --git a/src/library/scala/Float.scala b/src/library/scala/Float.scala
index bd7a07fece..b9c116da0b 100644
--- a/src/library/scala/Float.scala
+++ b/src/library/scala/Float.scala
@@ -370,9 +370,6 @@ object Float extends AnyValCompanion {
final val PositiveInfinity = java.lang.Float.POSITIVE_INFINITY
final val NegativeInfinity = java.lang.Float.NEGATIVE_INFINITY
- @deprecated("use Float.MinPositiveValue instead", "2.9.0")
- final val Epsilon = MinPositiveValue
-
/** The negative number with the greatest (finite) absolute value which is representable
* by a Float. Note that it differs from [[java.lang.Float.MIN_VALUE]], which
* is the smallest positive value representable by a Float. In Scala that number
diff --git a/src/library/scala/concurrent/BlockContext.scala b/src/library/scala/concurrent/BlockContext.scala
index a5b878c546..640560a174 100644
--- a/src/library/scala/concurrent/BlockContext.scala
+++ b/src/library/scala/concurrent/BlockContext.scala
@@ -12,9 +12,10 @@ import java.lang.Thread
import scala.concurrent.util.Duration
/**
- * A context to be notified by `scala.concurrent.blocking()` when
+ * A context to be notified by `scala.concurrent.blocking` when
* a thread is about to block. In effect this trait provides
- * the implementation for `scala.concurrent.blocking()`. `scala.concurrent.blocking()`
+ * the implementation for `scala.concurrent.Await`.
+ * `scala.concurrent.Await.result()` and `scala.concurrent.Await.ready()`
* locates an instance of `BlockContext` by first looking for one
* provided through `BlockContext.withBlockContext()` and failing that,
* checking whether `Thread.currentThread` is an instance of `BlockContext`.
@@ -27,11 +28,11 @@ import scala.concurrent.util.Duration
* {{{
* val oldContext = BlockContext.current
* val myContext = new BlockContext {
- * override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = {
+ * override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
* // you'd have code here doing whatever you need to do
* // when the thread is about to block.
* // Then you'd chain to the previous context:
- * oldContext.internalBlockingCall(awaitable, atMost)
+ * oldContext.blockOn(thunk)
* }
* }
* BlockContext.withBlockContext(myContext) {
@@ -42,35 +43,33 @@ import scala.concurrent.util.Duration
*/
trait BlockContext {
- /** Used internally by the framework; blocks execution for at most
- * `atMost` time while waiting for an `awaitable` object to become ready.
+ /** Used internally by the framework;
+ * Designates (and eventually executes) a thunk which potentially blocks the calling `Thread`.
*
- * Clients should use `scala.concurrent.blocking` instead; this is
- * the implementation of `scala.concurrent.blocking`, generally
- * provided by a `scala.concurrent.ExecutionContext` or `java.util.concurrent.Executor`.
+ * Clients must use `scala.concurrent.blocking` or `scala.concurrent.Await` instead.
*/
- def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T
+ def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T
}
object BlockContext {
private object DefaultBlockContext extends BlockContext {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- awaitable.result(atMost)(Await.canAwaitEvidence)
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = thunk
}
- private val contextLocal = new ThreadLocal[BlockContext]() {
- override def initialValue = Thread.currentThread match {
+ private val contextLocal = new ThreadLocal[BlockContext]()
+
+ /** Obtain the current thread's current `BlockContext`. */
+ def current: BlockContext = contextLocal.get match {
+ case null => Thread.currentThread match {
case ctx: BlockContext => ctx
case _ => DefaultBlockContext
}
+ case some => some
}
- /** Obtain the current thread's current `BlockContext`. */
- def current: BlockContext = contextLocal.get
-
/** Pushes a current `BlockContext` while executing `body`. */
def withBlockContext[T](blockContext: BlockContext)(body: => T): T = {
- val old = contextLocal.get
+ val old = contextLocal.get // can be null
try {
contextLocal.set(blockContext)
body
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index f82b79cb18..d24fdbf005 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -707,11 +707,9 @@ object Future {
// doesn't need to create defaultExecutionContext as
// a side effect.
private[concurrent] object InternalCallbackExecutor extends ExecutionContext {
- def execute(runnable: Runnable): Unit =
+ override def execute(runnable: Runnable): Unit =
runnable.run()
- def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- throw new IllegalStateException("bug in scala.concurrent, called blocking() from internal callback")
- def reportFailure(t: Throwable): Unit =
+ override def reportFailure(t: Throwable): Unit =
throw new IllegalStateException("problem in scala.concurrent internal callback", t)
}
}
diff --git a/src/library/scala/concurrent/default/SchedulerImpl.scala.disabled b/src/library/scala/concurrent/default/SchedulerImpl.scala.disabled
deleted file mode 100644
index 241efa8857..0000000000
--- a/src/library/scala/concurrent/default/SchedulerImpl.scala.disabled
+++ /dev/null
@@ -1,44 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.concurrent
-package default
-
-import scala.concurrent.util.Duration
-
-private[concurrent] final class SchedulerImpl extends Scheduler {
- private val timer =
- new java.util.Timer(true) // the associated thread runs as a daemon
-
- def schedule(delay: Duration, frequency: Duration)(thunk: => Unit): Cancellable = ???
-
- def scheduleOnce(delay: Duration, task: Runnable): Cancellable = {
- val timerTask = new java.util.TimerTask {
- def run(): Unit =
- task.run()
- }
- timer.schedule(timerTask, delay.toMillis)
- new Cancellable {
- def cancel(): Unit =
- timerTask.cancel()
- }
- }
-
- def scheduleOnce(delay: Duration)(task: => Unit): Cancellable = {
- val timerTask = new java.util.TimerTask {
- def run(): Unit =
- task
- }
- timer.schedule(timerTask, delay.toMillis)
- new Cancellable {
- def cancel(): Unit =
- timerTask.cancel()
- }
- }
-
-}
diff --git a/src/library/scala/concurrent/default/TaskImpl.scala.disabled b/src/library/scala/concurrent/default/TaskImpl.scala.disabled
deleted file mode 100644
index 8b4eb12d4f..0000000000
--- a/src/library/scala/concurrent/default/TaskImpl.scala.disabled
+++ /dev/null
@@ -1,313 +0,0 @@
-package scala.concurrent
-package default
-
-
-
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
-import scala.concurrent.forkjoin.{ ForkJoinPool, RecursiveAction, ForkJoinWorkerThread }
-import scala.util.Try
-import scala.util
-import scala.concurrent.util.Duration
-import scala.annotation.tailrec
-import scala.util.control.NonFatal
-
-
-private[concurrent] trait Completable[T] {
-self: Future[T] =>
-
- val executor: ExecutionContextImpl
-
- def newPromise[S]: Promise[S] = executor promise
-
- type Callback = Try[T] => Any
-
- def getState: State[T]
-
- def casState(oldv: State[T], newv: State[T]): Boolean
-
- protected def dispatch[U](r: Runnable) = executionContext execute r
-
- protected def processCallbacks(cbs: List[Callback], r: Try[T]) =
- for (cb <- cbs) dispatch(new Runnable {
- override def run() = cb(r)
- })
-
- def future: Future[T] = self
-
- def onComplete[U](callback: Try[T] => U): this.type = {
- @tailrec def tryAddCallback(): Try[T] = {
- getState match {
- case p @ Pending(lst) =>
- val pt = p.asInstanceOf[Pending[T]]
- if (casState(pt, Pending(callback :: pt.callbacks))) null
- else tryAddCallback()
- case Success(res) => util.Success(res)
- case Failure(t) => util.Failure(t)
- }
- }
-
- val res = tryAddCallback()
- if (res != null) dispatch(new Runnable {
- override def run() =
- try callback(res)
- catch handledFutureException andThen {
- t => Console.err.println(t)
- }
- })
-
- this
- }
-
- def isTimedout: Boolean = getState match {
- case Failure(ft: FutureTimeoutException) => true
- case _ => false
- }
-
-}
-
-private[concurrent] class PromiseImpl[T](context: ExecutionContextImpl)
-extends Promise[T] with Future[T] with Completable[T] {
-
- val executor: scala.concurrent.default.ExecutionContextImpl = context
-
- @volatile private var state: State[T] = _
-
- val updater = AtomicReferenceFieldUpdater.newUpdater(classOf[PromiseImpl[T]], classOf[State[T]], "state")
-
- updater.set(this, Pending(List()))
-
- def casState(oldv: State[T], newv: State[T]): Boolean = {
- updater.compareAndSet(this, oldv, newv)
- }
-
- def getState: State[T] = {
- updater.get(this)
- }
-
- @tailrec private def tryCompleteState(completed: State[T]): List[Callback] = (getState: @unchecked) match {
- case p @ Pending(cbs) => if (!casState(p, completed)) tryCompleteState(completed) else cbs
- case _ => null
- }
-
- def tryComplete(r: Try[T]) = r match {
- case util.Failure(t) => tryFailure(t)
- case util.Success(v) => trySuccess(v)
- }
-
- override def trySuccess(value: T): Boolean = {
- val cbs = tryCompleteState(Success(value))
- if (cbs == null)
- false
- else {
- processCallbacks(cbs, util.Success(value))
- this.synchronized {
- this.notifyAll()
- }
- true
- }
- }
-
- override def tryFailure(t: Throwable): Boolean = {
- val wrapped = wrap(t)
- val cbs = tryCompleteState(Failure(wrapped))
- if (cbs == null)
- false
- else {
- processCallbacks(cbs, util.Failure(wrapped))
- this.synchronized {
- this.notifyAll()
- }
- true
- }
- }
-
- def await(atMost: Duration)(implicit canawait: scala.concurrent.CanAwait): T = getState match {
- case Success(res) => res
- case Failure(t) => throw t
- case _ =>
- this.synchronized {
- while (true)
- getState match {
- case Pending(_) => this.wait()
- case Success(res) => return res
- case Failure(t) => throw t
- }
- }
- sys.error("unreachable")
- }
-
-}
-
-private[concurrent] class TaskImpl[T](context: ExecutionContextImpl, body: => T)
-extends RecursiveAction with Task[T] with Future[T] with Completable[T] {
-
- val executor: ExecutionContextImpl = context
-
- @volatile private var state: State[T] = _
-
- val updater = AtomicReferenceFieldUpdater.newUpdater(classOf[TaskImpl[T]], classOf[State[T]], "state")
-
- updater.set(this, Pending(List()))
-
- def casState(oldv: State[T], newv: State[T]): Boolean = {
- updater.compareAndSet(this, oldv, newv)
- }
-
- def getState: State[T] = {
- updater.get(this)
- }
-
- @tailrec private def tryCompleteState(completed: State[T]): List[Callback] = (getState: @unchecked) match {
- case p @ Pending(cbs) => if (!casState(p, completed)) tryCompleteState(completed) else cbs
- }
-
- def compute(): Unit = {
- var cbs: List[Callback] = null
- try {
- val res = body
- processCallbacks(tryCompleteState(Success(res)), util.Success(res))
- } catch {
- case t if NonFatal(t) =>
- processCallbacks(tryCompleteState(Failure(t)), util.Failure(t))
- case t =>
- val ee = new ExecutionException(t)
- processCallbacks(tryCompleteState(Failure(ee)), util.Failure(ee))
- throw t
- }
- }
-
- def start(): Unit = {
- Thread.currentThread match {
- case fj: ForkJoinWorkerThread if fj.getPool eq executor.pool => fork()
- case _ => executor.pool.execute(this)
- }
- }
-
- // TODO FIXME: handle timeouts
- def await(atMost: Duration): this.type =
- await
-
- def await: this.type = {
- this.join()
- this
- }
-
- def tryCancel(): Unit =
- tryUnfork()
-
- def await(atMost: Duration)(implicit canawait: CanAwait): T = {
- join() // TODO handle timeout also
- (updater.get(this): @unchecked) match {
- case Success(r) => r
- case Failure(t) => throw t
- }
- }
-
-}
-
-
-private[concurrent] sealed abstract class State[T]
-
-
-case class Pending[T](callbacks: List[Try[T] => Any]) extends State[T]
-
-
-case class Success[T](result: T) extends State[T]
-
-
-case class Failure[T](throwable: Throwable) extends State[T]
-
-
-private[concurrent] final class ExecutionContextImpl extends ExecutionContext {
- import ExecutionContextImpl._
-
- val pool = {
- val p = new ForkJoinPool
- p.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler {
- def uncaughtException(t: Thread, throwable: Throwable) {
- Console.err.println(throwable.getMessage)
- throwable.printStackTrace(Console.err)
- }
- })
- p
- }
-
- @inline
- private def executeTask(task: RecursiveAction) {
- if (Thread.currentThread.isInstanceOf[ForkJoinWorkerThread])
- task.fork()
- else
- pool execute task
- }
-
- def execute(task: Runnable) {
- val action = new RecursiveAction { def compute() { task.run() } }
- executeTask(action)
- }
-
- def execute[U](body: () => U) {
- val action = new RecursiveAction { def compute() { body() } }
- executeTask(action)
- }
-
- def task[T](body: => T): Task[T] = {
- new TaskImpl(this, body)
- }
-
- def future[T](body: => T): Future[T] = {
- val t = task(body)
- t.start()
- t.future
- }
-
- def promise[T]: Promise[T] =
- new PromiseImpl[T](this)
-
- def blocking[T](atMost: Duration)(body: =>T): T = blocking(body2awaitable(body), atMost)
-
- def blocking[T](awaitable: Awaitable[T], atMost: Duration): T = {
- currentExecutionContext.get match {
- case null => awaitable.await(atMost)(null) // outside - TODO - fix timeout case
- case x if x eq this => this.blockingCall(awaitable) // inside an execution context thread on this executor
- case x => x.blocking(awaitable, atMost)
- }
- }
-
- private def blockingCall[T](b: Awaitable[T]): T = b match {
- case fj: TaskImpl[_] if fj.executor.pool eq pool =>
- fj.await(Duration.fromNanos(0))
- case _ =>
- var res: T = null.asInstanceOf[T]
- @volatile var blockingDone = false
- // TODO add exception handling here!
- val mb = new ForkJoinPool.ManagedBlocker {
- def block() = {
- res = b.await(Duration.fromNanos(0))(CanAwaitEvidence)
- blockingDone = true
- true
- }
- def isReleasable = blockingDone
- }
- ForkJoinPool.managedBlock(mb, true)
- res
- }
-
- def reportFailure(t: Throwable): Unit = {}
-
-}
-
-
-object ExecutionContextImpl {
-
- private[concurrent] def currentExecutionContext: ThreadLocal[ExecutionContext] = new ThreadLocal[ExecutionContext] {
- override protected def initialValue = null
- }
-
-}
-
-
-
-
-
-
-
diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
index 98f821652f..875a558887 100644
--- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
+++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
@@ -13,7 +13,7 @@ package scala.concurrent.impl
import java.util.concurrent.{ LinkedBlockingQueue, Callable, Executor, ExecutorService, Executors, ThreadFactory, TimeUnit, ThreadPoolExecutor }
import java.util.Collection
import scala.concurrent.forkjoin._
-import scala.concurrent.{ BlockContext, ExecutionContext, Awaitable, ExecutionContextExecutor, ExecutionContextExecutorService }
+import scala.concurrent.{ BlockContext, ExecutionContext, Awaitable, CanAwait, ExecutionContextExecutor, ExecutionContextExecutorService }
import scala.concurrent.util.Duration
import scala.util.control.NonFatal
@@ -37,15 +37,15 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter:
def newThread(runnable: Runnable): Thread = wire(new Thread(runnable))
def newThread(fjp: ForkJoinPool): ForkJoinWorkerThread = wire(new ForkJoinWorkerThread(fjp) with BlockContext {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = {
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
var result: T = null.asInstanceOf[T]
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker {
@volatile var isdone = false
- def block(): Boolean = {
- result = try awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence) finally { isdone = true }
+ override def block(): Boolean = {
+ result = try thunk finally { isdone = true }
true
}
- def isReleasable = isdone
+ override def isReleasable = isdone
})
result
}
diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala
index 132e1d79e7..098008e958 100644
--- a/src/library/scala/concurrent/impl/Future.scala
+++ b/src/library/scala/concurrent/impl/Future.scala
@@ -10,31 +10,13 @@ package scala.concurrent.impl
-import scala.concurrent.util.Duration
-import scala.concurrent.{Awaitable, ExecutionContext, CanAwait}
-import scala.collection.mutable.Stack
+import scala.concurrent.ExecutionContext
import scala.util.control.NonFatal
-private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] {
-
-}
private[concurrent] object Future {
-
- /** Wraps a block of code into an awaitable object. */
- private[concurrent] def body2awaitable[T](body: =>T) = new Awaitable[T] {
- def ready(atMost: Duration)(implicit permit: CanAwait) = {
- body
- this
- }
- def result(atMost: Duration)(implicit permit: CanAwait) = body
- }
-
- def boxedType(c: Class[_]): Class[_] = if (c.isPrimitive) scala.concurrent.Future.toBoxed(c) else c
-
- private[impl] class PromiseCompletingRunnable[T](body: => T)
- extends Runnable {
+ class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()
override def run() = {
@@ -44,7 +26,7 @@ private[concurrent] object Future {
}
}
- def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = {
+ def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = {
val runnable = new PromiseCompletingRunnable(body)
executor.execute(runnable)
runnable.promise.future
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index 84638586cf..c2df9ac296 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -18,7 +18,7 @@ import scala.util.control.NonFatal
-private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with Future[T] {
+private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index 76703bf081..a6488b602f 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -9,6 +9,7 @@
package scala
import scala.concurrent.util.Duration
+import scala.annotation.implicitNotFound
/** This package object contains primitives for concurrent and parallel programming.
*/
@@ -17,6 +18,41 @@ package object concurrent {
type CancellationException = java.util.concurrent.CancellationException
type TimeoutException = java.util.concurrent.TimeoutException
+ @implicitNotFound("Don't call `Awaitable` methods directly, use the `Await` object.")
+ sealed trait CanAwait
+ private implicit object AwaitPermission extends CanAwait
+
+ /**
+ * `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances.
+ */
+ object Await {
+ /**
+ * Invokes ready() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
+ * ready() blocks until the awaitable has completed or the timeout expires.
+ *
+ * Throws a TimeoutException if the timeout expires, as that is in the contract of `Awaitable.ready`.
+ * @param awaitable the `Awaitable` on which `ready` is to be called
+ * @param atMost the maximum timeout for which to wait
+ * @return the result of `awaitable.ready` which is defined to be the awaitable itself.
+ */
+ @throws(classOf[TimeoutException])
+ def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type =
+ blocking(awaitable.ready(atMost))
+
+ /**
+ * Invokes result() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
+ * result() blocks until the awaitable has completed or the timeout expires.
+ *
+ * Throws a TimeoutException if the timeout expires, or any exception thrown by `Awaitable.result`.
+ * @param awaitable the `Awaitable` on which `result` is to be called
+ * @param atMost the maximum timeout for which to wait
+ * @return the result of `awaitable.result`
+ */
+ @throws(classOf[Exception])
+ def result[T](awaitable: Awaitable[T], atMost: Duration): T =
+ blocking(awaitable.result(atMost))
+ }
+
/** Starts an asynchronous computation and returns a `Future` object with the result of that computation.
*
* The result becomes available once the asynchronous computation is completed.
@@ -36,46 +72,18 @@ package object concurrent {
*/
def promise[T]()(implicit execctx: ExecutionContext): Promise[T] = Promise[T]()
- /** Used to block on a piece of code which potentially blocks.
+ /** Used to designate a piece of code which potentially blocks, allowing the BlockContext to adjust the runtime's behavior.
+ * Properly marking blocking code may improve performance or avoid deadlocks.
*
- * @param body A piece of code which contains potentially blocking or long running calls.
- *
- * Calling this method may throw the following exceptions:
- * - CancellationException - if the computation was cancelled
- * - InterruptedException - in the case that a wait within the blockable object was interrupted
- * - TimeoutException - in the case that the blockable object timed out
- */
- def blocking[T](body: =>T): T = blocking(impl.Future.body2awaitable(body), Duration.Inf)
-
- /** Blocks on an awaitable object.
+ * If you have an `Awaitable` then you should use Await.result instead of `blocking`.
*
- * @param awaitable An object with a `block` method which runs potentially blocking or long running calls.
+ * @param body A piece of code which contains potentially blocking or long running calls.
*
* Calling this method may throw the following exceptions:
* - CancellationException - if the computation was cancelled
* - InterruptedException - in the case that a wait within the blockable object was interrupted
* - TimeoutException - in the case that the blockable object timed out
*/
- def blocking[T](awaitable: Awaitable[T], atMost: Duration): T =
- BlockContext.current.internalBlockingCall(awaitable, atMost)
-}
-
-/* concurrency constructs */
-package concurrent {
-
- sealed trait CanAwait
-
- object Await {
- private[concurrent] implicit val canAwaitEvidence = new CanAwait {}
-
- def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type = {
- blocking(awaitable, atMost)
- awaitable
- }
-
- def result[T](awaitable: Awaitable[T], atMost: Duration): T = {
- blocking(awaitable, atMost)
- }
-
- }
+ @throws(classOf[Exception])
+ def blocking[T](body: =>T): T = BlockContext.current.blockOn(body)
}
diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala
index 6c239721c3..c254472342 100644
--- a/src/partest/scala/tools/partest/nest/DirectRunner.scala
+++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala
@@ -59,8 +59,12 @@ trait DirectRunner {
val futures = kindFiles map (f => (f, pool submit callable(manager runTest f))) toMap
pool.shutdown()
- if (!pool.awaitTermination(4, TimeUnit.HOURS))
+ try if (!pool.awaitTermination(4, TimeUnit.HOURS))
NestUI.warning("Thread pool timeout elapsed before all tests were complete!")
+ catch { case t: InterruptedException =>
+ NestUI.warning("Thread pool was interrupted")
+ t.printStackTrace()
+ }
for ((file, future) <- futures) yield {
val state = if (future.isCancelled) TestState.Timeout else future.get
diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala
index 9ec66b8531..eb1ecda900 100644
--- a/src/reflect/scala/reflect/api/StandardNames.scala
+++ b/src/reflect/scala/reflect/api/StandardNames.scala
@@ -43,7 +43,6 @@ trait StandardNames extends base.StandardNames {
val SUPER_PREFIX_STRING: String
val TRAIT_SETTER_SEPARATOR_STRING: String
- val ANYNAME: TermName
val FAKE_LOCAL_THIS: TermName
val INITIALIZER: TermName
val LAZY_LOCAL: TermName
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index 210af661ee..761b993539 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -180,7 +180,7 @@ trait Mirrors extends api.Mirrors {
// Still fiddling with whether it's cleaner to do some of this setup here
// or from constructors. The latter approach tends to invite init order issues.
- EmptyPackageClass setInfo ClassInfoType(Nil, newPackageScope(EmptyPackageClass), EmptyPackageClass)
+ EmptyPackageClass setInfo rootLoader
EmptyPackage setInfo EmptyPackageClass.tpe
connectModuleToClass(EmptyPackage, EmptyPackageClass)
@@ -231,7 +231,6 @@ trait Mirrors extends api.Mirrors {
override def isEffectiveRoot = true
override def isStatic = true
override def isNestedClass = false
- override def ownerOfNewSymbols = EmptyPackageClass
}
// The empty package, which holds all top level types without given packages.
final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index 20da38fd63..72e6707f57 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -415,6 +415,9 @@ trait Names extends api.Names with LowPriorityNames {
}
else toString
}
+
+ @inline
+ final def fingerPrint: Long = (1L << start)
/** TODO - find some efficiency. */
def append(ch: Char) = newName("" + this + ch)
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index ceacd2afb0..89e3c52de6 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -41,10 +41,15 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
* This is necessary because when run from reflection every scope needs to have a
* SynchronizedScope as mixin.
*/
- class Scope protected[Scopes] (initElems: ScopeEntry = null) extends Iterable[Symbol] {
+ class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends Iterable[Symbol] {
+
+ /** A bitset containing the last 6 bits of the start value of every name
+ * stored in this scope.
+ */
+ var fingerPrints: Long = initFingerPrints
protected[Scopes] def this(base: Scope) = {
- this(base.elems)
+ this(base.elems, base.fingerPrints)
nestinglevel = base.nestinglevel + 1
}
@@ -95,7 +100,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param e ...
*/
- protected def enter(e: ScopeEntry) {
+ protected def enterEntry(e: ScopeEntry) {
elemsCache = null
if (hashtable ne null)
enterInHash(e)
@@ -113,7 +118,11 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param sym ...
*/
- def enter[T <: Symbol](sym: T): T = { enter(newScopeEntry(sym, this)); sym }
+ def enter[T <: Symbol](sym: T): T = {
+ fingerPrints |= sym.name.fingerPrint
+ enterEntry(newScopeEntry(sym, this))
+ sym
+ }
/** enter a symbol, asserting that no symbol with same name exists in scope
*
@@ -147,6 +156,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
}
def rehash(sym: Symbol, newname: Name) {
+ fingerPrints |= newname.fingerPrint
if (hashtable ne null) {
val index = sym.name.start & HASHMASK
var e1 = hashtable(index)
@@ -344,7 +354,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** The empty scope (immutable).
*/
object EmptyScope extends Scope {
- override def enter(e: ScopeEntry) {
+ override def enterEntry(e: ScopeEntry) {
abort("EmptyScope.enter")
}
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 165e04863c..c8a2424118 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -297,7 +297,7 @@ trait StdNames {
val WHILE_PREFIX = "while$"
// Compiler internal names
- val ANYNAME: NameType = "<anyname>"
+ val ANYname: NameType = "<anyname>"
val CONSTRUCTOR: NameType = "<init>"
val EQEQ_LOCAL_VAR: NameType = "eqEqTemp$"
val FAKE_LOCAL_THIS: NameType = "this$"
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index fab5c5a2e7..d484617767 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -813,11 +813,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def isEffectiveRoot = false
- /** For RootClass, this is EmptyPackageClass. For all other symbols,
- * the symbol itself.
- */
- def ownerOfNewSymbols = this
-
final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol
final def isOverridableMember = !(isClass || isEffectivelyFinal) && (this ne NoSymbol) && owner.isClass
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index f3dd1f03ad..01679a777d 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -14,6 +14,7 @@ import Flags._
import scala.util.control.ControlThrowable
import scala.annotation.tailrec
import util.Statistics
+import scala.runtime.ObjectRef
/* A standard type pattern match:
case ErrorType =>
@@ -668,7 +669,8 @@ trait Types extends api.Types { self: SymbolTable =>
* Note: unfortunately it doesn't work to exclude DEFERRED this way.
*/
def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): List[Symbol] =
- findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
+ findMembers(excludedFlags, requiredFlags)
+// findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
def memberBasedOnName(name: Name, excludedFlags: Long): Symbol =
findMember(name, excludedFlags, 0, false)
@@ -1018,6 +1020,72 @@ trait Types extends api.Types { self: SymbolTable =>
else (baseClasses.head.newOverloaded(this, alts))
}
+ def findMembers(excludedFlags: Long, requiredFlags: Long): List[Symbol] = {
+ // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
+ // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
+ // without this, the matchesType call would lead to type variables on both sides
+ // of a subtyping/equality judgement, which can lead to recursive types being constructed.
+ // See (t0851) for a situation where this happens.
+ val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
+
+ Statistics.incCounter(findMembersCount)
+ val start = Statistics.pushTimer(typeOpsStack, findMembersNanos)
+
+ //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
+ var members: Scope = null
+ var required = requiredFlags
+ var excluded = excludedFlags | DEFERRED
+ var continue = true
+ var self: Type = null
+ while (continue) {
+ continue = false
+ val bcs0 = baseClasses
+ var bcs = bcs0
+ while (!bcs.isEmpty) {
+ val decls = bcs.head.info.decls
+ var entry = decls.elems
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (members eq null) members = newScope
+ var others: ScopeEntry = members.lookupEntry(sym.name)
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.sym
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = members lookupNextEntry others
+ }
+ if (others eq null) members enter sym
+ } else if (excl == DEFERRED) {
+ continue = true
+ }
+ }
+ entry = entry.next
+ } // while (entry ne null)
+ // excluded = excluded | LOCAL
+ bcs = bcs.tail
+ } // while (!bcs.isEmpty)
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
+ } // while (continue)
+ Statistics.popTimer(typeOpsStack, start)
+ if (suspension ne null) suspension foreach (_.suspended = false)
+ if (members eq null) Nil else members.toList
+ }
+
/**
* Find member(s) in this type. If several members matching criteria are found, they are
* returned in an OverloadedSymbol
@@ -1040,75 +1108,83 @@ trait Types extends api.Types { self: SymbolTable =>
val start = Statistics.pushTimer(typeOpsStack, findMemberNanos)
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
- var members: Scope = null
var member: Symbol = NoSymbol
+ var members: List[Symbol] = null
+ var lastM: ::[Symbol] = null
+ var membertpe: Type = null
+ var required = requiredFlags
var excluded = excludedFlags | DEFERRED
var continue = true
var self: Type = null
- var membertpe: Type = null
+ val fingerPrint: Long = name.fingerPrint
+
while (continue) {
continue = false
val bcs0 = baseClasses
var bcs = bcs0
while (!bcs.isEmpty) {
val decls = bcs.head.info.decls
- var entry =
- if (name == nme.ANYNAME) decls.elems else decls.lookupEntry(name)
- while (entry ne null) {
- val sym = entry.sym
- if (sym hasAllFlags requiredFlags) {
- val excl = sym.getFlag(excluded)
- if (excl == 0L &&
- (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
- (bcs eq bcs0) ||
- !sym.isPrivateLocal ||
- (bcs0.head.hasTransOwner(bcs.head)))) {
- if (name.isTypeName || stableOnly && sym.isStable) {
- Statistics.popTimer(typeOpsStack, start)
- if (suspension ne null) suspension foreach (_.suspended = false)
- return sym
- } else if (member == NoSymbol) {
- member = sym
- } else if (members eq null) {
- if (member.name != sym.name ||
- !(member == sym ||
- member.owner != sym.owner &&
- !sym.isPrivate && {
- if (self eq null) self = this.narrow
- if (membertpe eq null) membertpe = self.memberType(member)
- (membertpe matches self.memberType(sym))
- })) {
- members = newScope
- members enter member
- members enter sym
- }
- } else {
- var prevEntry = members.lookupEntry(sym.name)
- var symtpe: Type = null
- while ((prevEntry ne null) &&
- !(prevEntry.sym == sym ||
- prevEntry.sym.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow
- if (symtpe eq null) symtpe = self.memberType(sym)
- self.memberType(prevEntry.sym) matches symtpe
- })) {
- prevEntry = members lookupNextEntry prevEntry
- }
- if (prevEntry eq null) {
- members enter sym
+ if ((fingerPrint & decls.fingerPrints) != 0) {
+ var entry = decls.lookupEntry(name)
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (name.isTypeName || stableOnly && sym.isStable) {
+ Statistics.popTimer(typeOpsStack, start)
+ if (suspension ne null) suspension foreach (_.suspended = false)
+ return sym
+ } else if (member eq NoSymbol) {
+ member = sym
+ } else if (members eq null) {
+ if ((member ne sym) &&
+ ((member.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (membertpe eq null) membertpe = self.memberType(member)
+ !(membertpe matches self.memberType(sym))
+ })) {
+ lastM = new ::(sym, null)
+ members = member :: lastM
+ }
+ } else {
+ var others: List[Symbol] = members
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.head
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = others.tail
+ }
+ if (others eq null) {
+ val lastM1 = new ::(sym, null)
+ lastM.tl = lastM1
+ lastM = lastM1
+ }
}
+ } else if (excl == DEFERRED) {
+ continue = true
}
- } else if (excl == DEFERRED.toLong) {
- continue = true
}
- }
- entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
- } // while (entry ne null)
+ entry = decls lookupNextEntry entry
+ } // while (entry ne null)
+ } // if (fingerPrint matches)
// excluded = excluded | LOCAL
bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
} // while (!bcs.isEmpty)
- excluded = excludedFlags
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
} // while (continue)
Statistics.popTimer(typeOpsStack, start)
if (suspension ne null) suspension foreach (_.suspended = false)
@@ -1117,9 +1193,11 @@ trait Types extends api.Types { self: SymbolTable =>
member
} else {
Statistics.incCounter(multMemberCount)
- baseClasses.head.newOverloaded(this, members.toList)
+ lastM.tl = Nil
+ baseClasses.head.newOverloaded(this, members)
}
}
+
/** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */
def skolemsExceptMethodTypeParams: List[Symbol] = {
var boundSyms: List[Symbol] = List()
@@ -1610,8 +1688,13 @@ trait Types extends api.Types { self: SymbolTable =>
if (period != currentPeriod) {
tpe.baseClassesPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
- tpe.baseClassesCache = null
- tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ val start = Statistics.pushTimer(typeOpsStack, baseClassesNanos)
+ try {
+ tpe.baseClassesCache = null
+ tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ } finally {
+ Statistics.popTimer(typeOpsStack, start)
+ }
}
}
if (tpe.baseClassesCache eq null)
@@ -5066,7 +5149,7 @@ trait Types extends api.Types { self: SymbolTable =>
*/
def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
def createDummyClone(pre: Type): Type = {
- val dummy = currentOwner.enclClass.newValue(nme.ANYNAME).setInfo(pre.widen)
+ val dummy = currentOwner.enclClass.newValue(nme.ANYname).setInfo(pre.widen)
singleType(ThisType(currentOwner.enclClass), dummy)
}
def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match {
@@ -6909,14 +6992,17 @@ object TypesStats {
val lubCount = Statistics.newCounter ("#toplevel lubs/glbs")
val nestedLubCount = Statistics.newCounter ("#all lubs/glbs")
val findMemberCount = Statistics.newCounter ("#findMember ops")
+ val findMembersCount = Statistics.newCounter ("#findMembers ops")
val noMemberCount = Statistics.newSubCounter(" of which not found", findMemberCount)
val multMemberCount = Statistics.newSubCounter(" of which multiple overloaded", findMemberCount)
val typerNanos = Statistics.newTimer ("time spent typechecking", "typer")
val lubNanos = Statistics.newStackableTimer("time spent in lubs", typerNanos)
val subtypeNanos = Statistics.newStackableTimer("time spent in <:<", typerNanos)
val findMemberNanos = Statistics.newStackableTimer("time spent in findmember", typerNanos)
+ val findMembersNanos = Statistics.newStackableTimer("time spent in findmembers", typerNanos)
val asSeenFromNanos = Statistics.newStackableTimer("time spent in asSeenFrom", typerNanos)
val baseTypeSeqNanos = Statistics.newStackableTimer("time spent in baseTypeSeq", typerNanos)
+ val baseClassesNanos = Statistics.newStackableTimer("time spent in baseClasses", typerNanos)
val compoundBaseTypeSeqCount = Statistics.newSubCounter(" of which for compound types", baseTypeSeqCount)
val typerefBaseTypeSeqCount = Statistics.newSubCounter(" of which for typerefs", baseTypeSeqCount)
val singletonBaseTypeSeqCount = Statistics.newSubCounter(" of which for singletons", baseTypeSeqCount)
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 185621efa4..75d43a7553 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -1001,7 +1001,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
private lazy val magicSymbols: Map[(String, Name), Symbol] = {
def mapEntry(sym: Symbol): ((String, Name), Symbol) = (sym.owner.fullName, sym.name) -> sym
- Map() ++ (definitions.magicSymbols filter (_.isClass) map mapEntry)
+ Map() ++ (definitions.magicSymbols filter (_.isType) map mapEntry)
}
/** 1. If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package
diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
index c1cd5d2911..eb48e9dc79 100644
--- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
@@ -99,8 +99,10 @@ trait SymbolLoaders { self: SymbolTable =>
0 < dp && dp < (name.length - 1)
}
- class PackageScope(pkgClass: Symbol) extends Scope() with SynchronizedScope {
+ class PackageScope(pkgClass: Symbol) extends Scope(initFingerPrints = -1L) // disable fingerprinting as we do not know entries beforehand
+ with SynchronizedScope {
assert(pkgClass.isType)
+ // disable fingerprinting as we do not know entries beforehand
private val negatives = mutable.Set[Name]() // Syncnote: Performance only, so need not be protected.
override def lookupEntry(name: Name): ScopeEntry = {
val e = super.lookupEntry(name)
diff --git a/test/files/jvm/future-spec/FutureTests.scala b/test/files/jvm/future-spec/FutureTests.scala
index ca9ff5090f..30e1a722bf 100644
--- a/test/files/jvm/future-spec/FutureTests.scala
+++ b/test/files/jvm/future-spec/FutureTests.scala
@@ -507,6 +507,12 @@ object FutureTests extends MinimalScalaTest {
}
Await.ready(complex, defaultTimeout).isCompleted mustBe (true)
}
+
+ "should not throw when Await.ready" in {
+ val expected = try Right(5 / 0) catch { case a: ArithmeticException => Left(a) }
+ val f = future(5).map(_ / 0)
+ Await.ready(f, defaultTimeout).value.get.toString mustBe expected.toString
+ }
}
diff --git a/test/files/jvm/future-spec/PromiseTests.scala b/test/files/jvm/future-spec/PromiseTests.scala
index 49bc642b57..d15bb31f36 100644
--- a/test/files/jvm/future-spec/PromiseTests.scala
+++ b/test/files/jvm/future-spec/PromiseTests.scala
@@ -78,7 +78,7 @@ object PromiseTests extends MinimalScalaTest {
"contain a value" in { f((future, result) => future.value mustBe (Some(Right(result)))) }
- "return result with 'blocking'" in { f((future, result) => blocking(future, defaultTimeout) mustBe (result)) }
+ "return when ready with 'Await.ready'" in { f((future, result) => Await.ready(future, defaultTimeout).isCompleted mustBe (true)) }
"return result with 'Await.result'" in { f((future, result) => Await.result(future, defaultTimeout) mustBe (result)) }
@@ -163,12 +163,9 @@ object PromiseTests extends MinimalScalaTest {
})
}
- "throw exception with 'blocking'" in {
+ "throw not throw exception with 'Await.ready'" in {
f {
- (future, message) =>
- intercept[E] {
- blocking(future, defaultTimeout)
- }.getMessage mustBe (message)
+ (future, message) => Await.ready(future, defaultTimeout).isCompleted mustBe (true)
}
}
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index 5c9c71f3f8..1209b710b0 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -4,7 +4,9 @@ import scala.concurrent.{
TimeoutException,
SyncVar,
ExecutionException,
- ExecutionContext
+ ExecutionContext,
+ CanAwait,
+ Await
}
import scala.concurrent.{ future, promise, blocking }
import scala.util.{ Try, Success, Failure }
@@ -647,7 +649,7 @@ trait FutureProjections extends TestBase {
val f = future {
throw cause
}
- assert(blocking(f.failed, Duration(500, "ms")) == cause)
+ assert(Await.result(f.failed, Duration(500, "ms")) == cause)
done()
}
@@ -655,7 +657,7 @@ trait FutureProjections extends TestBase {
done =>
val f = future { 0 }
try {
- blocking(f.failed, Duration(500, "ms"))
+ Await.result(f.failed, Duration(500, "ms"))
assert(false)
} catch {
case nsee: NoSuchElementException => done()
@@ -678,7 +680,7 @@ trait Blocking extends TestBase {
def testAwaitSuccess(): Unit = once {
done =>
val f = future { 0 }
- blocking(f, Duration(500, "ms"))
+ Await.result(f, Duration(500, "ms"))
done()
}
@@ -689,7 +691,7 @@ trait Blocking extends TestBase {
throw cause
}
try {
- blocking(f, Duration(500, "ms"))
+ Await.result(f, Duration(500, "ms"))
assert(false)
} catch {
case t =>
@@ -708,7 +710,7 @@ trait BlockContexts extends TestBase {
import scala.concurrent.{ Await, Awaitable, BlockContext }
private def getBlockContext(body: => BlockContext): BlockContext = {
- blocking(Future { body }, Duration(500, "ms"))
+ Await.result(Future { body }, Duration(500, "ms"))
}
// test outside of an ExecutionContext
@@ -727,8 +729,7 @@ trait BlockContexts extends TestBase {
def testPushCustom(): Unit = {
val orig = BlockContext.current
val customBC = new BlockContext() {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- orig.internalBlockingCall(awaitable, atMost)
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = orig.blockOn(thunk)
}
val bc = getBlockContext({
@@ -744,8 +745,7 @@ trait BlockContexts extends TestBase {
def testPopCustom(): Unit = {
val orig = BlockContext.current
val customBC = new BlockContext() {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- orig.internalBlockingCall(awaitable, atMost)
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = orig.blockOn(thunk)
}
val bc = getBlockContext({
diff --git a/test/files/pos/t6047.flags b/test/files/pos/t6047.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/pos/t6047.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/pos/t6047.scala b/test/files/pos/t6047.scala
new file mode 100644
index 0000000000..66b52b285f
--- /dev/null
+++ b/test/files/pos/t6047.scala
@@ -0,0 +1,20 @@
+import scala.reflect.makro.Context
+import java.io.InputStream
+
+object Macros {
+ def unpack[A](input: InputStream): A = macro unpack_impl[A]
+
+ def unpack_impl[A: c.TypeTag](c: Context)(input: c.Expr[InputStream]): c.Expr[A] = {
+ import c.universe._
+
+ def unpackcode(tpe: c.Type): c.Expr[_] = {
+ if (tpe <:< implicitly[c.AbsTypeTag[Traversable[_]]].tpe) {
+
+ }
+ ???
+ }
+
+ unpackcode(c.typeOf[A])
+ ???
+ }
+ } \ No newline at end of file
diff --git a/test/files/run/reflection-magicsymbols-repl.check b/test/files/run/reflection-magicsymbols-repl.check
new file mode 100644
index 0000000000..d2ef4ad3cd
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-repl.check
@@ -0,0 +1,39 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.reflect.runtime.universe._
+import scala.reflect.runtime.universe._
+
+scala> class A {
+ def foo1(x: Int*) = ???
+ def foo2(x: => Int) = ???
+ def foo3(x: Any) = ???
+ def foo4(x: AnyRef) = ???
+ def foo5(x: AnyVal) = ???
+ def foo6(x: Null) = ???
+ def foo7(x: Nothing) = ???
+ def foo8(x: Singleton) = ???
+}
+defined class A
+
+scala> def test(n: Int): Unit = {
+ val sig = typeOf[A] member newTermName("foo" + n) typeSignature
+ val x = sig.asInstanceOf[MethodType].params.head
+ println(x.typeSignature)
+}
+warning: there were 1 feature warnings; re-run with -feature for details
+test: (n: Int)Unit
+
+scala> for (i <- 1 to 8) test(i)
+scala.Int*
+=> scala.Int
+scala.Any
+scala.AnyRef
+scala.AnyVal
+scala.Null
+scala.Nothing
+scala.Singleton
+
+scala>
diff --git a/test/files/run/reflection-magicsymbols-repl.scala b/test/files/run/reflection-magicsymbols-repl.scala
new file mode 100644
index 0000000000..26127b8661
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-repl.scala
@@ -0,0 +1,23 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |import scala.reflect.runtime.universe._
+ |class A {
+ | def foo1(x: Int*) = ???
+ | def foo2(x: => Int) = ???
+ | def foo3(x: Any) = ???
+ | def foo4(x: AnyRef) = ???
+ | def foo5(x: AnyVal) = ???
+ | def foo6(x: Null) = ???
+ | def foo7(x: Nothing) = ???
+ | def foo8(x: Singleton) = ???
+ |}
+ |def test(n: Int): Unit = {
+ | val sig = typeOf[A] member newTermName("foo" + n) typeSignature
+ | val x = sig.asInstanceOf[MethodType].params.head
+ | println(x.typeSignature)
+ |}
+ |for (i <- 1 to 8) test(i)
+ |""".stripMargin
+}
diff --git a/test/files/run/reflection-magicsymbols-vanilla.check b/test/files/run/reflection-magicsymbols-vanilla.check
new file mode 100644
index 0000000000..4f4e8d94a9
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-vanilla.check
@@ -0,0 +1,8 @@
+Int*
+=> Int
+Any
+AnyRef
+AnyVal
+Null
+Nothing
+Singleton
diff --git a/test/files/run/reflection-magicsymbols-vanilla.scala b/test/files/run/reflection-magicsymbols-vanilla.scala
new file mode 100644
index 0000000000..32819dcc46
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-vanilla.scala
@@ -0,0 +1,20 @@
+class A {
+ def foo1(x: Int*) = ???
+ def foo2(x: => Int) = ???
+ def foo3(x: Any) = ???
+ def foo4(x: AnyRef) = ???
+ def foo5(x: AnyVal) = ???
+ def foo6(x: Null) = ???
+ def foo7(x: Nothing) = ???
+ def foo8(x: Singleton) = ???
+}
+
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ def test(n: Int): Unit = {
+ val sig = typeOf[A] member newTermName("foo" + n) typeSignature
+ val x = sig.asInstanceOf[MethodType].params.head
+ println(x.typeSignature)
+ }
+ for (i <- 1 to 8) test(i)
+}
diff --git a/test/files/run/reflection-magicsymbols.check b/test/files/run/reflection-magicsymbols.check
deleted file mode 100644
index 2600847d99..0000000000
--- a/test/files/run/reflection-magicsymbols.check
+++ /dev/null
@@ -1,22 +0,0 @@
-Type in expressions to have them evaluated.
-Type :help for more information.
-
-scala>
-
-scala> import scala.reflect.runtime.universe._
-import scala.reflect.runtime.universe._
-
-scala> class A { def foo(x: Int*) = 1 }
-defined class A
-
-scala> val sig = typeOf[A] member newTermName("foo") typeSignature
-warning: there were 1 feature warnings; re-run with -feature for details
-sig: reflect.runtime.universe.Type = (x: <?>)scala.Int
-
-scala> val x = sig.asInstanceOf[MethodType].params.head
-x: reflect.runtime.universe.Symbol = value x
-
-scala> println(x.typeSignature)
-scala.Int*
-
-scala>
diff --git a/test/files/run/reflection-magicsymbols.scala b/test/files/run/reflection-magicsymbols.scala
deleted file mode 100644
index a40845d6ac..0000000000
--- a/test/files/run/reflection-magicsymbols.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-import scala.tools.partest.ReplTest
-
-object Test extends ReplTest {
- def code = """
- |import scala.reflect.runtime.universe._
- |class A { def foo(x: Int*) = 1 }
- |val sig = typeOf[A] member newTermName("foo") typeSignature
- |val x = sig.asInstanceOf[MethodType].params.head
- |println(x.typeSignature)
- |""".stripMargin
-}
diff --git a/test/files/run/t6086-repl.check b/test/files/run/t6086-repl.check
new file mode 100644
index 0000000000..f868aa18d0
--- /dev/null
+++ b/test/files/run/t6086-repl.check
@@ -0,0 +1,12 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> case class X(s: String)
+defined class X
+
+scala> scala.reflect.runtime.universe.typeOf[X]
+res0: reflect.runtime.universe.Type = X
+
+scala>
diff --git a/test/files/run/t6086-repl.scala b/test/files/run/t6086-repl.scala
new file mode 100644
index 0000000000..87f94ec9f6
--- /dev/null
+++ b/test/files/run/t6086-repl.scala
@@ -0,0 +1,8 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |case class X(s: String)
+ |scala.reflect.runtime.universe.typeOf[X]
+ |""".stripMargin
+}
diff --git a/test/files/run/t6086-vanilla.check b/test/files/run/t6086-vanilla.check
new file mode 100644
index 0000000000..fd66be08d0
--- /dev/null
+++ b/test/files/run/t6086-vanilla.check
@@ -0,0 +1 @@
+X
diff --git a/test/files/run/t6086-vanilla.scala b/test/files/run/t6086-vanilla.scala
new file mode 100644
index 0000000000..b4de581ad5
--- /dev/null
+++ b/test/files/run/t6086-vanilla.scala
@@ -0,0 +1,6 @@
+case class X(s: String)
+
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ println(typeOf[X])
+} \ No newline at end of file