summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Garcia <miguelalfredo.garcia@epfl.ch>2012-08-06 11:01:17 +0200
committerMiguel Garcia <miguelalfredo.garcia@epfl.ch>2012-08-06 11:01:17 +0200
commit61cc8ff61c81a1276a921ad5288ee3bebea1c96e (patch)
tree516aabb9f5ce523ef26b0e3ac8099dd818bb314d
parenta05a68a9894f78fc8d7423c722e516a7ee49d559 (diff)
downloadscala-61cc8ff61c81a1276a921ad5288ee3bebea1c96e.tar.gz
scala-61cc8ff61c81a1276a921ad5288ee3bebea1c96e.tar.bz2
scala-61cc8ff61c81a1276a921ad5288ee3bebea1c96e.zip
SI-6188 ICodeReader notes exception handlers, Inliner takes them into account
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala13
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala3
-rw-r--r--test/files/run/t6188.check1
-rw-r--r--test/files/run/t6188.flags1
-rw-r--r--test/files/run/t6188.scala12
6 files changed, 30 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] =
diff --git a/test/files/run/t6188.check b/test/files/run/t6188.check
new file mode 100644
index 0000000000..1af3932ecd
--- /dev/null
+++ b/test/files/run/t6188.check
@@ -0,0 +1 @@
+Failure(java.lang.Exception: this is an exception)
diff --git a/test/files/run/t6188.flags b/test/files/run/t6188.flags
new file mode 100644
index 0000000000..0ebca3e7af
--- /dev/null
+++ b/test/files/run/t6188.flags
@@ -0,0 +1 @@
+ -optimize
diff --git a/test/files/run/t6188.scala b/test/files/run/t6188.scala
new file mode 100644
index 0000000000..48180ddf9d
--- /dev/null
+++ b/test/files/run/t6188.scala
@@ -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)
+ }
+}
+