Remove Concat and StringPlus intrinsics in favor of IrStringConcatenation.
This commit is contained in:
committed by
max-kammerer
parent
26c9d69252
commit
f2392a6a28
+10
-6
@@ -8,13 +8,15 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrStringConcatenationImpl
|
||||
import org.jetbrains.kotlin.ir.types.isString
|
||||
import org.jetbrains.kotlin.ir.types.isStringClassType
|
||||
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -73,11 +75,13 @@ class FlattenStringConcatenationLowering(val context: CommonBackendContext) : Fi
|
||||
return when (expression) {
|
||||
is IrStringConcatenation -> true
|
||||
is IrCall -> {
|
||||
val dispatchReceiver = expression.dispatchReceiver
|
||||
dispatchReceiver != null &&
|
||||
dispatchReceiver.type.isString() &&
|
||||
expression.symbol.owner.name == PLUS_NAME &&
|
||||
expression.type.isString() &&
|
||||
val function = expression.symbol.owner
|
||||
val receiver = expression.dispatchReceiver ?: expression.extensionReceiver
|
||||
receiver != null &&
|
||||
receiver.type.isStringClassType() &&
|
||||
function.getPackageFragment()?.fqName == KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME &&
|
||||
function.name == PLUS_NAME &&
|
||||
expression.type.isStringClassType() &&
|
||||
expression.valueArgumentsCount == 1
|
||||
}
|
||||
else -> false
|
||||
|
||||
+22
-7
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.Not
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.CrIrType
|
||||
@@ -29,9 +30,7 @@ import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -774,12 +773,28 @@ class ExpressionCodegen(
|
||||
|
||||
override fun visitStringConcatenation(expression: IrStringConcatenation, data: BlockInfo): PromisedValue {
|
||||
expression.markLineNumber(startOffset = true)
|
||||
when (expression.arguments.size) {
|
||||
0 -> mv.aconst("")
|
||||
1 -> {
|
||||
val arity = expression.arguments.size
|
||||
when {
|
||||
arity == 0 -> mv.aconst("")
|
||||
arity == 1 -> {
|
||||
// Convert single arg to string.
|
||||
val type = expression.arguments[0].accept(this, data).materialized.type
|
||||
AsmUtil.genToString(StackValue.onStack(type), type, null, typeMapper).put(expression.asmType, mv)
|
||||
if (!expression.arguments[0].type.isString())
|
||||
AsmUtil.genToString(StackValue.onStack(type), type, null, typeMapper).put(expression.asmType, mv)
|
||||
}
|
||||
arity == 2 && expression.arguments[0].type.isStringClassType() -> {
|
||||
// Call the stringPlus intrinsic
|
||||
expression.arguments.forEach {
|
||||
val type = it.accept(this, data).materialized.type
|
||||
if (type.sort != Type.OBJECT)
|
||||
AsmUtil.genToString(StackValue.onStack(type), type, null, typeMapper).put(expression.asmType, mv)
|
||||
}
|
||||
mv.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME,
|
||||
"stringPlus",
|
||||
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;",
|
||||
false
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
// Use StringBuilder to concatenate.
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class Concat : IntrinsicMethod() {
|
||||
override fun toCallable(
|
||||
expression: IrMemberAccessExpression,
|
||||
signature: JvmMethodSignature,
|
||||
context: JvmBackendContext
|
||||
): IrIntrinsicFunction {
|
||||
val argsTypes = expression.receiverAndArgs().asmTypes(context).toMutableList()
|
||||
argsTypes[0] = AsmTypes.JAVA_STRING_TYPE
|
||||
|
||||
return object : IrIntrinsicFunction(expression, signature, context, argsTypes) {
|
||||
|
||||
override fun genInvokeInstruction(v: InstructionAdapter) {
|
||||
AsmUtil.genInvokeAppendMethod(v, argsTypes[1], null)
|
||||
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)
|
||||
}
|
||||
|
||||
override fun invoke(
|
||||
v: InstructionAdapter,
|
||||
codegen: org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen,
|
||||
data: BlockInfo
|
||||
): StackValue {
|
||||
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
|
||||
v.dup()
|
||||
|
||||
return super.invoke(v, codegen, data)
|
||||
}
|
||||
|
||||
|
||||
override fun genArg(
|
||||
expression: IrExpression,
|
||||
codegen: org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen,
|
||||
index: Int,
|
||||
data: BlockInfo
|
||||
) {
|
||||
super.genArg(expression, codegen, index, data)
|
||||
if (index == 0) {
|
||||
codegen.mv.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-3
@@ -55,7 +55,6 @@ public class IntrinsicMethods {
|
||||
private static final IteratorNext ITERATOR_NEXT = new IteratorNext();
|
||||
private static final ArraySet ARRAY_SET = new ArraySet();
|
||||
private static final ArrayGet ARRAY_GET = new ArrayGet();
|
||||
private static final StringPlus STRING_PLUS = new StringPlus();
|
||||
private static final ToString TO_STRING = new ToString();
|
||||
private static final Clone CLONE = new Clone();
|
||||
|
||||
@@ -119,13 +118,11 @@ public class IntrinsicMethods {
|
||||
|
||||
declareIntrinsicFunction(FQ_NAMES._boolean, "not", 0, new Not());
|
||||
|
||||
declareIntrinsicFunction(FQ_NAMES.string, "plus", 1, new Concat());
|
||||
declareIntrinsicFunction(FQ_NAMES.string, "get", 1, new StringGetChar());
|
||||
|
||||
declareIntrinsicFunction(FQ_NAMES.cloneable, "clone", 0, CLONE);
|
||||
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.FQ_NAMES.any, "toString", 0, TO_STRING);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.FQ_NAMES.string, "plus", 1, STRING_PLUS);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOfNulls", 1, new NewArray());
|
||||
|
||||
for (PrimitiveType type : PrimitiveType.values()) {
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ open class IrIntrinsicFunction(
|
||||
}
|
||||
}
|
||||
|
||||
open fun genArg(expression: IrExpression, codegen: ExpressionCodegen, index: Int, data: BlockInfo) {
|
||||
private fun genArg(expression: IrExpression, codegen: ExpressionCodegen, index: Int, data: BlockInfo) {
|
||||
codegen.gen(expression, argsTypes[index], data)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
|
||||
class StringPlus : IntrinsicMethod() {
|
||||
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
|
||||
return IrIntrinsicFunction.create(expression, signature, context) {
|
||||
it.invokestatic("kotlin/jvm/internal/Intrinsics", "stringPlus",
|
||||
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,9 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName
|
||||
private fun IrType.isNotNullClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = false)
|
||||
private fun IrType.isNullableClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = true)
|
||||
|
||||
private fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean): Boolean {
|
||||
private fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean? = null): Boolean {
|
||||
if (this !is IrSimpleType) return false
|
||||
if (this.hasQuestionMark != hasQuestionMark) return false
|
||||
if (hasQuestionMark != null && this.hasQuestionMark != hasQuestionMark) return false
|
||||
val classSymbol = this.classifier as? IrClassSymbol ?: return false
|
||||
return classFqNameEquals(classSymbol, fqName)
|
||||
}
|
||||
@@ -37,6 +37,7 @@ fun IrType.isNullableAny(): Boolean = isNullableClassType(KotlinBuiltIns.FQ_NAME
|
||||
|
||||
fun IrType.isString(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.string)
|
||||
fun IrType.isNullableString(): Boolean = isNullableClassType(KotlinBuiltIns.FQ_NAMES.string)
|
||||
fun IrType.isStringClassType(): Boolean = isClassType(KotlinBuiltIns.FQ_NAMES.string)
|
||||
fun IrType.isArray(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.array)
|
||||
fun IrType.isNullableArray(): Boolean = isNullableClassType(KotlinBuiltIns.FQ_NAMES.array)
|
||||
fun IrType.isCollection(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.collection.toUnsafe())
|
||||
|
||||
Reference in New Issue
Block a user