Do not copy immediately created arrays in spread arguments
E.g., 'foo(x = *intArrayOf(42))'. #KT-20462 Fixed
This commit is contained in:
@@ -2656,6 +2656,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean canSkipArrayCopyForSpreadArgument(KtExpression spreadArgument) {
|
||||||
|
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt.getResolvedCall(spreadArgument, bindingContext);
|
||||||
|
if (resolvedCall == null) return false;
|
||||||
|
|
||||||
|
CallableDescriptor calleeDescriptor = resolvedCall.getResultingDescriptor();
|
||||||
|
return (calleeDescriptor instanceof ConstructorDescriptor) ||
|
||||||
|
CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall) ||
|
||||||
|
(DescriptorUtils.getFqName(calleeDescriptor).asString().equals("kotlin.arrayOfNulls"));
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public StackValue genVarargs(@NotNull VarargValueArgument valueArgument, @NotNull KotlinType outType) {
|
public StackValue genVarargs(@NotNull VarargValueArgument valueArgument, @NotNull KotlinType outType) {
|
||||||
@@ -2678,10 +2687,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
Type arrayType = getArrayType(arrayOfReferences ? AsmTypes.OBJECT_TYPE : elementType);
|
Type arrayType = getArrayType(arrayOfReferences ? AsmTypes.OBJECT_TYPE : elementType);
|
||||||
return StackValue.operation(type, adapter -> {
|
return StackValue.operation(type, adapter -> {
|
||||||
gen(arguments.get(0).getArgumentExpression(), type);
|
KtExpression spreadArgument = arguments.get(0).getArgumentExpression();
|
||||||
v.dup();
|
gen(spreadArgument, type);
|
||||||
v.arraylength();
|
if (!canSkipArrayCopyForSpreadArgument(spreadArgument)) {
|
||||||
v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false);
|
v.dup();
|
||||||
|
v.arraylength();
|
||||||
|
v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false);
|
||||||
|
}
|
||||||
if (arrayOfReferences) {
|
if (arrayOfReferences) {
|
||||||
v.checkcast(type);
|
v.checkcast(type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
fun booleanVararg(vararg xs: Boolean) {
|
||||||
|
if (xs.size != 1 && xs[0] != true) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byteVararg(vararg xs: Byte) {
|
||||||
|
if (xs.size != 1 && xs[0] != 1.toByte()) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shortVararg(vararg xs: Short) {
|
||||||
|
if (xs.size != 1 && xs[0] != 1.toShort()) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun intVararg(vararg xs: Int) {
|
||||||
|
if (xs.size != 1 && xs[0] != 1) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun longVararg(vararg xs: Long) {
|
||||||
|
if (xs.size != 1 && xs[0] != 1L) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun floatVararg(vararg xs: Float) {
|
||||||
|
if (xs.size != 1 && xs[0] != 1.0f) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doubleVararg(vararg xs: Double) {
|
||||||
|
if (xs.size != 1 && xs[0] != 1.0) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun anyVararg(vararg xs: Any?) {
|
||||||
|
if (xs.size != 1 && (xs[0] != 1 && xs[0] != null)) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> genericVararg(vararg xs: T) {
|
||||||
|
if (xs.size != 1 && (xs[0] != 1 && xs[0] != null)) throw AssertionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
booleanVararg(*booleanArrayOf(true))
|
||||||
|
booleanVararg(*BooleanArray(1))
|
||||||
|
booleanVararg(*BooleanArray(1) { true })
|
||||||
|
booleanVararg(xs = *booleanArrayOf(true))
|
||||||
|
booleanVararg(xs = *BooleanArray(1))
|
||||||
|
booleanVararg(xs = *BooleanArray(1) { true })
|
||||||
|
|
||||||
|
byteVararg(*byteArrayOf(1))
|
||||||
|
byteVararg(*ByteArray(1))
|
||||||
|
byteVararg(*ByteArray(1) { 1 })
|
||||||
|
byteVararg(xs = *byteArrayOf(1))
|
||||||
|
byteVararg(xs = *ByteArray(1))
|
||||||
|
byteVararg(xs = *ByteArray(1) { 1 })
|
||||||
|
|
||||||
|
shortVararg(*shortArrayOf(1))
|
||||||
|
shortVararg(*ShortArray(1))
|
||||||
|
shortVararg(*ShortArray(1) { 1 })
|
||||||
|
shortVararg(xs = *shortArrayOf(1))
|
||||||
|
shortVararg(xs = *ShortArray(1))
|
||||||
|
shortVararg(xs = *ShortArray(1) { 1 })
|
||||||
|
|
||||||
|
intVararg(*intArrayOf(1))
|
||||||
|
intVararg(*IntArray(1))
|
||||||
|
intVararg(*IntArray(1) { 1 })
|
||||||
|
intVararg(xs = *intArrayOf(1))
|
||||||
|
intVararg(xs = *IntArray(1))
|
||||||
|
intVararg(xs = *IntArray(1) { 1 })
|
||||||
|
|
||||||
|
longVararg(*longArrayOf(1L))
|
||||||
|
longVararg(*LongArray(1))
|
||||||
|
longVararg(*LongArray(1) { 1L })
|
||||||
|
longVararg(xs = *longArrayOf(1L))
|
||||||
|
longVararg(xs = *LongArray(1))
|
||||||
|
longVararg(xs = *LongArray(1) { 1L })
|
||||||
|
|
||||||
|
floatVararg(*floatArrayOf(1.0f))
|
||||||
|
floatVararg(*FloatArray(1))
|
||||||
|
floatVararg(*FloatArray(1) { 1.0f })
|
||||||
|
floatVararg(xs = *floatArrayOf(1.0f))
|
||||||
|
floatVararg(xs = *FloatArray(1))
|
||||||
|
floatVararg(xs = *FloatArray(1) { 1.0f })
|
||||||
|
|
||||||
|
doubleVararg(*doubleArrayOf(1.0))
|
||||||
|
doubleVararg(*DoubleArray(1))
|
||||||
|
doubleVararg(*DoubleArray(1) { 1.0 })
|
||||||
|
doubleVararg(xs = *doubleArrayOf(1.0))
|
||||||
|
doubleVararg(xs = *DoubleArray(1))
|
||||||
|
doubleVararg(xs = *DoubleArray(1) { 1.0 })
|
||||||
|
|
||||||
|
anyVararg(*arrayOf(1))
|
||||||
|
anyVararg(*Array(1) { 1 })
|
||||||
|
anyVararg(*arrayOfNulls(1))
|
||||||
|
anyVararg(xs = *arrayOf(1))
|
||||||
|
anyVararg(xs = *Array(1) { 1 })
|
||||||
|
anyVararg(xs = *arrayOfNulls(1))
|
||||||
|
|
||||||
|
genericVararg(*arrayOf(1))
|
||||||
|
genericVararg(*Array(1) { 1 })
|
||||||
|
genericVararg(*arrayOfNulls<Int>(1))
|
||||||
|
genericVararg(xs = *arrayOf(1))
|
||||||
|
genericVararg(xs = *Array(1) { 1 })
|
||||||
|
genericVararg(xs = *arrayOfNulls<Int>(1))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
fun booleanVararg(vararg xs: Boolean) {}
|
||||||
|
fun byteVararg(vararg xs: Byte) {}
|
||||||
|
fun shortVararg(vararg xs: Short) {}
|
||||||
|
fun intVararg(vararg xs: Int) {}
|
||||||
|
fun longVararg(vararg xs: Long) {}
|
||||||
|
fun floatVararg(vararg xs: Float) {}
|
||||||
|
fun doubleVararg(vararg xs: Double) {}
|
||||||
|
fun anyVararg(vararg xs: Any?) {}
|
||||||
|
fun <T> genericVararg(vararg xs: T) {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
booleanVararg(*booleanArrayOf(true))
|
||||||
|
booleanVararg(*BooleanArray(1))
|
||||||
|
booleanVararg(*BooleanArray(1) { true })
|
||||||
|
booleanVararg(xs = *booleanArrayOf(true))
|
||||||
|
booleanVararg(xs = *BooleanArray(1))
|
||||||
|
booleanVararg(xs = *BooleanArray(1) { true })
|
||||||
|
|
||||||
|
byteVararg(*byteArrayOf(1))
|
||||||
|
byteVararg(*ByteArray(1))
|
||||||
|
byteVararg(*ByteArray(1) { 1 })
|
||||||
|
byteVararg(xs = *byteArrayOf(1))
|
||||||
|
byteVararg(xs = *ByteArray(1))
|
||||||
|
byteVararg(xs = *ByteArray(1) { 1 })
|
||||||
|
|
||||||
|
shortVararg(*shortArrayOf(1))
|
||||||
|
shortVararg(*ShortArray(1))
|
||||||
|
shortVararg(*ShortArray(1) { 1 })
|
||||||
|
shortVararg(xs = *shortArrayOf(1))
|
||||||
|
shortVararg(xs = *ShortArray(1))
|
||||||
|
shortVararg(xs = *ShortArray(1) { 1 })
|
||||||
|
|
||||||
|
intVararg(*intArrayOf(1))
|
||||||
|
intVararg(*IntArray(1))
|
||||||
|
intVararg(*IntArray(1) { 1 })
|
||||||
|
intVararg(xs = *intArrayOf(1))
|
||||||
|
intVararg(xs = *IntArray(1))
|
||||||
|
intVararg(xs = *IntArray(1) { 1 })
|
||||||
|
|
||||||
|
longVararg(*longArrayOf(1L))
|
||||||
|
longVararg(*LongArray(1))
|
||||||
|
longVararg(*LongArray(1) { 1L })
|
||||||
|
longVararg(xs = *longArrayOf(1L))
|
||||||
|
longVararg(xs = *LongArray(1))
|
||||||
|
longVararg(xs = *LongArray(1) { 1L })
|
||||||
|
|
||||||
|
floatVararg(*floatArrayOf(1.0f))
|
||||||
|
floatVararg(*FloatArray(1))
|
||||||
|
floatVararg(*FloatArray(1) { 1.0f })
|
||||||
|
floatVararg(xs = *floatArrayOf(1.0f))
|
||||||
|
floatVararg(xs = *FloatArray(1))
|
||||||
|
floatVararg(xs = *FloatArray(1) { 1.0f })
|
||||||
|
|
||||||
|
doubleVararg(*doubleArrayOf(1.0))
|
||||||
|
doubleVararg(*DoubleArray(1))
|
||||||
|
doubleVararg(*DoubleArray(1) { 1.0 })
|
||||||
|
doubleVararg(xs = *doubleArrayOf(1.0))
|
||||||
|
doubleVararg(xs = *DoubleArray(1))
|
||||||
|
doubleVararg(xs = *DoubleArray(1) { 1.0 })
|
||||||
|
|
||||||
|
anyVararg(*arrayOf(1))
|
||||||
|
anyVararg(*Array(1) { 1 })
|
||||||
|
anyVararg(*arrayOfNulls(1))
|
||||||
|
anyVararg(xs = *arrayOf(1))
|
||||||
|
anyVararg(xs = *Array(1) { 1 })
|
||||||
|
anyVararg(xs = *arrayOfNulls(1))
|
||||||
|
|
||||||
|
genericVararg(*arrayOf(1))
|
||||||
|
genericVararg(*Array(1) { 1 })
|
||||||
|
genericVararg(*arrayOfNulls<Int>(1))
|
||||||
|
genericVararg(xs = *arrayOf(1))
|
||||||
|
genericVararg(xs = *Array(1) { 1 })
|
||||||
|
genericVararg(xs = *arrayOfNulls<Int>(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 copyOf
|
||||||
|
// 0 clone
|
||||||
+6
@@ -19688,6 +19688,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("doNotCopyImmediatelyCreatedArrays.kt")
|
||||||
|
public void testDoNotCopyImmediatelyCreatedArrays() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
||||||
|
|||||||
@@ -19688,6 +19688,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("doNotCopyImmediatelyCreatedArrays.kt")
|
||||||
|
public void testDoNotCopyImmediatelyCreatedArrays() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
||||||
|
|||||||
@@ -2202,6 +2202,21 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/bytecodeText/varargs")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Varargs extends AbstractBytecodeTextTest {
|
||||||
|
public void testAllFilesPresentInVarargs() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/varargs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("doNotCopyImmediatelyCreatedArrays.kt")
|
||||||
|
public void testDoNotCopyImmediatelyCreatedArrays() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/varargs/doNotCopyImmediatelyCreatedArrays.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/bytecodeText/when")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/when")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -19688,6 +19688,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("doNotCopyImmediatelyCreatedArrays.kt")
|
||||||
|
public void testDoNotCopyImmediatelyCreatedArrays() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
||||||
|
|||||||
@@ -23666,6 +23666,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("doNotCopyImmediatelyCreatedArrays.kt")
|
||||||
|
public void testDoNotCopyImmediatelyCreatedArrays() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/vararg/kt1978.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user