From 904fed2d2e7125aef40bb43c4f25af9b9c00df65 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 26 Jan 2018 16:56:41 +0100 Subject: [PATCH 1/2] Fix #746: Generate efficient try cases for parameterized exceptions We were missing a case for AppliedType --- .../dotty/tools/dotc/transform/TryCatchPatterns.scala | 2 ++ tests/pos/i746.scala | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/pos/i746.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index a669dcb79843..eb4183167097 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -76,6 +76,8 @@ class TryCatchPatterns extends MiniPhase { (pre == NoPrefix || pre.widen.typeSymbol.isStatic) && // Does not require outer class check !tp.symbol.is(Flags.Trait) && // Traits not supported by JVM tp.derivesFrom(defn.ThrowableClass) + case tp: AppliedType => + isSimpleThrowable(tp.tycon) case _ => false } diff --git a/tests/pos/i746.scala b/tests/pos/i746.scala new file mode 100644 index 000000000000..c221cfc00e28 --- /dev/null +++ b/tests/pos/i746.scala @@ -0,0 +1,10 @@ +class Test[T] { + + def f(x: Int) = try { + ??? + } + catch { + case ex: scala.runtime.NonLocalReturnControl[T @scala.unchecked] => + ??? + } +} From 578b3341876b391f273840fa7af2dcdfdc5c3195 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 26 Jan 2018 19:30:08 +0100 Subject: [PATCH 2/2] Add bytecode test --- .../backend/jvm/DottyBytecodeTests.scala | 28 +++++++++++++++++++ tests/pos/i746.scala | 10 ------- 2 files changed, 28 insertions(+), 10 deletions(-) delete mode 100644 tests/pos/i746.scala diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala index d288e26f1950..9f90bedf2598 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -3,6 +3,8 @@ package dotty.tools.backend.jvm import org.junit.Assert._ import org.junit.Test +import scala.tools.asm.Opcodes + class TestBCode extends DottyBytecodeTest { import ASMConverters._ @Test def nullChecks = { @@ -213,4 +215,30 @@ class TestBCode extends DottyBytecodeTest { assert(!arrayWrapped, "Arrays should not be wrapped when passed to a Java varargs method\n") } } + + @Test def efficientTryCases = { + val source = + """ + |class Test { + | def test = + | try print("foo") + | catch { + | case _: scala.runtime.NonLocalReturnControl[_] => () + | } + |} + """.stripMargin + + checkBCode(source) { dir => + val moduleIn = dir.lookupName("Test.class", directory = false) + val moduleNode = loadClassNode(moduleIn.input) + val method = getMethod(moduleNode, "test") + + val hasInstanceof = instructionsFromMethod(method).exists { + case TypeOp(Opcodes.INSTANCEOF, _) => true + case _ => false + } + + assert(!hasInstanceof, "Try case should not issue INSTANCEOF opcode\n") + } + } } diff --git a/tests/pos/i746.scala b/tests/pos/i746.scala deleted file mode 100644 index c221cfc00e28..000000000000 --- a/tests/pos/i746.scala +++ /dev/null @@ -1,10 +0,0 @@ -class Test[T] { - - def f(x: Int) = try { - ??? - } - catch { - case ex: scala.runtime.NonLocalReturnControl[T @scala.unchecked] => - ??? - } -}