From b6c2609e2eed661ac8f0e19d62135253a3a28b0a Mon Sep 17 00:00:00 2001 From: Rory Graves Date: Wed, 21 Jun 2017 21:43:27 +0100 Subject: Reduce logging overhead and minor cleanups --- .../scala/scala/async/internal/AnfTransform.scala | 6 ++-- .../scala/scala/async/internal/AsyncAnalysis.scala | 4 +-- .../scala/scala/async/internal/AsyncBase.scala | 2 +- src/main/scala/scala/async/internal/AsyncId.scala | 4 +-- .../scala/scala/async/internal/AsyncMacro.scala | 4 +-- .../scala/async/internal/AsyncTransform.scala | 5 +-- .../scala/scala/async/internal/AsyncUtils.scala | 9 ++--- .../scala/scala/async/internal/ExprBuilder.scala | 9 ++--- .../scala/scala/async/internal/LiveVariables.scala | 40 +++++++++++++--------- src/test/scala/scala/async/TreeInterrogation.scala | 4 +-- .../scala/async/run/SyncOptimizationSpec.scala | 2 +- .../scala/async/run/anf/AnfTransformSpec.scala | 6 ++-- .../scala/scala/async/run/ifelse4/IfElse4.scala | 2 +- src/test/scala/scala/async/run/match0/Match0.scala | 2 +- 14 files changed, 53 insertions(+), 46 deletions(-) diff --git a/src/main/scala/scala/async/internal/AnfTransform.scala b/src/main/scala/scala/async/internal/AnfTransform.scala index 3d14fb7..32c993a 100644 --- a/src/main/scala/scala/async/internal/AnfTransform.scala +++ b/src/main/scala/scala/async/internal/AnfTransform.scala @@ -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 diff --git a/src/main/scala/scala/async/internal/AsyncAnalysis.scala b/src/main/scala/scala/async/internal/AsyncAnalysis.scala index bd64f17..1470592 100644 --- a/src/main/scala/scala/async/internal/AsyncAnalysis.scala +++ b/src/main/scala/scala/async/internal/AsyncAnalysis.scala @@ -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 => @@ -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) { diff --git a/src/main/scala/scala/async/internal/AsyncBase.scala b/src/main/scala/scala/async/internal/AsyncBase.scala index ec9dc25..c883986 100644 --- a/src/main/scala/scala/async/internal/AsyncBase.scala +++ b/src/main/scala/scala/async/internal/AsyncBase.scala @@ -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) diff --git a/src/main/scala/scala/async/internal/AsyncId.scala b/src/main/scala/scala/async/internal/AsyncId.scala index 8654474..86d9748 100644 --- a/src/main/scala/scala/async/internal/AsyncId.scala +++ b/src/main/scala/scala/async/internal/AsyncId.scala @@ -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) diff --git a/src/main/scala/scala/async/internal/AsyncMacro.scala b/src/main/scala/scala/async/internal/AsyncMacro.scala index 57c73fc..113e7a8 100644 --- a/src/main/scala/scala/async/internal/AsyncMacro.scala +++ b/src/main/scala/scala/async/internal/AsyncMacro.scala @@ -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) } diff --git a/src/main/scala/scala/async/internal/AsyncTransform.scala b/src/main/scala/scala/async/internal/AsyncTransform.scala index feb1ea7..58f7f64 100644 --- a/src/main/scala/scala/async/internal/AsyncTransform.scala +++ b/src/main/scala/scala/async/internal/AsyncTransform.scala @@ -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) diff --git a/src/main/scala/scala/async/internal/AsyncUtils.scala b/src/main/scala/scala/async/internal/AsyncUtils.scala index 1d15c4c..385cde4 100644 --- a/src/main/scala/scala/async/internal/AsyncUtils.scala +++ b/src/main/scala/scala/async/internal/AsyncUtils.scala @@ -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") } diff --git a/src/main/scala/scala/async/internal/ExprBuilder.scala b/src/main/scala/scala/async/internal/ExprBuilder.scala index fe62cd6..002e5cc 100644 --- a/src/main/scala/scala/async/internal/ExprBuilder.scala +++ b/src/main/scala/scala/async/internal/ExprBuilder.scala @@ -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 => @@ -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 } } @@ -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)) } diff --git a/src/main/scala/scala/async/internal/LiveVariables.scala b/src/main/scala/scala/async/internal/LiveVariables.scala index db15015..8ae00f5 100644 --- a/src/main/scala/scala/async/internal/LiveVariables.scala +++ b/src/main/scala/scala/async/internal/LiveVariables.scala @@ -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 { @@ -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`. */ @@ -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. @@ -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] = { @@ -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 @@ -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 { @@ -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 } diff --git a/src/test/scala/scala/async/TreeInterrogation.scala b/src/test/scala/scala/async/TreeInterrogation.scala index 1637102..d2e8513 100644 --- a/src/test/scala/scala/async/TreeInterrogation.scala +++ b/src/test/scala/scala/async/TreeInterrogation.scala @@ -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 { @@ -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$", "", "apply", "apply")) + defDefs.map(_.decoded.trim) mustStartWith List("foo$macro$", "", "apply", "apply") } } diff --git a/src/test/scala/scala/async/run/SyncOptimizationSpec.scala b/src/test/scala/scala/async/run/SyncOptimizationSpec.scala index dd649f4..0d08279 100644 --- a/src/test/scala/scala/async/run/SyncOptimizationSpec.scala +++ b/src/test/scala/scala/async/run/SyncOptimizationSpec.scala @@ -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 diff --git a/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala b/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala index 13cc351..29b7c1d 100644 --- a/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala +++ b/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala @@ -217,7 +217,7 @@ class AnfTransformSpec { val result = async { var i = 0 def next() = { - i += 1; + i += 1 i } foo(next(), await(next())) @@ -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())) @@ -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) diff --git a/src/test/scala/scala/async/run/ifelse4/IfElse4.scala b/src/test/scala/scala/async/run/ifelse4/IfElse4.scala index b0ecf13..7c65421 100644 --- a/src/test/scala/scala/async/run/ifelse4/IfElse4.scala +++ b/src/test/scala/scala/async/run/ifelse4/IfElse4.scala @@ -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") } diff --git a/src/test/scala/scala/async/run/match0/Match0.scala b/src/test/scala/scala/async/run/match0/Match0.scala index 8eead71..c5138ad 100644 --- a/src/test/scala/scala/async/run/match0/Match0.scala +++ b/src/test/scala/scala/async/run/match0/Match0.scala @@ -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) } -- cgit v1.2.3