aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scala/async/internal
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-07-21 12:40:37 +0200
committerJason Zaugg <jzaugg@gmail.com>2014-07-21 15:45:52 +0200
commitde102789917e4b9aeae2836bde70c2a8c29a7e0e (patch)
tree88338e5ada77918fc9cb251e626aec406722779f /src/main/scala/scala/async/internal
parenta08a822df9987bf34ec804f0e5a537da75fd3294 (diff)
parent154a2d7d7fab1b6db940a01c212c8de0138ae930 (diff)
downloadscala-async-de102789917e4b9aeae2836bde70c2a8c29a7e0e.tar.gz
scala-async-de102789917e4b9aeae2836bde70c2a8c29a7e0e.tar.bz2
scala-async-de102789917e4b9aeae2836bde70c2a8c29a7e0e.zip
Merge remote-tracking branch 'origin/2.10.x' into merge/2.10.x-to-master-20140721
Conflicts: src/main/scala/scala/async/internal/AsyncTransform.scala src/main/scala/scala/async/internal/Lifter.scala
Diffstat (limited to 'src/main/scala/scala/async/internal')
-rw-r--r--src/main/scala/scala/async/internal/AsyncTransform.scala7
-rw-r--r--src/main/scala/scala/async/internal/Lifter.scala3
-rw-r--r--src/main/scala/scala/async/internal/LiveVariables.scala71
-rw-r--r--src/main/scala/scala/async/internal/TransformUtils.scala8
4 files changed, 55 insertions, 34 deletions
diff --git a/src/main/scala/scala/async/internal/AsyncTransform.scala b/src/main/scala/scala/async/internal/AsyncTransform.scala
index aca8c7e..66cfb87 100644
--- a/src/main/scala/scala/async/internal/AsyncTransform.scala
+++ b/src/main/scala/scala/async/internal/AsyncTransform.scala
@@ -157,9 +157,10 @@ trait AsyncTransform {
case ValDef(_, _, _, rhs) if liftedSyms(tree.symbol) =>
api.atOwner(api.currentOwner) {
val fieldSym = tree.symbol
- val set = Assign(gen.mkAttributedStableRef(thisType(fieldSym.owner.asClass), fieldSym), api.recur(rhs))
- set.changeOwner(tree.symbol, api.currentOwner)
- api.typecheck(atPos(tree.pos)(set))
+ val lhs = atPos(tree.pos) {
+ gen.mkAttributedStableRef(thisType(fieldSym.owner.asClass), fieldSym)
+ }
+ treeCopy.Assign(tree, lhs, api.recur(rhs)).setType(definitions.UnitTpe).changeOwner(fieldSym, api.currentOwner)
}
case _: DefTree if liftedSyms(tree.symbol) =>
EmptyTree
diff --git a/src/main/scala/scala/async/internal/Lifter.scala b/src/main/scala/scala/async/internal/Lifter.scala
index bf7bdbd..4242a8e 100644
--- a/src/main/scala/scala/async/internal/Lifter.scala
+++ b/src/main/scala/scala/async/internal/Lifter.scala
@@ -115,8 +115,7 @@ trait Lifter {
sym.setFlag(MUTABLE | STABLE | PRIVATE | LOCAL)
sym.setName(name.fresh(sym.name.toTermName))
sym.setInfo(deconst(sym.info))
- val zeroRhs = atPos(t.pos)(gen.mkZero(vd.symbol.info))
- treeCopy.ValDef(vd, Modifiers(sym.flags), sym.name, TypeTree(tpe(sym)).setPos(t.pos), zeroRhs)
+ treeCopy.ValDef(vd, Modifiers(sym.flags), sym.name, TypeTree(tpe(sym)).setPos(t.pos), EmptyTree)
case dd@DefDef(_, _, tparams, vparamss, tpt, rhs) =>
sym.setName(this.name.fresh(sym.name.toTermName))
sym.setFlag(PRIVATE | LOCAL)
diff --git a/src/main/scala/scala/async/internal/LiveVariables.scala b/src/main/scala/scala/async/internal/LiveVariables.scala
index 7f386c8..5b49398 100644
--- a/src/main/scala/scala/async/internal/LiveVariables.scala
+++ b/src/main/scala/scala/async/internal/LiveVariables.scala
@@ -126,14 +126,22 @@ trait LiveVariables {
/** Tests if `state1` is a predecessor of `state2`.
*/
- def isPred(state1: Int, state2: Int, seen: Set[Int] = Set()): Boolean =
- if (seen(state1)) false // breaks cycles in the CFG
- else cfg get state1 match {
- case Some(nextStates) =>
- nextStates.contains(state2) || nextStates.exists(isPred(_, state2, seen + state1))
- case None =>
- false
- }
+ def isPred(state1: Int, state2: Int): Boolean = {
+ val seen = scala.collection.mutable.HashSet[Int]()
+
+ def isPred0(state1: Int, state2: Int): Boolean =
+ if(state1 == state2) false
+ else if (seen(state1)) false // breaks cycles in the CFG
+ else cfg get state1 match {
+ case Some(nextStates) =>
+ seen += state1
+ nextStates.contains(state2) || nextStates.exists(isPred0(_, state2))
+ case None =>
+ false
+ }
+
+ isPred0(state1, state2)
+ }
val finalState = asyncStates.find(as => !asyncStates.exists(other => isPred(as.state, other.state))).get
@@ -162,12 +170,10 @@ trait LiveVariables {
LVexit = LVexit + (finalState.state -> noNull)
var currStates = List(finalState) // start at final state
- var pred = List[AsyncState]() // current predecessor states
- var hasChanged = true // if something has changed we need to continue iterating
var captured: Set[Symbol] = Set()
- while (hasChanged) {
- hasChanged = false
+ while (!currStates.isEmpty) {
+ var entryChanged: List[AsyncState] = Nil
for (cs <- currStates) {
val LVentryOld = LVentry(cs.state)
@@ -176,22 +182,23 @@ trait LiveVariables {
val LVentryNew = LVexit(cs.state) ++ referenced.used
if (!LVentryNew.sameElements(LVentryOld)) {
LVentry = LVentry + (cs.state -> LVentryNew)
- hasChanged = true
+ entryChanged ::= cs
}
}
- pred = currStates.flatMap(cs => asyncStates.filter(_.nextStates.contains(cs.state)))
+ val pred = entryChanged.flatMap(cs => asyncStates.filter(_.nextStates.contains(cs.state)))
+ var exitChanged: List[AsyncState] = Nil
for (p <- pred) {
val LVexitOld = LVexit(p.state)
val LVexitNew = p.nextStates.flatMap(succ => LVentry(succ)).toSet
if (!LVexitNew.sameElements(LVexitOld)) {
LVexit = LVexit + (p.state -> LVexitNew)
- hasChanged = true
+ exitChanged ::= p
}
}
- currStates = pred
+ currStates = exitChanged
}
for (as <- asyncStates) {
@@ -199,21 +206,29 @@ trait LiveVariables {
AsyncUtils.vprintln(s"LVexit at state #${as.state}: ${LVexit(as.state).mkString(", ")}")
}
- def lastUsagesOf(field: Tree, at: AsyncState, avoid: Set[AsyncState]): Set[Int] =
- if (avoid(at)) Set()
- else if (captured(field.symbol)) {
- Set()
- }
- else LVentry get at.state match {
- case Some(fields) if fields.exists(_ == field.symbol) =>
- Set(at.state)
- case _ =>
- val preds = asyncStates.filter(_.nextStates.contains(at.state)).toSet
- preds.flatMap(p => lastUsagesOf(field, p, avoid + at))
+ def lastUsagesOf(field: Tree, at: AsyncState): Set[Int] = {
+ val avoid = scala.collection.mutable.HashSet[AsyncState]()
+
+ def lastUsagesOf0(field: Tree, at: AsyncState): Set[Int] = {
+ if (avoid(at)) Set()
+ else if (captured(field.symbol)) {
+ Set()
+ }
+ else LVentry get at.state match {
+ case Some(fields) if fields.exists(_ == field.symbol) =>
+ Set(at.state)
+ case _ =>
+ avoid += at
+ val preds = asyncStates.filter(_.nextStates.contains(at.state)).toSet
+ preds.flatMap(p => lastUsagesOf0(field, p))
+ }
}
+ lastUsagesOf0(field, at)
+ }
+
val lastUsages: Map[Tree, Set[Int]] =
- liftables.map(fld => (fld -> lastUsagesOf(fld, finalState, Set()))).toMap
+ liftables.map(fld => (fld -> lastUsagesOf(fld, finalState))).toMap
for ((fld, lastStates) <- lastUsages)
AsyncUtils.vprintln(s"field ${fld.symbol.name} is last used in states ${lastStates.mkString(", ")}")
diff --git a/src/main/scala/scala/async/internal/TransformUtils.scala b/src/main/scala/scala/async/internal/TransformUtils.scala
index a01a801..665dead 100644
--- a/src/main/scala/scala/async/internal/TransformUtils.scala
+++ b/src/main/scala/scala/async/internal/TransformUtils.scala
@@ -164,11 +164,17 @@ private[async] trait TransformUtils {
case ld: LabelDef => ld.symbol
}.toSet
t.exists {
- case rt: RefTree => !(labelDefs contains rt.symbol)
+ case rt: RefTree => rt.symbol != null && isLabel(rt.symbol) && !(labelDefs contains rt.symbol)
case _ => false
}
}
+ private def isLabel(sym: Symbol): Boolean = {
+ val LABEL = 1L << 17 // not in the public reflection API.
+ (internal.flags(sym).asInstanceOf[Long] & LABEL) != 0L
+ }
+
+
/** Map a list of arguments to:
* - A list of argument Trees
* - A list of auxillary results.