summaryrefslogtreecommitdiff
path: root/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala
diff options
context:
space:
mode:
authorSimon Ochsenreither <simon@ochsenreither.de>2015-09-02 19:01:37 +0200
committerSimon Ochsenreither <simon@ochsenreither.de>2016-02-03 10:42:21 +0100
commitcd0211cf0fb755281c7607bf6a172df306b5686f (patch)
treef0c049a38ae9f16d192edff6887e0d428ab13b74 /test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala
parentbbd890bf907c00f17df39eb4bc656b30d4317b9a (diff)
downloadscala-cd0211cf0fb755281c7607bf6a172df306b5686f.tar.gz
scala-cd0211cf0fb755281c7607bf6a172df306b5686f.tar.bz2
scala-cd0211cf0fb755281c7607bf6a172df306b5686f.zip
SI-9315 Desugar string concat to java.lang.StringBuilder ...
... instead of scala.collection.mutable.StringBuilder to benefit from JVM optimizations. Unfortunately primitives are already boxed in erasure when they end up in this part of the backend.
Diffstat (limited to 'test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala')
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala70
1 files changed, 70 insertions, 0 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala
new file mode 100644
index 0000000000..80cde6c9a9
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala
@@ -0,0 +1,70 @@
+package scala.tools.nsc
+package backend.jvm
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import scala.tools.testing.AssertUtil._
+
+import CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+import scala.tools.testing.ClearAfterClass
+
+object StringConcatTest extends ClearAfterClass.Clearable {
+ var compiler = newCompiler()
+ def clear(): Unit = { compiler = null }
+}
+
+@RunWith(classOf[JUnit4])
+class StringConcatTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = StringConcatTest
+ val compiler = StringConcatTest.compiler
+
+ val commonPreInstructions = List(Label(0), LineNumber(1, Label(0)), TypeOp(NEW, "java/lang/StringBuilder"), Op(DUP), Invoke(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false), Ldc(LDC, "abc"), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false), VarOp(ALOAD, 0))
+
+ val commonPostInstructions = List(Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false), Op(ARETURN), Label(12))
+
+ def instructionsWithCommonParts(instructions: List[Instruction]) = commonPreInstructions ++ instructions ++ commonPostInstructions
+
+ def instructionsForResultMethod(code: String): List[Instruction] = {
+ val methods = compileMethods(compiler)(code)
+ val resultMethod = methods.find(_.name == "result").get
+ instructionsFromMethod(resultMethod)
+ }
+
+ @Test
+ def concatStringToStringBuilder: Unit = {
+ val code = """ def string = "def"; def result = "abc" + string """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "string", "()Ljava/lang/String;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+
+ @Test
+ def concatStringBufferToStringBuilder: Unit = {
+ val code = """ def stringBuffer = new java.lang.StringBuffer("def"); def result = "abc" + stringBuffer """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "stringBuffer", "()Ljava/lang/StringBuffer;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/StringBuffer;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+
+ @Test
+ def concatCharSequenceToStringBuilder: Unit = {
+ val code = """ def charSequence: CharSequence = "def"; def result = "abc" + charSequence """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "charSequence", "()Ljava/lang/CharSequence;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+
+ @Test
+ def concatIntToStringBuilder: Unit = {
+ val code = """ def int = 123; def result = "abc" + int """
+ val actualInstructions = instructionsForResultMethod(code)
+ val expectedInstructions = instructionsWithCommonParts(List(Invoke(INVOKEVIRTUAL, "C", "int", "()I", false), Invoke(INVOKESTATIC, "scala/runtime/BoxesRunTime", "boxToInteger", "(I)Ljava/lang/Integer;", false), Invoke(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/Object;)Ljava/lang/StringBuilder;", false)))
+ assertSameCode(actualInstructions, expectedInstructions)
+ }
+}