Do not copy immediately created arrays in spread arguments

E.g., 'foo(x = *intArrayOf(42))'.

 #KT-20462 Fixed
This commit is contained in:
Dmitry Petrov
2017-09-27 16:14:09 +03:00
parent 0d5a2a7e18
commit 73724bcdc7
8 changed files with 234 additions and 4 deletions
@@ -2656,6 +2656,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
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
public StackValue genVarargs(@NotNull VarargValueArgument valueArgument, @NotNull KotlinType outType) {
@@ -2678,10 +2687,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (size == 1) {
Type arrayType = getArrayType(arrayOfReferences ? AsmTypes.OBJECT_TYPE : elementType);
return StackValue.operation(type, adapter -> {
gen(arguments.get(0).getArgumentExpression(), type);
v.dup();
v.arraylength();
v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false);
KtExpression spreadArgument = arguments.get(0).getArgumentExpression();
gen(spreadArgument, type);
if (!canSkipArrayCopyForSpreadArgument(spreadArgument)) {
v.dup();
v.arraylength();
v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false);
}
if (arrayOfReferences) {
v.checkcast(type);
}