summaryrefslogtreecommitdiff
path: root/test/files/run/icode-reader-dead-code.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2014-06-05 10:37:20 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2014-06-05 10:37:20 +0200
commit5fc16e4ee7ab0be163f4a12600538ce628a6ce2a (patch)
treed7f17d949cd6a098ccadb910b3e2ea0fd94f0dfd /test/files/run/icode-reader-dead-code.scala
parentee6ffbfc5d403137b8e6a4fd91960a7cc0defd34 (diff)
downloadscala-5fc16e4ee7ab0be163f4a12600538ce628a6ce2a.tar.gz
scala-5fc16e4ee7ab0be163f4a12600538ce628a6ce2a.tar.bz2
scala-5fc16e4ee7ab0be163f4a12600538ce628a6ce2a.zip
Test: classfile reading during inlining works if there is dead code
Diffstat (limited to 'test/files/run/icode-reader-dead-code.scala')
-rw-r--r--test/files/run/icode-reader-dead-code.scala82
1 files changed, 82 insertions, 0 deletions
diff --git a/test/files/run/icode-reader-dead-code.scala b/test/files/run/icode-reader-dead-code.scala
new file mode 100644
index 0000000000..00ba58829f
--- /dev/null
+++ b/test/files/run/icode-reader-dead-code.scala
@@ -0,0 +1,82 @@
+import java.io.{FileOutputStream, FileInputStream}
+
+import scala.tools.asm.{ClassWriter, Opcodes, ClassReader}
+import scala.tools.asm.tree.{InsnNode, ClassNode}
+import scala.tools.nsc.backend.jvm.AsmUtils
+import scala.tools.partest.DirectTest
+import scala.collection.JavaConverters._
+
+/**
+ * Test that the ICodeReader does not crash if the bytecode of a method has unreachable code.
+ */
+object Test extends DirectTest {
+ def code: String = ???
+
+ def show(): Unit = {
+ // The bytecode of f will be modified using ASM by `addDeadCode`
+ val aCode =
+ """
+ |package p
+ |class A {
+ | @inline final def f = 1
+ |}
+ """.stripMargin
+
+ val bCode =
+ """
+ |package p
+ |class B {
+ | def g = (new A()).f
+ |}
+ """.stripMargin
+
+ compileString(newCompiler("-usejavacp"))(aCode)
+
+ addDeadCode()
+
+ // If inlining fails, the compiler will issue an inliner warning that is not present in the
+ // check file
+ compileString(newCompiler("-usejavacp", "-optimise"))(bCode)
+ }
+
+ def readClass(file: String) = {
+ val cnode = new ClassNode()
+ val is = new FileInputStream(file)
+ val reader = new ClassReader(is)
+ reader.accept(cnode, 0)
+ is.close()
+ cnode
+ }
+
+ def writeClass(file: String, cnode: ClassNode): Unit = {
+ val writer = new ClassWriter(0)
+ cnode.accept(writer)
+
+ val os = new FileOutputStream(file)
+ os.write(writer.toByteArray)
+ os.close()
+ }
+
+ def addDeadCode() {
+ val file = (testOutput / "p" / "A.class").path
+ val cnode = readClass(file)
+ val method = cnode.methods.asScala.find(_.name == "f").head
+
+ AsmUtils.traceMethod(method)
+
+ val insns = method.instructions
+ val it = insns.iterator()
+ while (it.hasNext) {
+ val in = it.next()
+ if (in.getOpcode == Opcodes.IRETURN) {
+ // Insert an ATHROW before the IRETURN. The IRETURN will then be dead code.
+ // The ICodeReader should not crash if there's dead code.
+ insns.insert(in.getPrevious, new InsnNode(Opcodes.ATHROW))
+ }
+ }
+
+ AsmUtils.traceMethod(method)
+
+ writeClass(file, cnode)
+ }
+}