summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/TailCalls.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-10-08 08:53:52 +1000
committerJason Zaugg <jzaugg@gmail.com>2014-10-10 15:23:38 +1000
commit96f47647381425be5c8c0e771590d6abe0f4d231 (patch)
treee6e0af0d4c5593b6690a0f1df653f35d69fae693 /src/compiler/scala/tools/nsc/transform/TailCalls.scala
parent22233f40f641815fe7b9304bb386ee27c8422603 (diff)
downloadscala-96f47647381425be5c8c0e771590d6abe0f4d231.tar.gz
scala-96f47647381425be5c8c0e771590d6abe0f4d231.tar.bz2
scala-96f47647381425be5c8c0e771590d6abe0f4d231.zip
Optimize tail calls to avoid findMember calls
Cache the member symbols for `Boolean.{||, &&}` per-run, rather than look them up repeatedly. Based on profiling the tail calls phase in the program below, which was distilled by @rmacleod2 from the code generated by macros in https://github.com/paytronix/utils-open/tree/release/2014/ernststavrosgrouper Wall clock time went from 12s to 6.5s. ```scala object Test { def a(): Option[String] = Some("a") def main(args: Array[String]) { a() match { case Some(b1) => a() match { case Some(b2) => a() match { case Some(b3) => a() match { case Some(b4) => a() match { case Some(b5) => a() match { case Some(b6) => a() match { case Some(b7) => a() match { case Some(b8) => a() match { case Some(b9) => a() match { case Some(b10) => a() match { case Some(b11) => a() match { case Some(b12) => a() match { case Some(b13) => a() match { case Some(b14) => a() match { case Some(b15) => a() match { case Some(b16) => a() match { case Some(b17) => a() match { case Some(b18) => a() match { case Some(b19) => a() match { case Some(b20) => println("yay") case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } case None => None } } } ```
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/TailCalls.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index ef534f70fd..93a343675b 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -265,6 +265,10 @@ abstract class TailCalls extends Transform {
!(sym.hasAccessorFlag || sym.isConstructor)
}
+ // intentionally shadowing imports from definitions for performance
+ val runDefinitions = currentRun.runDefinitions
+ import runDefinitions.{Boolean_or, Boolean_and}
+
tree match {
case ValDef(_, _, _, _) =>
if (tree.symbol.isLazy && tree.symbol.hasAnnotation(TailrecClass))
@@ -421,6 +425,10 @@ abstract class TailCalls extends Transform {
def traverseNoTail(tree: Tree) = traverse(tree, maybeTailNew = false)
def traverseTreesNoTail(trees: List[Tree]) = trees foreach traverseNoTail
+ // intentionally shadowing imports from definitions for performance
+ private val runDefinitions = currentRun.runDefinitions
+ import runDefinitions.{Boolean_or, Boolean_and}
+
override def traverse(tree: Tree) = tree match {
// we're looking for label(x){x} in tail position, since that means `a` is in tail position in a call `label(a)`
case LabelDef(_, List(arg), body@Ident(_)) if arg.symbol == body.symbol =>