Skip to content

Commit ef77a54

Browse files
committed
Merge pull request scala#4916 from lrytz/restoreASMTests
Restore backend tests that were removed together with GenASM
2 parents 90ee1b8 + 983894f commit ef77a54

34 files changed

+374
-655
lines changed

test/junit/scala/collection/immutable/SetTests.scala renamed to test/junit/scala/collection/immutable/SetTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import org.junit.runner.RunWith
66
import org.junit.runners.JUnit4
77

88
@RunWith(classOf[JUnit4])
9-
class SetTests {
9+
class SetTest {
1010
@Test
1111
def test_SI8346_toSet_soundness(): Unit = {
1212
val any2stringadd = "Disabled string conversions so as not to get confused!"

test/junit/scala/issues/BytecodeTests.scala renamed to test/junit/scala/issues/BytecodeTest.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import scala.collection.JavaConverters._
1111
import scala.tools.partest.ASMConverters._
1212
import scala.tools.testing.ClearAfterClass
1313

14-
object BytecodeTests extends ClearAfterClass.Clearable {
14+
object BytecodeTest extends ClearAfterClass.Clearable {
1515
var compiler = newCompiler()
1616
def clear(): Unit = { compiler = null }
1717
}
1818

1919
@RunWith(classOf[JUnit4])
20-
class BytecodeTests extends ClearAfterClass {
21-
ClearAfterClass.stateToClear = BytecodeTests
22-
val compiler = BytecodeTests.compiler
20+
class BytecodeTest extends ClearAfterClass {
21+
ClearAfterClass.stateToClear = BytecodeTest
22+
val compiler = BytecodeTest.compiler
2323

2424
@Test
2525
def t8731(): Unit = {
@@ -107,7 +107,6 @@ class BytecodeTests extends ClearAfterClass {
107107

108108
import Opcodes._
109109
val expected = List(
110-
LineNumber(3, Label(0)),
111110
LineNumber(4, Label(0)),
112111
LineNumber(5, Label(5)),
113112
Jump(IFNE, Label(11)),

test/junit/scala/sys/process/t7350.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
package scala.sys.process
32

43
import org.junit.runner.RunWith

test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ object CodeGenTools {
4848
resetOutput(compiler)
4949
compiler
5050
}
51-
51+
5252
def newCompilerWithoutVirtualOutdir(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Global = {
5353
val settings = new Settings()
5454
val args = (CommandLineParser tokenize defaultArgs) ++ (CommandLineParser tokenize extraArgs)

test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,4 +1468,52 @@ class InlinerTest extends ClearAfterClass {
14681468
assertEquals(casts("t5"), Nil)
14691469
assertEquals(casts("t6"), Nil)
14701470
}
1471+
1472+
@Test
1473+
def inlineFromSealed(): Unit = {
1474+
val code =
1475+
"""sealed abstract class Foo {
1476+
| @inline def bar(x: Int) = x + 1
1477+
|}
1478+
|object Foo {
1479+
| def mkFoo(): Foo = new Baz2
1480+
|}
1481+
|
1482+
|object Baz1 extends Foo
1483+
|final class Baz2 extends Foo
1484+
|
1485+
|object Test {
1486+
| def f = Foo.mkFoo() bar 10
1487+
|}
1488+
""".stripMargin
1489+
1490+
val cls = compile(code)
1491+
val test = cls.find(_.name == "Test$").get
1492+
assertEquals(
1493+
getSingleMethod(test, "f").instructions.summary,
1494+
List(GETSTATIC, "mkFoo",
1495+
BIPUSH, ISTORE,
1496+
IFNONNULL, ACONST_NULL, ATHROW, -1 /*label*/,
1497+
ILOAD, ICONST_1, IADD, IRETURN))
1498+
}
1499+
1500+
@Test // a test taken from the test suite for the 2.11 inliner
1501+
def oldInlineHigherOrderTest(): Unit = {
1502+
val code =
1503+
"""class C {
1504+
| private var debug = false
1505+
| @inline private def ifelse[T](cond: => Boolean, ifPart: => T, elsePart: => T): T = if (cond) ifPart else elsePart
1506+
| final def t = ifelse(debug, 1, 2)
1507+
|}
1508+
""".stripMargin
1509+
val List(c) = compile(code)
1510+
val t = getSingleMethod(c, "t")
1511+
1512+
// box-unbox will clean it up
1513+
assertEquals(getSingleMethod(c, "t").instructions.summary,
1514+
List(
1515+
ALOAD, "C$$$anonfun$1", IFEQ /*A*/,
1516+
"C$$$anonfun$2", IRETURN,
1517+
-1 /*A*/, "C$$$anonfun$3", IRETURN))
1518+
}
14711519
}

test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala

Lines changed: 183 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@ import org.junit.Test
88
import scala.tools.asm.Opcodes._
99
import org.junit.Assert._
1010

11+
import scala.tools.asm.tree.ClassNode
1112
import scala.tools.nsc.backend.jvm.AsmUtils._
1213
import scala.tools.testing.AssertUtil._
1314

1415
import CodeGenTools._
1516
import scala.tools.partest.ASMConverters
1617
import ASMConverters._
1718
import scala.tools.testing.ClearAfterClass
19+
import scala.collection.convert.decorateAsScala._
1820

1921
object MethodLevelOptsTest extends ClearAfterClass.Clearable {
20-
var methodOptCompiler = newCompiler(extraArgs = "-Ybackend:GenBCode -Yopt:l:method")
22+
var methodOptCompiler = newCompiler(extraArgs = "-Yopt:l:method")
2123
def clear(): Unit = { methodOptCompiler = null }
2224
}
2325

@@ -29,6 +31,8 @@ class MethodLevelOptsTest extends ClearAfterClass {
2931

3032
def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1))
3133

34+
def locals(c: ClassNode, m: String) = findAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2)
35+
3236
@Test
3337
def eliminateEmptyTry(): Unit = {
3438
val code = "def f = { try {} catch { case _: Throwable => 0; () }; 1 }"
@@ -559,4 +563,182 @@ class MethodLevelOptsTest extends ClearAfterClass {
559563
getSingleMethod(c, "t").instructions.dropNonOp,
560564
List(VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), Op(ICONST_1), Op(IRETURN), Label(6), Op(ICONST_0), Op(IRETURN)))
561565
}
566+
567+
@Test
568+
def t5313(): Unit = {
569+
val code =
570+
"""class C {
571+
| def randomBoolean = scala.util.Random.nextInt % 2 == 0
572+
|
573+
| // 3 stores to kept1 (slot 1), 1 store to result (slot 2)
574+
| def t1 = {
575+
| var kept1 = new Object
576+
| val result = new java.lang.ref.WeakReference(kept1)
577+
| kept1 = null // we can't eliminate this assignment because result can observe
578+
| // when the object has no more references. See SI-5313
579+
| kept1 = new Object // could eliminate this one with a more elaborate analysis (we know it contains null)
580+
| // however, such is not implemented: if a var is live, then stores are kept.
581+
| result
582+
| }
583+
|
584+
| // only two variables are live: kept2 and kept3. they end up on slots 1 and 2.
585+
| // kept2 has 2 stores, kept3 has 1 store.
586+
| def t2 = {
587+
| var erased2 = null // we can eliminate this store because it's never used
588+
| val erased3 = erased2 // and this
589+
| var erased4 = erased2 // and this
590+
| val erased5 = erased4 // and this
591+
| var kept2: Object = new Object // ultimately can't be eliminated
592+
| while(randomBoolean) {
593+
| val kept3 = kept2
594+
| kept2 = null // this can't, because it clobbers kept2, which is used
595+
| erased4 = null // safe to eliminate
596+
| println(kept3)
597+
| }
598+
| 0
599+
| }
600+
|
601+
| def t3 = {
602+
| var kept4 = new Object // have to keep, it's used
603+
| try
604+
| println(kept4)
605+
| catch {
606+
| case _ : Throwable => kept4 = null // have to keep, it clobbers kept4 which is used
607+
| }
608+
| 0
609+
| }
610+
|
611+
| def t4 = {
612+
| var kept5 = new Object
613+
| print(kept5)
614+
| kept5 = null // can't eliminate it's a clobber and it's used
615+
| print(kept5)
616+
| kept5 = null // eliminated by nullness analysis (store null to a local that is known to be null)
617+
| 0
618+
| }
619+
|
620+
| def t5 = {
621+
| while(randomBoolean) {
622+
| var kept6: AnyRef = null // not used, but have to keep because it clobbers the next used store
623+
| // on the back edge of the loop
624+
| kept6 = new Object // used
625+
| println(kept6)
626+
| }
627+
| 0
628+
| }
629+
|}
630+
""".stripMargin
631+
632+
val List(c) = compileClasses(methodOptCompiler)(code)
633+
def stores(m: String) = getSingleMethod(c, m).instructions.filter(_.opcode == ASTORE)
634+
635+
assertEquals(locals(c, "t1"), List(("this",0), ("kept1",1), ("result",2)))
636+
assert(stores("t1") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1), VarOp(ASTORE, 1)),
637+
textify(findAsmMethod(c, "t1")))
638+
639+
assertEquals(locals(c, "t2"), List(("this",0), ("kept2",1), ("kept3",2)))
640+
assert(stores("t2") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1)),
641+
textify(findAsmMethod(c, "t2")))
642+
643+
assertEquals(locals(c, "t3"), List(("this",0), ("kept4",1)))
644+
assert(stores("t3") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)),
645+
textify(findAsmMethod(c, "t3")))
646+
647+
assertEquals(locals(c, "t4"), List(("this",0), ("kept5",1)))
648+
assert(stores("t4") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)),
649+
textify(findAsmMethod(c, "t4")))
650+
651+
assertEquals(locals(c, "t5"), List(("this",0), ("kept6",1)))
652+
assert(stores("t5") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)),
653+
textify(findAsmMethod(c, "t5")))
654+
}
655+
656+
@Test
657+
def testCpp(): Unit = {
658+
// copied from an old test (run/test-cpp.scala)
659+
val code =
660+
"""class C {
661+
| import scala.util.Random._
662+
|
663+
| def t1(x: Int) = {
664+
| val y = x
665+
| println(y)
666+
| }
667+
|
668+
| def t2 = {
669+
| val x = 2
670+
| val y = x
671+
| println(y)
672+
| }
673+
|
674+
| def t3 = {
675+
| val x = this
676+
| val y = x
677+
| println(y)
678+
| }
679+
|
680+
| def f = nextInt
681+
|
682+
| def t4 = {
683+
| val x = f
684+
| val y = x
685+
| println(y)
686+
| }
687+
|
688+
| def t5 = {
689+
| var x = nextInt
690+
| var y = x
691+
| println(y)
692+
|
693+
| y = nextInt
694+
| x = y
695+
| println(x)
696+
| }
697+
|}
698+
""".stripMargin
699+
700+
val List(c) = compileClasses(methodOptCompiler)(code)
701+
assertEquals(locals(c, "t1"), List(("this", 0), ("x", 1)))
702+
703+
assertEquals(locals(c, "t2"), List(("this", 0), ("x", 1)))
704+
// we don't have constant propagation (yet).
705+
// the local var can't be optimized as a store;laod sequence, there's a GETSTATIC between the two
706+
assertEquals(
707+
textify(findAsmMethod(c, "t2")),
708+
getSingleMethod(c, "t2").instructions.dropNonOp.map(_.opcode),
709+
List(
710+
ICONST_2, ISTORE,
711+
GETSTATIC, // Predef.MODULE$
712+
ILOAD, INVOKESTATIC, // boxToInteger
713+
INVOKEVIRTUAL, // println
714+
RETURN))
715+
716+
assertEquals(locals(c, "t3"), List(("this", 0)))
717+
assertEquals(locals(c, "t4"), List(("this", 0), ("x", 1)))
718+
assertEquals(locals(c, "t5"), List(("this", 0), ("x", 1)))
719+
}
720+
721+
@Test
722+
def t7006(): Unit = {
723+
val code =
724+
"""class C {
725+
| def t: Unit = {
726+
| try {
727+
| val x = 3
728+
| } finally {
729+
| print("hello")
730+
| }
731+
| while(true) { }
732+
| }
733+
|}
734+
""".stripMargin
735+
val List(c) = compileClasses(methodOptCompiler)(code)
736+
val t = getSingleMethod(c, "t")
737+
assertEquals(t.handlers, Nil)
738+
assertEquals(locals(c, "t"), List(("this", 0)))
739+
assertEquals(t.instructions.summary,
740+
List(
741+
GETSTATIC, LDC, "print",
742+
-1, GOTO))
743+
}
562744
}

0 commit comments

Comments
 (0)