diff options
author | Paul Phillips <paulp@improving.org> | 2011-12-20 14:45:11 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-01-03 10:57:06 -0800 |
commit | 45a26ce3102f54e4f72165aef42fab7f73681c1d (patch) | |
tree | d13f32bce0859bb162d96b844fbdc10a368d1df6 /src/compiler/scala/tools/nsc/backend/opt/Inliners.scala | |
parent | 471a63a9e6618f25feb3a5266c38ad98ea2a5ac7 (diff) | |
download | scala-45a26ce3102f54e4f72165aef42fab7f73681c1d.tar.gz scala-45a26ce3102f54e4f72165aef42fab7f73681c1d.tar.bz2 scala-45a26ce3102f54e4f72165aef42fab7f73681c1d.zip |
Optimization/robustness in the backend.
Trying to help icode/jvm get through their business a bit faster, and
also make things more robust. Less null, more distinguished objects.
More encapsulation, fewer public vars. Helping updateSuccessorList()
to avoid assembling a list of successors on every call only to find
most of the time that it's the same list it already had (e.g. compiling
quick.lib it says "59076 calls, 690 requiring allocation" rather than
59076 calls, 59076 requiring allocation.)
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/opt/Inliners.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/opt/Inliners.scala | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index d56a0740d9..e01c42ad87 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -9,6 +9,7 @@ package backend.opt import scala.collection.mutable import scala.tools.nsc.symtab._ +import scala.tools.nsc.util.{ NoSourceFile } /** * @author Iulian Dragos @@ -111,8 +112,8 @@ abstract class Inliners extends SubComponent { private val inlinedMethodCount = perRunCaches.newMap[Symbol, Int]() withDefaultValue 0 def analyzeMethod(m: IMethod): Unit = { - var sizeBeforeInlining = if (m.code ne null) m.code.blockCount else 0 - var instrBeforeInlining = if (m.code ne null) m.code.instructionCount else 0 + var sizeBeforeInlining = if (m.hasCode) m.code.blockCount else 0 + var instrBeforeInlining = if (m.hasCode) m.code.instructionCount else 0 var retry = false var count = 0 fresh.clear() @@ -210,11 +211,11 @@ abstract class Inliners extends SubComponent { if (caller.inline) { log("Not inlining into " + caller.sym.originalName.decode + " because it is marked @inline.") } - else if (caller.hasCode) { + else if (caller.m.hasCode) { log("Analyzing " + m + " count " + count + " with " + caller.length + " blocks") tfa init m tfa.run - caller.linearized foreach { bb => + caller.m.linearizedBlocks() foreach { bb => info = tfa in bb breakable { @@ -311,18 +312,16 @@ abstract class Inliners extends SubComponent { def isMonadic = isMonadicMethod(sym) def handlers = m.exh - def blocks = if (m.code eq null) sys.error("blocks = null + " + m) else m.code.blocks + def blocks = m.blocks def locals = m.locals def length = blocks.length def openBlocks = blocks filterNot (_.closed) - def instructions = blocks.flatten + def instructions = m.code.instructions def linearized = linearizer linearize m 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 def hasNonFinalizerHandler = handlers exists { case _: Finalizer => true @@ -457,7 +456,7 @@ abstract class Inliners extends SubComponent { if (retVal ne null) caller addLocal retVal - inc.blocks foreach { b => + inc.m foreachBlock { b => inlinedBlock += (b -> newBlock()) inlinedBlock(b).varsInScope ++= (b.varsInScope map inlinedLocals) } @@ -475,11 +474,11 @@ abstract class Inliners extends SubComponent { blockEmit(STORE_LOCAL(inlinedThis)) // jump to the start block of the callee - blockEmit(JUMP(inlinedBlock(inc.m.code.startBlock))) + blockEmit(JUMP(inlinedBlock(inc.m.startBlock))) block.close // duplicate the other blocks in the callee - linearizer linearize inc.m foreach { bb => + inc.m.linearizedBlocks() foreach { bb => var info = a in bb def emitInlined(i: Instruction) = inlinedBlock(bb).emit(i, targetPos) def emitDrops(toDrop: Int) = info.stack.types drop toDrop foreach (t => emitInlined(DROP(t))) @@ -511,23 +510,23 @@ abstract class Inliners extends SubComponent { } def isStampedForInlining(stack: TypeStack) = - !sameSymbols && inc.hasCode && shouldInline && isSafeToInline(stack) + !sameSymbols && inc.m.hasCode && shouldInline && isSafeToInline(stack) def logFailure(stack: TypeStack) = log( """|inline failed for %s: | pair.sameSymbols: %s | inc.numInlined < 2: %s - | inc.hasCode: %s + | inc.m.hasCode: %s | isSafeToInline: %s | shouldInline: %s """.stripMargin.format( inc.m, sameSymbols, inc.numInlined < 2, - inc.hasCode, isSafeToInline(stack), shouldInline + inc.m.hasCode, isSafeToInline(stack), shouldInline ) ) def failureReason(stack: TypeStack) = - if (!inc.hasCode) "bytecode was unavailable" + if (!inc.m.hasCode) "bytecode was unavailable" else if (!isSafeToInline(stack)) "it is unsafe (target may reference private fields)" else "of a bug (run with -Ylog:inline -Ydebug for more information)" @@ -550,14 +549,14 @@ abstract class Inliners extends SubComponent { */ def isSafeToInline(stack: TypeStack): Boolean = { def makePublic(f: Symbol): Boolean = - inc.hasSourceFile && (f.isSynthetic || f.isParamAccessor) && { + (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && { debuglog("Making not-private symbol out of synthetic: " + f) f setNotFlag Flags.PRIVATE true } - if (!inc.hasCode || inc.isRecursive) + if (!inc.m.hasCode || inc.isRecursive) return false val accessNeeded = usesNonPublics.getOrElseUpdate(inc.m, { @@ -610,7 +609,7 @@ abstract class Inliners extends SubComponent { * - it's good to inline closures functions. * - it's bad (useless) to inline inside bridge methods */ - private def neverInline = caller.isBridge || !inc.hasCode || inc.noinline + private def neverInline = caller.isBridge || !inc.m.hasCode || inc.noinline private def alwaysInline = inc.inline def shouldInline: Boolean = !neverInline && (alwaysInline || { |