summaryrefslogtreecommitdiff
path: root/src/compiler
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 /src/compiler
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 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala4
3 files changed, 19 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
index 4a10756468..328a8187c8 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
@@ -40,7 +40,7 @@ abstract class BCodeIdiomatic extends SubComponent {
if (emitStackMapFrame) asm.ClassWriter.COMPUTE_FRAMES else 0
)
- val StringBuilderClassName = "scala/collection/mutable/StringBuilder"
+ lazy val JavaStringBuilderClassName = jlStringBuilderRef.internalName
val EMPTY_STRING_ARRAY = Array.empty[String]
val EMPTY_INT_ARRAY = Array.empty[Int]
@@ -184,10 +184,10 @@ abstract class BCodeIdiomatic extends SubComponent {
* can-multi-thread
*/
final def genStartConcat(pos: Position): Unit = {
- jmethod.visitTypeInsn(Opcodes.NEW, StringBuilderClassName)
+ jmethod.visitTypeInsn(Opcodes.NEW, JavaStringBuilderClassName)
jmethod.visitInsn(Opcodes.DUP)
invokespecial(
- StringBuilderClassName,
+ JavaStringBuilderClassName,
INSTANCE_CONSTRUCTOR_NAME,
"()V",
pos
@@ -198,21 +198,23 @@ abstract class BCodeIdiomatic extends SubComponent {
* can-multi-thread
*/
final def genStringConcat(el: BType, pos: Position): Unit = {
-
- val jtype =
- if (el.isArray || el.isClass) ObjectRef
- else el
+ val jtype = el match {
+ case ct: ClassBType if ct.isSubtypeOf(StringRef).get => StringRef
+ case ct: ClassBType if ct.isSubtypeOf(jlStringBufferRef).get => jlStringBufferRef
+ case ct: ClassBType if ct.isSubtypeOf(jlCharSequenceRef).get => jlCharSequenceRef
+ case rt: RefBType => ObjectRef
+ case pt: PrimitiveBType => pt // Currently this ends up being boxed in erasure
+ }
val bt = MethodBType(List(jtype), jlStringBuilderRef)
-
- invokevirtual(StringBuilderClassName, "append", bt.descriptor, pos)
+ invokevirtual(JavaStringBuilderClassName, "append", bt.descriptor, pos)
}
/*
* can-multi-thread
*/
final def genEndConcat(pos: Position): Unit = {
- invokevirtual(StringBuilderClassName, "toString", "()Ljava/lang/String;", pos)
+ invokevirtual(JavaStringBuilderClassName, "toString", "()Ljava/lang/String;", pos)
}
/*
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
index 8bb71a386f..6d322d1a34 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
@@ -95,7 +95,9 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) {
lazy val ObjectRef : ClassBType = classBTypeFromSymbol(ObjectClass)
lazy val StringRef : ClassBType = classBTypeFromSymbol(StringClass)
lazy val PredefRef : ClassBType = classBTypeFromSymbol(PredefModule.moduleClass)
- lazy val jlStringBuilderRef : ClassBType = classBTypeFromSymbol(StringBuilderClass)
+ lazy val jlStringBuilderRef : ClassBType = classBTypeFromSymbol(JavaStringBuilderClass)
+ lazy val jlStringBufferRef : ClassBType = classBTypeFromSymbol(JavaStringBufferClass)
+ lazy val jlCharSequenceRef : ClassBType = classBTypeFromSymbol(JavaCharSequenceClass)
lazy val jlThrowableRef : ClassBType = classBTypeFromSymbol(ThrowableClass)
lazy val jlCloneableRef : ClassBType = classBTypeFromSymbol(JavaCloneableClass) // java/lang/Cloneable
lazy val jiSerializableRef : ClassBType = classBTypeFromSymbol(JavaSerializableClass) // java/io/Serializable
@@ -343,6 +345,8 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes:
def StringRef : ClassBType = _coreBTypes.StringRef
def PredefRef : ClassBType = _coreBTypes.PredefRef
def jlStringBuilderRef : ClassBType = _coreBTypes.jlStringBuilderRef
+ def jlStringBufferRef : ClassBType = _coreBTypes.jlStringBufferRef
+ def jlCharSequenceRef : ClassBType = _coreBTypes.jlCharSequenceRef
def jlThrowableRef : ClassBType = _coreBTypes.jlThrowableRef
def jlCloneableRef : ClassBType = _coreBTypes.jlCloneableRef
def jiSerializableRef : ClassBType = _coreBTypes.jiSerializableRef
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
index 4ecaf17a10..16fe2e5cff 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
@@ -21,7 +21,7 @@ class BoxUnbox[BT <: BTypes](val btypes: BT) {
import backendUtils._
/**
- * Eliminate box-unbox paris within `method`. Such appear commonly after closure elimination:
+ * Eliminate box-unbox pairs within `method`. Such appear commonly after closure elimination:
*
* def t2 = {
* val f = (b: Byte, i: Int) => i + b // no specialized variant for this function type
@@ -767,7 +767,7 @@ class BoxUnbox[BT <: BTypes](val btypes: BT) {
private def isSpecializedTupleClass(tupleClass: InternalName) = specializedTupleClassR.pattern.matcher(tupleClass).matches
private val specializedTupleGetterR = "_[12]\\$mc[IJDCZ]\\$sp".r
- private def isSpecializedTupleGetter(mi: MethodInsnNode) = specializedTupleGetterR.pattern.matcher(mi.name)matches
+ private def isSpecializedTupleGetter(mi: MethodInsnNode) = specializedTupleGetterR.pattern.matcher(mi.name).matches
private val tupleGetterR = "_\\d\\d?".r
private def isTupleGetter(mi: MethodInsnNode) = tupleGetterR.pattern.matcher(mi.name).matches