Skip to content

Commit

Permalink
SI-6188 ICodeReader notes exception handlers, Inliner takes them into…
Browse files Browse the repository at this point in the history
… account
  • Loading branch information
magarciaEPFL committed Aug 6, 2012
1 parent a05a68a commit 61cc8ff
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/compiler/scala/tools/nsc/backend/icode/Members.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =>
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 ", "")
}

Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand All @@ -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] =
Expand Down
1 change: 1 addition & 0 deletions test/files/run/t6188.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Failure(java.lang.Exception: this is an exception)
1 change: 1 addition & 0 deletions test/files/run/t6188.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-optimize
12 changes: 12 additions & 0 deletions test/files/run/t6188.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SI-6188 Optimizer incorrectly removes method invocations containing throw expressions

import scala.util.Success

object Test {
def main(args: Array[String]) {
val e = new Exception("this is an exception")
val res = Success(1).flatMap[Int](x => throw e)
println(res)
}
}

0 comments on commit 61cc8ff

Please sign in to comment.