Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce logging overhead and minor cleanups #172

Merged
merged 1 commit into from
Jun 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/main/scala/scala/async/internal/AnfTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ private[async] trait AnfTransform {
indent += 1
def oneLine(s: Any) = s.toString.replaceAll("""\n""", "\\\\n").take(127)
try {
AsyncUtils.trace(s"${indentString}$prefix(${oneLine(args)})")
if(AsyncUtils.trace)
AsyncUtils.trace(s"$indentString$prefix(${oneLine(args)})")
val result = t
AsyncUtils.trace(s"${indentString}= ${oneLine(result)}")
if(AsyncUtils.trace)
AsyncUtils.trace(s"$indentString= ${oneLine(result)}")
result
} finally {
indent -= 1
Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/scala/async/internal/AsyncAnalysis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
package scala.async.internal

import scala.collection.mutable.ListBuffer
import scala.reflect.macros.Context
import scala.collection.mutable

trait AsyncAnalysis {
self: AsyncMacro =>
Expand All @@ -30,7 +28,7 @@ trait AsyncAnalysis {

override def nestedClass(classDef: ClassDef) {
val kind = if (classDef.symbol.asClass.isTrait) "trait" else "class"
reportUnsupportedAwait(classDef, s"nested ${kind}")
reportUnsupportedAwait(classDef, s"nested $kind")
}

override def nestedModule(module: ModuleDef) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/scala/async/internal/AsyncBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ abstract class AsyncBase {
val asyncMacro = AsyncMacro(c, self)(body.tree)

val code = asyncMacro.asyncTransform[T](execContext.tree)(c.weakTypeTag[T])
AsyncUtils.vprintln(s"async state machine transform expands to:\n ${code}")
AsyncUtils.vprintln(s"async state machine transform expands to:\n $code")

// Mark range positions for synthetic code as transparent to allow some wiggle room for overlapping ranges
for (t <- code) t.setPos(t.pos.makeTransparent)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/scala/async/internal/AsyncId.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ object AsyncTestLV extends AsyncBase {

def asyncIdImpl[T: c.WeakTypeTag](c: Context)(body: c.Expr[T]): c.Expr[T] = asyncImpl[T](c)(body)(c.literalUnit)

var log: List[(String, Any)] = List()
var log: List[(String, Any)] = Nil
def assertNulledOut(a: Any): Unit = assert(log.exists(_._2 == a), AsyncTestLV.log)
def assertNotNulledOut(a: Any): Unit = assert(!log.exists(_._2 == a), AsyncTestLV.log)
def clear() = log = Nil
def clear(): Unit = log = Nil

def apply(name: String, v: Any): Unit =
log ::= (name -> v)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/scala/async/internal/AsyncMacro.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private[async] trait AsyncMacro
val body: c.Tree
var containsAwait: c.Tree => Boolean

lazy val macroPos = c.macroApplication.pos.makeTransparent
def atMacroPos(t: c.Tree) = c.universe.atPos(macroPos)(t)
lazy val macroPos: c.universe.Position = c.macroApplication.pos.makeTransparent
def atMacroPos(t: c.Tree): c.Tree = c.universe.atPos(macroPos)(t)

}
5 changes: 3 additions & 2 deletions src/main/scala/scala/async/internal/AsyncTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ trait AsyncTransform {

val stateMachineClass = stateMachine.symbol
val asyncBlock: AsyncBlock = {
val symLookup = new SymLookup(stateMachineClass, applyDefDefDummyBody.vparamss.head.head.symbol)
val symLookup = SymLookup(stateMachineClass, applyDefDefDummyBody.vparamss.head.head.symbol)
buildAsyncBlock(anfTree, symLookup)
}

logDiagnostics(anfTree, asyncBlock.asyncStates.map(_.toString))
if(AsyncUtils.verbose)
logDiagnostics(anfTree, asyncBlock.asyncStates.map(_.toString))

val liftedFields: List[Tree] = liftables(asyncBlock.asyncStates)

Expand Down
9 changes: 5 additions & 4 deletions src/main/scala/scala/async/internal/AsyncUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ package scala.async.internal

object AsyncUtils {


private def enabled(level: String) = sys.props.getOrElse(s"scala.async.$level", "false").equalsIgnoreCase("true")

private def verbose = enabled("debug")
private def trace = enabled("trace")
private[async] val verbose = enabled("debug")
private[async] val trace = enabled("trace")

private[async] def vprintln(s: => Any): Unit = if (verbose) println(s"[async] $s")
@inline private[async] def vprintln(s: => Any): Unit = if (verbose) println(s"[async] $s")

private[async] def trace(s: => Any): Unit = if (trace) println(s"[async] $s")
@inline private[async] def trace(s: => Any): Unit = if (trace) println(s"[async] $s")
}
9 changes: 3 additions & 6 deletions src/main/scala/scala/async/internal/ExprBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
package scala.async.internal

import scala.collection.mutable.ListBuffer
import collection.mutable
import language.existentials
import scala.reflect.api.Universe
import scala.reflect.api

trait ExprBuilder {
builder: AsyncMacro =>
Expand Down Expand Up @@ -370,11 +367,11 @@ trait ExprBuilder {
c.Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), lastStateBody)
mkHandlerCase(lastState.state, Block(rhs.tree, Return(literalUnit)))
}
asyncStates.toList match {
asyncStates match {
case s :: Nil =>
List(caseForLastState)
case _ =>
val initCases = for (state <- asyncStates.toList.init) yield state.mkHandlerCaseForState[T]
val initCases = for (state <- asyncStates.init) yield state.mkHandlerCaseForState[T]
initCases :+ caseForLastState
}
}
Expand Down Expand Up @@ -442,7 +439,7 @@ trait ExprBuilder {
* }
*/
def onCompleteHandler[T: WeakTypeTag]: Tree = {
val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T]).toList
val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T])
forever {
adaptToUnit(toList(resumeFunTree))
}
Expand Down
40 changes: 24 additions & 16 deletions src/main/scala/scala/async/internal/LiveVariables.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ trait LiveVariables {
AsyncUtils.vprintln(s"fields never zero-ed out: ${noNull.mkString(", ")}")

/**
* Traverse statements of an `AsyncState`, collect `Ident`-s refering to lifted fields.
* Traverse statements of an `AsyncState`, collect `Ident`-s referring to lifted fields.
*
* @param as a state of an `async` expression
* @return a set of lifted fields that are used within state `as`
*/
def fieldsUsedIn(as: AsyncState): ReferencedFields = {
class FindUseTraverser extends AsyncTraverser {
var usedFields = Set[Symbol]()
var capturedFields = Set[Symbol]()
var usedFields: Set[Symbol] = Set[Symbol]()
var capturedFields: Set[Symbol] = Set[Symbol]()
private def capturing[A](body: => A): A = {
val saved = capturing
try {
Expand Down Expand Up @@ -122,7 +122,7 @@ trait LiveVariables {
* A state `i` is contained in the list that is the value to which
* key `j` maps iff control can flow from state `j` to state `i`.
*/
val cfg: Map[Int, List[Int]] = asyncStates.map(as => (as.state -> as.nextStates)).toMap
val cfg: Map[Int, List[Int]] = asyncStates.map(as => as.state -> as.nextStates).toMap

/** Tests if `state1` is a predecessor of `state2`.
*/
Expand All @@ -145,8 +145,10 @@ trait LiveVariables {

val finalState = asyncStates.find(as => !asyncStates.exists(other => isPred(as.state, other.state))).get

for (as <- asyncStates)
AsyncUtils.vprintln(s"fields used in state #${as.state}: ${fieldsUsedIn(as)}")
if(AsyncUtils.verbose) {
for (as <- asyncStates)
AsyncUtils.vprintln(s"fields used in state #${as.state}: ${fieldsUsedIn(as)}")
}

/* Backwards data-flow analysis. Computes live variables information at entry and exit
* of each async state.
Expand Down Expand Up @@ -201,9 +203,11 @@ trait LiveVariables {
currStates = exitChanged
}

for (as <- asyncStates) {
AsyncUtils.vprintln(s"LVentry at state #${as.state}: ${LVentry(as.state).mkString(", ")}")
AsyncUtils.vprintln(s"LVexit at state #${as.state}: ${LVexit(as.state).mkString(", ")}")
if(AsyncUtils.verbose) {
for (as <- asyncStates) {
AsyncUtils.vprintln(s"LVentry at state #${as.state}: ${LVentry(as.state).mkString(", ")}")
AsyncUtils.vprintln(s"LVexit at state #${as.state}: ${LVexit(as.state).mkString(", ")}")
}
}

def lastUsagesOf(field: Tree, at: AsyncState): Set[Int] = {
Expand All @@ -215,7 +219,7 @@ trait LiveVariables {
Set()
}
else LVentry get at.state match {
case Some(fields) if fields.exists(_ == field.symbol) =>
case Some(fields) if fields.contains(field.symbol) =>
Set(at.state)
case _ =>
avoid += at
Expand All @@ -228,10 +232,12 @@ trait LiveVariables {
}

val lastUsages: Map[Tree, Set[Int]] =
liftables.map(fld => (fld -> lastUsagesOf(fld, finalState))).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(", ")}")
if(AsyncUtils.verbose) {
for ((fld, lastStates) <- lastUsages)
AsyncUtils.vprintln(s"field ${fld.symbol.name} is last used in states ${lastStates.mkString(", ")}")
}

val nullOutAt: Map[Tree, Set[Int]] =
for ((fld, lastStates) <- lastUsages) yield {
Expand All @@ -242,14 +248,16 @@ trait LiveVariables {
val succNums = lastAsyncState.nextStates
// all successor states that are not indirect predecessors
// filter out successor states where the field is live at the entry
succNums.filter(num => !isPred(num, s)).filterNot(num => LVentry(num).exists(_ == fld.symbol))
succNums.filter(num => !isPred(num, s)).filterNot(num => LVentry(num).contains(fld.symbol))
}
}
(fld, killAt)
}

for ((fld, killAt) <- nullOutAt)
AsyncUtils.vprintln(s"field ${fld.symbol.name} should be nulled out in states ${killAt.mkString(", ")}")
if(AsyncUtils.verbose) {
for ((fld, killAt) <- nullOutAt)
AsyncUtils.vprintln(s"field ${fld.symbol.name} should be nulled out in states ${killAt.mkString(", ")}")
}

nullOutAt
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/scala/async/TreeInterrogation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TreeInterrogation {
@Test
def `a minimal set of vals are lifted to vars`() {
val cm = reflect.runtime.currentMirror
val tb = mkToolbox(s"-cp ${toolboxClasspath}")
val tb = mkToolbox(s"-cp $toolboxClasspath")
val tree = tb.parse(
"""| import _root_.scala.async.internal.AsyncId._
| async {
Expand Down Expand Up @@ -49,7 +49,7 @@ class TreeInterrogation {
&& !dd.symbol.asTerm.isAccessor && !dd.symbol.asTerm.isSetter => dd.name
}
}.flatten
defDefs.map(_.decoded.trim).toList mustStartWith (List("foo$macro$", "<init>", "apply", "apply"))
defDefs.map(_.decoded.trim) mustStartWith List("foo$macro$", "<init>", "apply", "apply")
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/scala/async/run/SyncOptimizationSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SyncOptimizationSpec {
@Test
def awaitOnCompletedFutureRunsOnSameThread: Unit = {

def stackDepth = Thread.currentThread().getStackTrace.size
def stackDepth = Thread.currentThread().getStackTrace.length

val future = async {
val thread1 = Thread.currentThread
Expand Down
6 changes: 3 additions & 3 deletions src/test/scala/scala/async/run/anf/AnfTransformSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ class AnfTransformSpec {
val result = async {
var i = 0
def next() = {
i += 1;
i += 1
i
}
foo(next(), await(next()))
Expand Down Expand Up @@ -298,7 +298,7 @@ class AnfTransformSpec {
val result = async {
var i = 0
def next() = {
i += 1;
i += 1
i
}
foo(b = next(), a = await(next()))
Expand All @@ -311,7 +311,7 @@ class AnfTransformSpec {
import AsyncId.{async, await}
var i = 0
def next() = {
i += 1;
i += 1
i
}
def foo(a: Int = next(), b: Int = next()) = (a, b)
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/scala/async/run/ifelse4/IfElse4.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class IfElse4Spec {
@Test
def `await result with complex type containing skolem`() {
val o = new TestIfElse4Class
val fut = o.run(new o.K(null))
val fut = o.run(o.K(null))
val res = Await.result(fut, 2 seconds)
res.id mustBe ("foo")
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/scala/async/run/match0/Match0.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class MatchSpec {
val x = 1
Option(x) match {
case op @ Some(x) =>
assert(op == Some(1))
assert(op.contains(1))
x + AsyncId.await(x)
case None => AsyncId.await(0)
}
Expand Down