diff options
Diffstat (limited to 'src')
3 files changed, 16 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 00f4a9d262..44c4a3a6db 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -170,6 +170,7 @@ trait Members { var sourceFile: SourceFile = NoSourceFile var returnType: TypeKind = _ var recursive: Boolean = false + var bytecodeHasEHs = false // set by ICodeReader only, used by Inliner to prevent inlining (SI-6188) /** local variables and method parameters */ var locals: List[Local] = Nil diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index cce18d436f..dd7676a371 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -405,6 +405,12 @@ abstract class Inliners extends SubComponent { val inc = new IMethodInfo(callee) val pair = new CallerCalleeInfo(caller, inc, fresh, inlinedMethodCount) + if(inc.hasHandlers && (stackLength == -1)) { + // no inlining is done, yet don't warn about it, stackLength == -1 indicates we're trying to inlineWithoutTFA. + // Shortly, a TFA will be computed and an error message reported if indeed inlining not possible. + return false + } + (pair isStampedForInlining stackLength) match { case inlInfo if inlInfo.isSafe => @@ -605,7 +611,7 @@ abstract class Inliners extends SubComponent { def isSmall = (length <= SMALL_METHOD_SIZE) && blocks(0).length < 10 def isLarge = length > MAX_INLINE_SIZE def isRecursive = m.recursive - def hasHandlers = handlers.nonEmpty + def hasHandlers = handlers.nonEmpty || m.bytecodeHasEHs def isSynchronized = sym.hasFlag(Flags.SYNCHRONIZED) def hasNonFinalizerHandler = handlers exists { @@ -941,6 +947,7 @@ abstract class Inliners extends SubComponent { if(inc.isRecursive) { rs ::= "is recursive" } if(isInlineForbidden) { rs ::= "is annotated @noinline" } if(inc.isSynchronized) { rs ::= "is synchronized method" } + if(inc.m.bytecodeHasEHs) { rs ::= "bytecode contains exception handlers / finally clause" } // SI-6188 if(rs.isEmpty) null else rs.mkString("", ", and ", "") } @@ -974,6 +981,10 @@ abstract class Inliners extends SubComponent { return DontInlineHere("too low score (heuristics)") } + if(inc.hasHandlers && (stackLength != 0)) { + // TODO pending return DontInlineHere("callee contains exception handlers / finally clause, and is invoked with non-empty operand stack") // SI-6157 + } + if(isKnownToInlineSafely) { return InlineableAtThisCaller } if(stackLength > inc.minimumStack && inc.hasNonFinalizerHandler) { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index bb9f9bde98..3a3be4dc78 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -594,6 +594,7 @@ abstract class ICodeReader extends ClassfileParser { while (pc < codeLength) parseInstruction val exceptionEntries = in.nextChar.toInt + code.containsEHs = (exceptionEntries != 0) var i = 0 while (i < exceptionEntries) { // skip start end PC @@ -647,6 +648,7 @@ abstract class ICodeReader extends ClassfileParser { var containsDUPX = false var containsNEW = false + var containsEHs = false def emit(i: Instruction) { instrs += ((pc, i)) @@ -664,6 +666,7 @@ abstract class ICodeReader extends ClassfileParser { val code = new Code(method) method.setCode(code) + method.bytecodeHasEHs = containsEHs var bb = code.startBlock def makeBasicBlocks: mutable.Map[Int, BasicBlock] = |