summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-12-20 14:45:11 -0800
committerPaul Phillips <paulp@improving.org>2012-01-03 10:57:06 -0800
commit45a26ce3102f54e4f72165aef42fab7f73681c1d (patch)
treed13f32bce0859bb162d96b844fbdc10a368d1df6 /src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
parent471a63a9e6618f25feb3a5266c38ad98ea2a5ac7 (diff)
downloadscala-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.scala35
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 || {