diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2010-08-23 08:52:31 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2010-08-23 08:52:31 +0000 |
commit | 6892195b1f94b64e9749f52e2af4bf4c663e8dde (patch) | |
tree | 4b01e3826788f09889a7c4ada9c1420a943a4ed0 | |
parent | d4e44a65651a1a45a5aae10af601cffbc27bd5f0 (diff) | |
download | scala-6892195b1f94b64e9749f52e2af4bf4c663e8dde.tar.gz scala-6892195b1f94b64e9749f52e2af4bf4c663e8dde.tar.bz2 scala-6892195b1f94b64e9749f52e2af4bf4c663e8dde.zip |
Various fixes to optimizations, and mainly much...
Various fixes to optimizations, and mainly much better heuristics for
inlining. Now even the compiler is some 3% faster! Yeah!
5 files changed, 29 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 8e3fe907a8..228ece4ea8 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -149,7 +149,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable def informTime(msg: String, start: Long) = informProgress(msg + " in " + (currentTime - start) + "ms") - def log(msg: AnyRef) { + /*@inline final*/ def log(msg: => AnyRef) { if (settings.log contains phase.name) inform("[log " + phase + "] " + msg) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index a5e2e978a3..91e1b4eb8a 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -338,10 +338,10 @@ trait BasicBlocks { * is closed, which sets the DIRTYSUCCS flag. */ def emit(instr: Instruction, pos: Position) { - if (closed) { +/* if (closed) { print() Console.println("trying to emit: " + instr) - } + } */ assert(!closed || ignore, "BasicBlock closed") if (!ignore) { diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala index 0897b94a15..bbb84430c4 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala @@ -179,9 +179,9 @@ abstract class ClosureElimination extends SubComponent { () } case Boxed(LocalVar(loc1)) :: _ => - val value = info.getBinding(loc1) - bb.replaceInstruction(i, DROP(icodes.AnyRefReference) :: valueToInstruction(value) :: Nil) - log("replaced " + i + " with " + value) + val loc2 = info.getAlias(loc1) + bb.replaceInstruction(i, DROP(icodes.AnyRefReference) :: valueToInstruction(Deref(LocalVar(loc2))) :: Nil) + log("replaced " + i + " with " + LocalVar(loc2)) case _ => () } diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 155bc17491..c0146bcd0c 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -118,6 +118,8 @@ abstract class Inliners extends SubComponent { } def analyzeMethod(m: IMethod): Unit = { + var sizeBeforeInlining = if (m.code ne null) m.code.blocks.length else 0 + var instrBeforeInlining = if (m.code ne null) m.code.blocks.foldLeft(0)(_ + _.length) else 0 var retry = false var count = 0 fresh.clear @@ -170,6 +172,8 @@ abstract class Inliners extends SubComponent { count += 1 pair.doInline(bb, i) + if (!inc.inline || inc.isMonadic) + caller.inlinedCalls += 1 inlinedMethodCount(inc.sym) += 1 /* Remove this method from the cache, as the calls-private relation @@ -229,6 +233,12 @@ abstract class Inliners extends SubComponent { while (retry && count < MAX_INLINE_RETRY) m.normalize + if (sizeBeforeInlining > 0) { + val instrAfterInlining = m.code.blocks.foldLeft(0)(_ + _.length) + val prefix = if ((instrAfterInlining > 2 * instrBeforeInlining) && (instrAfterInlining > 200)) " !! " else "" + log(prefix + " %s blocks before inlining: %d (%d) after: %d (%d)".format( + m.symbol.fullName, sizeBeforeInlining, instrBeforeInlining, m.code.blocks.length, instrAfterInlining)) + } } private def isMonadicMethod(sym: Symbol) = sym.name match { @@ -297,13 +307,16 @@ abstract class Inliners extends SubComponent { def instructions = blocks.flatten def linearized = linearizer linearize m - def isSmall = length <= SMALL_METHOD_SIZE + def isSmall = (length <= SMALL_METHOD_SIZE) && blocks(0).length < 10 def isLarge = length > MAX_INLINE_SIZE def isRecursive = m.recursive def hasCode = m.code != null def hasSourceFile = m.sourceFile != null def hasHandlers = handlers.nonEmpty + // the number of inlined calls in 'm', used by 'shouldInline' + var inlinedCalls = 0 + def addLocals(ls: List[Local]) = m.locals ++= ls def addLocal(l: Local) = addLocals(List(l)) def addHandlers(exhs: List[ExceptionHandler]) = m.exh = exhs ::: m.exh @@ -622,6 +635,12 @@ abstract class Inliners extends SubComponent { log("shouldInline: " + caller.m + " with " + inc.m) var score = 0 + + // better not inline inside closures, but hope that the closure itself + // is repeatedly inlined + if (caller.isInClosure) score -= 2 + else if (caller.inlinedCalls < 1) score -= 1 // only monadic methods can trigger the first inline + if (inc.isSmall) score += 1 if (caller.isSmall && isLargeSum) { @@ -633,7 +652,7 @@ abstract class Inliners extends SubComponent { score -= 1 if (inc.isMonadic) - score += 2 + score += 3 else if (inc.isHigherOrder) score += 1 if (inc.isInClosure) @@ -641,8 +660,7 @@ abstract class Inliners extends SubComponent { if (inc.numInlined > 2) score -= 2 - if (settings.debug.value) - log("shouldInline(" + inc.m + ") score: " + score) + log("shouldInline(" + inc.m + ") score: " + score) score > 0 }) diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala index 0fdbeae98f..04bc0564b8 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala @@ -29,7 +29,7 @@ abstract class SymbolTable extends reflect.generic.Universe { def settings: Settings def rootLoader: LazyType - def log(msg: AnyRef) + def log(msg: => AnyRef) def abort(msg: String) = throw new Error(msg) def abort() = throw new Error() |