diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index bc35197ac3f..1c6aee0df5b 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -912,6 +912,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/arrays/kt45410.kt"); } + @Test + @TestMetadata("kt47499.kt") + public void testKt47499() throws Exception { + runTest("compiler/testData/codegen/box/arrays/kt47499.kt"); + } + @Test @TestMetadata("kt503.kt") public void testKt503() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt index 58494d2c808..4e18defecd6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt @@ -16,19 +16,31 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics -import org.jetbrains.kotlin.backend.jvm.codegen.* -import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression 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.Type object Clone : IntrinsicMethod() { - override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo) = with(codegen) { - val result = expression.dispatchReceiver!!.accept(this, data).materialized() - assert(!AsmUtil.isPrimitive(result.type)) { "clone() of primitive type" } - val opcode = if (expression is IrCall && expression.superQualifierSymbol != null) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL - mv.visitMethodInsn(opcode, "java/lang/Object", "clone", "()Ljava/lang/Object;", false) - MaterialValue(codegen, AsmTypes.OBJECT_TYPE, context.irBuiltIns.anyNType) + + private val CLONEABLE_TYPE = Type.getObjectType("java/lang/Cloneable") + + override fun toCallable( + expression: IrFunctionAccessExpression, + signature: JvmMethodSignature, + context: JvmBackendContext + ): IrIntrinsicFunction { + val isSuperCall = expression is IrCall && expression.superQualifierSymbol != null + val opcode = if (isSuperCall) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL + val newSignature = signature.newReturnType(AsmTypes.OBJECT_TYPE) + val argTypes0 = expression.argTypes(context) + // Don't upcast receiver to java.lang.Cloneable, since 'clone' is protected in java.lang.Object. + val argTypes = if (isSuperCall || argTypes0[0] == CLONEABLE_TYPE) listOf(AsmTypes.OBJECT_TYPE) else argTypes0 + return IrIntrinsicFunction.create(expression, newSignature, context, argTypes) { mv -> + mv.visitMethodInsn(opcode, "java/lang/Object", "clone", "()Ljava/lang/Object;", false) + } } } diff --git a/compiler/testData/codegen/box/arrays/kt47499.kt b/compiler/testData/codegen/box/arrays/kt47499.kt new file mode 100644 index 00000000000..46d1777b6b0 --- /dev/null +++ b/compiler/testData/codegen/box/arrays/kt47499.kt @@ -0,0 +1,79 @@ +// TARGET_BACKEND: JVM +// In Kotlin/JVM arrays are cloneable +// WITH_RUNTIME + +import kotlin.test.* + +fun T.id() = this + +fun Array.test() = id().clone() +fun Array.testGeneric() = id().clone() + +fun BooleanArray.test() = id().clone() +fun ByteArray.test() = id().clone() +fun ShortArray.test() = id().clone() +fun IntArray.test() = id().clone() +fun LongArray.test() = id().clone() +fun FloatArray.test() = id().clone() +fun DoubleArray.test() = id().clone() +fun CharArray.test() = id().clone() + +fun Array>.testGeneric2D() = id().clone() +fun Array.testInt2D() = id().clone() +fun Array>.testString2D() = id().clone() + +fun box(): String { + val a1 = arrayOf("a", "b", "c") + val a2 = a1.test() + assertEquals(a1.toList(), a2.toList()) + val a3 = a1.testGeneric() + assertEquals(a1.toList(), a3.toList()) + + val ba1 = booleanArrayOf(true) + val ba2 = ba1.test() + assertEquals(ba1.toList(), ba2.toList()) + + val bya1 = byteArrayOf(1, 2, 3) + val bya2 = bya1.test() + assertEquals(bya1.toList(), bya2.toList()) + + val sa1 = shortArrayOf(1, 2, 3) + val sa2 = sa1.test() + assertEquals(sa1.toList(), sa2.toList()) + + val ia1 = intArrayOf(1, 3, 5, 7) + val ia2 = ia1.test() + assertEquals(ia1.toList(), ia2.toList()) + + val la1 = longArrayOf(1, 2, 3, 4) + val la2 = la1.test() + assertEquals(la1.toList(), la2.toList()) + + val fa1 = floatArrayOf(0.1f, 0.2f, 0.3f) + val fa2 = fa1.test() + assertEquals(fa1.toList(), fa2.toList()) + + val da1 = doubleArrayOf(0.1, 0.2, 0.3) + val da2 = da1.test() + assertEquals(da1.toList(), da2.toList()) + + val ca1 = charArrayOf('a', 'b', 'c') + val ca2 = ca1.test() + assertEquals(ca1.toList(), ca2.toList()) + + val a2a1 = arrayOf(arrayOf(1, 2, 3)) + val a2a2 = a2a1.testGeneric() + val a2a3 = a2a1.testGeneric2D() + assertEquals(a2a1.toList(), a2a2.toList()) + assertEquals(a2a1.toList(), a2a3.toList()) + + val ia21 = arrayOf(intArrayOf(1, 2, 3)) + val ia22 = ia21.testInt2D() + assertEquals(ia21.toList(), ia22.toList()) + + val sa21 = arrayOf(arrayOf("a", "b", "c")) + val sa22 = sa21.testString2D() + assertEquals(sa21.toList(), sa22.toList()) + + return "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index cb4f9f2b2ba..fb043446876 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -912,6 +912,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/arrays/kt45410.kt"); } + @Test + @TestMetadata("kt47499.kt") + public void testKt47499() throws Exception { + runTest("compiler/testData/codegen/box/arrays/kt47499.kt"); + } + @Test @TestMetadata("kt503.kt") public void testKt503() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index a0c389e3039..d0bcf6b9f49 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -912,6 +912,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/arrays/kt45410.kt"); } + @Test + @TestMetadata("kt47499.kt") + public void testKt47499() throws Exception { + runTest("compiler/testData/codegen/box/arrays/kt47499.kt"); + } + @Test @TestMetadata("kt503.kt") public void testKt503() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 218350614bb..4bb8d49979c 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -797,6 +797,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/arrays/kt45410.kt"); } + @TestMetadata("kt47499.kt") + public void testKt47499() throws Exception { + runTest("compiler/testData/codegen/box/arrays/kt47499.kt"); + } + @TestMetadata("kt503.kt") public void testKt503() throws Exception { runTest("compiler/testData/codegen/box/arrays/kt503.kt");