Skip to content

Commit eda88c8

Browse files
committed
Merge pull request scala#1764 from adriaanm/backport/sip14
SIP-14 backport to 2.9.x
2 parents 8e3d23a + f0bc3f7 commit eda88c8

32 files changed

+4925
-15
lines changed

build.xml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,9 @@ INITIALISATION
286286
<property name="scalac.args.optimise" value=""/>
287287
<!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
288288
This is to facilitate testing new command line options which do not yet exist in starr. -->
289-
<property name="scalac.args.quickonly" value=""/>
289+
<property name="scalac.args.quickonly" value="-Ydependent-method-types"/>
290290
<property name="scalac.args.all" value="${scalac.args} ${scalac.args.optimise}"/>
291-
<property name="scalac.args.quick" value="${scalac.args.all} ${scalac.args.quickonly}"/>
291+
<property name="scalac.args.quick" value="${scalac.args.all} ${scalac.args.quickonly}"/>
292292
<!-- Setting-up Ant contrib tasks -->
293293
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant/ant-contrib.jar"/>
294294
<!-- This is the start time for the distribution -->
@@ -376,8 +376,9 @@ LOCAL REFERENCE BUILD (LOCKER)
376376
<javac
377377
srcdir="${src.dir}/library"
378378
destdir="${build-locker.dir}/classes/library"
379-
classpath="${build-locker.dir}/classes/library"
379+
classpathref="quick.compilation.path"
380380
includes="**/*.java"
381+
excludes="scala/concurrent/**/*.java"
381382
target="1.5" source="1.5">
382383
<compilerarg line="${javac.args}"/>
383384
</javac>
@@ -392,6 +393,17 @@ LOCAL REFERENCE BUILD (LOCKER)
392393
srcdir="${src.dir}/library"
393394
jvmargs="${scalacfork.jvmargs}">
394395
<include name="**/*.scala"/>
396+
<!-- Exclude duration package and everything that depends on it -->
397+
<exclude name="scala/concurrent/duration/**/*.scala"/>
398+
<exclude name="scala/concurrent/package.scala"/>
399+
<exclude name="scala/concurrent/Awaitable.scala"/>
400+
<exclude name="scala/concurrent/Future.scala"/>
401+
<exclude name="scala/concurrent/Promise.scala"/>
402+
<exclude name="scala/concurrent/ExecutionContext.scala"/>
403+
<exclude name="scala/concurrent/BlockContext.scala"/>
404+
<exclude name="scala/concurrent/impl/Future.scala"/>
405+
<exclude name="scala/concurrent/impl/Promise.scala"/>
406+
<exclude name="scala/concurrent/impl/ExecutionContextImpl.scala"/>
395407
<compilationpath>
396408
<pathelement location="${build-locker.dir}/classes/library"/>
397409
<pathelement location="${lib.dir}/forkjoin.jar"/>
@@ -546,7 +558,7 @@ QUICK BUILD (QUICK)
546558
<javac
547559
srcdir="${src.dir}/library"
548560
destdir="${build-quick.dir}/classes/library"
549-
classpath="${build-quick.dir}/classes/library"
561+
classpathref="quick.compilation.path"
550562
includes="**/*.java"
551563
target="1.5" source="1.5">
552564
<compilerarg line="${javac.args}"/>
@@ -1083,7 +1095,7 @@ BOOTSTRAPPING BUILD (STRAP)
10831095
<javac
10841096
srcdir="${src.dir}/library"
10851097
destdir="${build-strap.dir}/classes/library"
1086-
classpath="${build-strap.dir}/classes/library"
1098+
classpathref="strap.compilation.path"
10871099
includes="**/*.java"
10881100
target="1.5" source="1.5">
10891101
<compilerarg line="${javac.args}"/>
@@ -1100,7 +1112,7 @@ BOOTSTRAPPING BUILD (STRAP)
11001112
destdir="${build-strap.dir}/classes/library"
11011113
compilerpathref="pack.classpath"
11021114
srcpath="${src.dir}/library"
1103-
params="${scalac.args.all}"
1115+
params="${scalac.args.quick}"
11041116
srcdir="${src.dir}/library"
11051117
jvmargs="${scalacfork.jvmargs}">
11061118
<include name="**/*.scala"/>
@@ -1109,7 +1121,7 @@ BOOTSTRAPPING BUILD (STRAP)
11091121
<scalacfork
11101122
destdir="${build-strap.dir}/classes/library"
11111123
compilerpathref="pack.classpath"
1112-
params="${scalac.args.all}"
1124+
params="${scalac.args.quick}"
11131125
srcdir="${src.dir}/actors"
11141126
jvmargs="${scalacfork.jvmargs}">
11151127
<include name="**/*.scala"/>
@@ -1118,7 +1130,7 @@ BOOTSTRAPPING BUILD (STRAP)
11181130
<scalacfork
11191131
destdir="${build-strap.dir}/classes/library"
11201132
compilerpathref="pack.classpath"
1121-
params="${scalac.args.all}"
1133+
params="${scalac.args.quick}"
11221134
srcdir="${src.dir}/dbc"
11231135
jvmargs="${scalacfork.jvmargs}">
11241136
<include name="**/*.scala"/>
@@ -1127,7 +1139,7 @@ BOOTSTRAPPING BUILD (STRAP)
11271139
<scalacfork
11281140
destdir="${build-strap.dir}/classes/library"
11291141
compilerpathref="pack.classpath"
1130-
params="${scalac.args.all}"
1142+
params="${scalac.args.quick}"
11311143
srcdir="${src.dir}/swing"
11321144
jvmargs="${scalacfork.jvmargs}">
11331145
<include name="**/*.scala"/>
@@ -1163,7 +1175,7 @@ BOOTSTRAPPING BUILD (STRAP)
11631175
<scalacfork
11641176
destdir="${build-strap.dir}/classes/compiler"
11651177
compilerpathref="pack.classpath"
1166-
params="${scalac.args.all}"
1178+
params="${scalac.args.quick}"
11671179
srcdir="${src.dir}/compiler"
11681180
jvmargs="${scalacfork.jvmargs}">
11691181
<include name="**/*.scala"/>
@@ -1531,6 +1543,7 @@ DOCUMENTATION
15311543
docUncompilable="${src.dir}/library-aux"
15321544
sourcepath="${src.dir}"
15331545
classpathref="pack.classpath"
1546+
addparams="-Ydependent-method-types"
15341547
docRootContent="${build-docs.dir}/library/lib/rootdoc.txt">
15351548
<src>
15361549
<files includes="${src.dir}/actors"/>

src/compiler/scala/tools/nsc/ast/TreeGen.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ abstract class TreeGen {
124124

125125
/** Computes stable type for a tree if possible */
126126
def stableTypeFor(tree: Tree): Option[Type] = tree match {
127+
case This(_) if tree.symbol != null && !tree.symbol.isError =>
128+
Some(ThisType(tree.symbol))
127129
case Ident(_) if tree.symbol.isStable =>
128130
Some(singleType(tree.symbol.owner.thisType, tree.symbol))
129131
case Select(qual, _) if ((tree.symbol ne null) && (qual.tpe ne null)) && // turned assert into guard for #4064

src/compiler/scala/tools/nsc/backend/icode/Members.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ trait Members { self: ICodes =>
154154
var returnType: TypeKind = _
155155

156156
var recursive: Boolean = false
157+
var bytecodeHasEHs = false // set by ICodeReader only, used by Inliner to prevent inlining (SI-6188)
157158

158159
/** local variables and method parameters */
159160
var locals: List[Local] = Nil

src/compiler/scala/tools/nsc/backend/opt/Inliners.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ abstract class Inliners extends SubComponent {
311311
def isRecursive = m.recursive
312312
def hasCode = m.code != null
313313
def hasSourceFile = m.sourceFile != null
314-
def hasHandlers = handlers.nonEmpty
314+
def hasHandlers = handlers.nonEmpty || m.bytecodeHasEHs
315315

316316
// the number of inlined calls in 'm', used by 'shouldInline'
317317
var inlinedCalls = 0
@@ -495,7 +495,7 @@ abstract class Inliners extends SubComponent {
495495
}
496496

497497
def isStampedForInlining(stack: TypeStack) =
498-
!sameSymbols && inc.hasCode && shouldInline && isSafeToInline(stack)
498+
!sameSymbols && inc.hasCode && !inc.m.bytecodeHasEHs && shouldInline && isSafeToInline(stack)
499499

500500
def logFailure(stack: TypeStack) = log(
501501
"""|inline failed for %s:

src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ abstract class ICodeReader extends ClassfileParser {
618618
while (pc < codeLength) parseInstruction
619619

620620
val exceptionEntries = in.nextChar.toInt
621+
code.containsEHs = (exceptionEntries != 0)
621622
var i = 0
622623
while (i < exceptionEntries) {
623624
// skip start end PC
@@ -669,6 +670,7 @@ abstract class ICodeReader extends ClassfileParser {
669670

670671
var containsDUPX = false
671672
var containsNEW = false
673+
var containsEHs = false
672674

673675
def emit(i: Instruction) {
674676
instrs += ((pc, i))
@@ -686,6 +688,7 @@ abstract class ICodeReader extends ClassfileParser {
686688

687689
val code = new Code(method)
688690
method.setCode(code)
691+
method.bytecodeHasEHs = containsEHs
689692
var bb = code.startBlock
690693

691694
def makeBasicBlocks: mutable.Map[Int, BasicBlock] =
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
package scala.concurrent
10+
11+
12+
13+
import scala.concurrent.duration.Duration
14+
15+
16+
17+
/**
18+
* An object that may eventually be completed with a result value of type `T` which may be
19+
* awaited using blocking methods.
20+
*
21+
* The [[Await]] object provides methods that allow accessing the result of an `Awaitable`
22+
* by blocking the current thread until the `Awaitable` has been completed or a timeout has
23+
* occurred.
24+
*/
25+
trait Awaitable[+T] {
26+
27+
/**
28+
* Await the "completed" state of this `Awaitable`.
29+
*
30+
* '''''This method should not be called directly; use [[Await.ready]] instead.'''''
31+
*
32+
* @param atMost
33+
* maximum wait time, which may be negative (no waiting is done),
34+
* [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive
35+
* duration
36+
* @return this `Awaitable`
37+
* @throws InterruptedException if the current thread is interrupted while waiting
38+
* @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready
39+
* @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
40+
*/
41+
@throws(classOf[TimeoutException])
42+
@throws(classOf[InterruptedException])
43+
def ready(atMost: Duration)(implicit permit: CanAwait): this.type
44+
45+
/**
46+
* Await and return the result (of type `T`) of this `Awaitable`.
47+
*
48+
* '''''This method should not be called directly; use [[Await.result]] instead.'''''
49+
*
50+
* @param atMost
51+
* maximum wait time, which may be negative (no waiting is done),
52+
* [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive
53+
* duration
54+
* @return the result value if the `Awaitable` is completed within the specific maximum wait time
55+
* @throws InterruptedException if the current thread is interrupted while waiting
56+
* @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready
57+
* @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
58+
*/
59+
@throws(classOf[Exception])
60+
def result(atMost: Duration)(implicit permit: CanAwait): T
61+
}
62+
63+
64+
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
package scala.concurrent
10+
11+
/**
12+
* A context to be notified by `scala.concurrent.blocking` when
13+
* a thread is about to block. In effect this trait provides
14+
* the implementation for `scala.concurrent.Await`.
15+
* `scala.concurrent.Await.result()` and `scala.concurrent.Await.ready()`
16+
* locates an instance of `BlockContext` by first looking for one
17+
* provided through `BlockContext.withBlockContext()` and failing that,
18+
* checking whether `Thread.currentThread` is an instance of `BlockContext`.
19+
* So a thread pool can have its `java.lang.Thread` instances implement
20+
* `BlockContext`. There's a default `BlockContext` used if the thread
21+
* doesn't implement `BlockContext`.
22+
*
23+
* Typically, you'll want to chain to the previous `BlockContext`,
24+
* like this:
25+
* {{{
26+
* val oldContext = BlockContext.current
27+
* val myContext = new BlockContext {
28+
* override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
29+
* // you'd have code here doing whatever you need to do
30+
* // when the thread is about to block.
31+
* // Then you'd chain to the previous context:
32+
* oldContext.blockOn(thunk)
33+
* }
34+
* }
35+
* BlockContext.withBlockContext(myContext) {
36+
* // then this block runs with myContext as the handler
37+
* // for scala.concurrent.blocking
38+
* }
39+
* }}}
40+
*/
41+
trait BlockContext {
42+
43+
/** Used internally by the framework;
44+
* Designates (and eventually executes) a thunk which potentially blocks the calling `Thread`.
45+
*
46+
* Clients must use `scala.concurrent.blocking` or `scala.concurrent.Await` instead.
47+
*/
48+
def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T
49+
}
50+
51+
object BlockContext {
52+
private object DefaultBlockContext extends BlockContext {
53+
override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = thunk
54+
}
55+
56+
private val contextLocal = new ThreadLocal[BlockContext]()
57+
58+
/** Obtain the current thread's current `BlockContext`. */
59+
def current: BlockContext = contextLocal.get match {
60+
case null => Thread.currentThread match {
61+
case ctx: BlockContext => ctx
62+
case _ => DefaultBlockContext
63+
}
64+
case some => some
65+
}
66+
67+
/** Pushes a current `BlockContext` while executing `body`. */
68+
def withBlockContext[T](blockContext: BlockContext)(body: => T): T = {
69+
val old = contextLocal.get // can be null
70+
try {
71+
contextLocal.set(blockContext)
72+
body
73+
} finally {
74+
contextLocal.set(old)
75+
}
76+
}
77+
}

src/library/scala/concurrent/DelayedLazyVal.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
package scala.concurrent
1111

12-
import ops.future
13-
1412
/** A <code>DelayedLazyVal</code> is a wrapper for lengthy
1513
* computations which have a valid partially computed result.
1614
* The first argument is a function for obtaining the result
@@ -41,7 +39,7 @@ class DelayedLazyVal[T](f: () => T, body: => Unit) {
4139
*/
4240
def apply(): T = if (isDone) complete else f()
4341

44-
future {
42+
ops.future {
4543
body
4644
_isDone = true
4745
}

0 commit comments

Comments
 (0)