diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-11-02 21:58:04 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-01-31 22:13:46 +0100 |
commit | c30cf0ee814337109941876b08323a42b440a724 (patch) | |
tree | 2b24c06643a4461bbe5769d5d42b1e5f043fbe5b | |
parent | 67f7df27a8f4f97929140904eec237541d2b65ab (diff) | |
download | scala-c30cf0ee814337109941876b08323a42b440a724.tar.gz scala-c30cf0ee814337109941876b08323a42b440a724.tar.bz2 scala-c30cf0ee814337109941876b08323a42b440a724.zip |
Optimization in TailCalls
Only store the position and reason for a failure to tailcall
transform a method if we ever need to report it, ie, if the
method was annotated with @tailrec.
Saves object hashing and map updates, profiling suggests
that this reduces the tailcalls phase from about 2% of compilation
time to about 1%.
Also, clear the maps eagerly after each compilation unit,
rather than letting them accumulate entries for the entire
run. Working with smaller maps can't hurt.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/TailCalls.scala | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 05fa65eb9c..5973c70583 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -128,6 +128,7 @@ abstract class TailCalls extends Transform { logResult(msg)(method.newValue(nme.THIS, pos, SYNTHETIC) setInfo currentClass.typeOfThis) } override def toString = s"${method.name} tparams=$tparams tailPos=$tailPos label=$label label info=${label.info}" + } object EmptyTailContext extends TailContext { @@ -185,6 +186,18 @@ abstract class TailCalls extends Transform { private def noTailContext() = new ClonedTailContext(ctx, tailPos = false) private def yesTailContext() = new ClonedTailContext(ctx, tailPos = true) + + override def transformUnit(unit: CompilationUnit): Unit = { + try { + super.transformUnit(unit) + } finally { + // OPT clear these after each compilation unit + failPositions.clear() + failReasons.clear() + accessed.clear() + } + } + /** Rewrite this tree to contain no tail recursive calls */ def transform(tree: Tree, nctx: TailContext): Tree = { val saved = ctx @@ -218,12 +231,12 @@ abstract class TailCalls extends Transform { */ def fail(reason: String) = { debuglog("Cannot rewrite recursive call at: " + fun.pos + " because: " + reason) - failReasons(ctx) = reason + if (ctx.isMandatory) failReasons(ctx) = reason treeCopy.Apply(tree, noTailTransform(target), transformArgs) } /* Position of failure is that of the tree being considered. */ def failHere(reason: String) = { - failPositions(ctx) = fun.pos + if (ctx.isMandatory) failPositions(ctx) = fun.pos fail(reason) } def rewriteTailCall(recv: Tree): Tree = { |