Code clean, small refactorings and tests
#KT-8987 Fixed
This commit is contained in:
@@ -16,25 +16,24 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
|
||||||
import org.jetbrains.kotlin.utils.mapToIndex
|
import org.jetbrains.kotlin.utils.mapToIndex
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ArgumentAndIndex(val arg: ResolvedValueArgument, val declIndex: Int, var type: Type? = null, var reorder: Boolean = false, var tempValue: StackValue? = null)
|
class ArgumentAndDeclIndex(val arg: ResolvedValueArgument, val declIndex: Int)
|
||||||
|
|
||||||
abstract class ArgumentGenerator {
|
abstract class ArgumentGenerator {
|
||||||
/**
|
/**
|
||||||
* @return a `List` of bit masks of default arguments that should be passed as last arguments to $default method, if there were
|
* @return a `List` of bit masks of default arguments that should be passed as last arguments to $default method, if there were
|
||||||
* * any default arguments, or an empty `List` if there were none
|
* any default arguments, or an empty `List` if there were none
|
||||||
* *
|
*
|
||||||
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
|
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
|
||||||
* @param valueArgumentsByIndex
|
|
||||||
* *
|
|
||||||
* @param actualArgs
|
|
||||||
*/
|
*/
|
||||||
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>, codegen: ExpressionCodegen): DefaultCallMask {
|
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallMask {
|
||||||
//HACK: see tempVariable in ExpressionCodegen
|
//HACK: see tempVariable in ExpressionCodegen
|
||||||
|
assert (valueArgumentsByIndex.size() == actualArgs.size())
|
||||||
val actualArguments = if (actualArgs.isNotEmpty()) actualArgs else valueArgumentsByIndex
|
val actualArguments = if (actualArgs.isNotEmpty()) actualArgs else valueArgumentsByIndex
|
||||||
|
|
||||||
assert(valueArgumentsByIndex.size() == actualArguments.size()) {
|
assert(valueArgumentsByIndex.size() == actualArguments.size()) {
|
||||||
@@ -43,24 +42,23 @@ abstract class ArgumentGenerator {
|
|||||||
|
|
||||||
val arg2Index = valueArgumentsByIndex.mapToIndex()
|
val arg2Index = valueArgumentsByIndex.mapToIndex()
|
||||||
|
|
||||||
val actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex> = ArrayList(actualArguments.filter { it !is DefaultValueArgument }.map {
|
val actualArgsWithDeclIndex = actualArguments.filter { it !is DefaultValueArgument }.map {
|
||||||
ArgumentAndIndex(it, arg2Index[it]!!)
|
ArgumentAndDeclIndex(it, arg2Index[it]!!)
|
||||||
})
|
}.toArrayList()
|
||||||
|
|
||||||
valueArgumentsByIndex.withIndex().forEach {
|
valueArgumentsByIndex.withIndex().forEach {
|
||||||
if (it.value is DefaultValueArgument) {
|
if (it.value is DefaultValueArgument) {
|
||||||
actualArgsWithDeclIndex.add(it.index, ArgumentAndIndex(it.value, it.index))
|
actualArgsWithDeclIndex.add(it.index, ArgumentAndDeclIndex(it.value, it.index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val masks = DefaultCallMask(valueArgumentsByIndex.size())
|
val masks = DefaultCallMask(valueArgumentsByIndex.size())
|
||||||
var orderChanged = false
|
|
||||||
|
|
||||||
for ((actualIndex, argumentWithDeclIndex) in actualArgsWithDeclIndex.withIndex()) {
|
for (argumentWithDeclIndex in actualArgsWithDeclIndex) {
|
||||||
val argument = argumentWithDeclIndex.arg
|
val argument = argumentWithDeclIndex.arg
|
||||||
val declIndex = argumentWithDeclIndex.declIndex
|
val declIndex = argumentWithDeclIndex.declIndex
|
||||||
|
|
||||||
argumentWithDeclIndex.type = when (argument) {
|
when (argument) {
|
||||||
is ExpressionValueArgument -> {
|
is ExpressionValueArgument -> {
|
||||||
generateExpression(declIndex, argument)
|
generateExpression(declIndex, argument)
|
||||||
}
|
}
|
||||||
@@ -75,11 +73,6 @@ abstract class ArgumentGenerator {
|
|||||||
generateOther(declIndex, argument)
|
generateOther(declIndex, argument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actualIndex != declIndex || orderChanged) {
|
|
||||||
orderChanged = true
|
|
||||||
argumentWithDeclIndex.reorder = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reorderArgumentsIfNeeded(actualArgsWithDeclIndex)
|
reorderArgumentsIfNeeded(actualArgsWithDeclIndex)
|
||||||
@@ -87,23 +80,23 @@ abstract class ArgumentGenerator {
|
|||||||
return masks
|
return masks
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun generateExpression(i: Int, argument: ExpressionValueArgument): Type {
|
protected open fun generateExpression(i: Int, argument: ExpressionValueArgument) {
|
||||||
throw UnsupportedOperationException("Unsupported expression value argument #$i: $argument")
|
throw UnsupportedOperationException("Unsupported expression value argument #$i: $argument")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun generateDefault(i: Int, argument: DefaultValueArgument): Type {
|
protected open fun generateDefault(i: Int, argument: DefaultValueArgument) {
|
||||||
throw UnsupportedOperationException("Unsupported default value argument #$i: $argument")
|
throw UnsupportedOperationException("Unsupported default value argument #$i: $argument")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun generateVararg(i: Int, argument: VarargValueArgument): Type {
|
protected open fun generateVararg(i: Int, argument: VarargValueArgument) {
|
||||||
throw UnsupportedOperationException("Unsupported vararg value argument #$i: $argument")
|
throw UnsupportedOperationException("Unsupported vararg value argument #$i: $argument")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun generateOther(i: Int, argument: ResolvedValueArgument): Type {
|
protected open fun generateOther(i: Int, argument: ResolvedValueArgument) {
|
||||||
throw UnsupportedOperationException("Unsupported value argument #$i: $argument")
|
throw UnsupportedOperationException("Unsupported value argument #$i: $argument")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun reorderArgumentsIfNeeded(args: ArrayList<ArgumentAndIndex>) {
|
protected open fun reorderArgumentsIfNeeded(args: List<ArgumentAndDeclIndex>) {
|
||||||
throw UnsupportedOperationException("Unsupported operation")
|
throw UnsupportedOperationException("Unsupported operation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.psi.ValueArgument;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.pushDefaultValueOnStack;
|
import static org.jetbrains.kotlin.codegen.AsmUtil.pushDefaultValueOnStack;
|
||||||
@@ -54,19 +53,17 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
|||||||
@Override
|
@Override
|
||||||
public DefaultCallMask generate(
|
public DefaultCallMask generate(
|
||||||
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
|
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
|
||||||
@NotNull List<? extends ResolvedValueArgument> valueArgs,
|
@NotNull List<? extends ResolvedValueArgument> valueArgs
|
||||||
@NotNull ExpressionCodegen codegen
|
|
||||||
) {
|
) {
|
||||||
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
|
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
|
||||||
this.codegen.setShouldMarkLineNumbers(false);
|
this.codegen.setShouldMarkLineNumbers(false);
|
||||||
DefaultCallMask masks = super.generate(valueArgumentsByIndex, valueArgs, codegen);
|
DefaultCallMask masks = super.generate(valueArgumentsByIndex, valueArgs);
|
||||||
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
|
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
|
||||||
return masks;
|
return masks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
protected Type generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
protected void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||||
Type type = valueParameterTypes.get(i);
|
Type type = valueParameterTypes.get(i);
|
||||||
ValueArgument valueArgument = argument.getValueArgument();
|
ValueArgument valueArgument = argument.getValueArgument();
|
||||||
@@ -74,31 +71,26 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
|||||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||||
assert argumentExpression != null : valueArgument.asElement().getText();
|
assert argumentExpression != null : valueArgument.asElement().getText();
|
||||||
callGenerator.genValueAndPut(parameter, argumentExpression, type, i);
|
callGenerator.genValueAndPut(parameter, argumentExpression, type, i);
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
protected Type generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
protected void generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||||
Type type = valueParameterTypes.get(i);
|
Type type = valueParameterTypes.get(i);
|
||||||
pushDefaultValueOnStack(type, codegen.v);
|
pushDefaultValueOnStack(type, codegen.v);
|
||||||
callGenerator.afterParameterPut(type, null, parameter, i);
|
callGenerator.afterParameterPut(type, null, parameter, i);
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
protected Type generateVararg(int i, @NotNull VarargValueArgument argument) {
|
protected void generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||||
Type type = valueParameterTypes.get(i);
|
Type type = valueParameterTypes.get(i);
|
||||||
codegen.genVarargs(argument, parameter.getType());
|
codegen.genVarargs(argument, parameter.getType());
|
||||||
callGenerator.afterParameterPut(type, null, parameter, i);
|
callGenerator.afterParameterPut(type, null, parameter, i);
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> actualArgsWithDeclIndex) {
|
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex) {
|
||||||
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex);
|
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex, valueParameterTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ import org.jetbrains.kotlin.psi.JetExpression
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
abstract class CallGenerator {
|
abstract class CallGenerator {
|
||||||
|
|
||||||
internal class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator() {
|
internal class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator() {
|
||||||
@@ -41,8 +39,8 @@ abstract class CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun genCallWithoutAssertions(
|
override fun genCallWithoutAssertions(
|
||||||
method: CallableMethod, codegen: ExpressionCodegen) {
|
callableMethod: CallableMethod, codegen: ExpressionCodegen) {
|
||||||
method.genInvokeInstruction(codegen.v)
|
callableMethod.genInvokeInstruction(codegen.v)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterParameterPut(
|
override fun afterParameterPut(
|
||||||
@@ -61,7 +59,7 @@ abstract class CallGenerator {
|
|||||||
valueParameterDescriptor: ValueParameterDescriptor,
|
valueParameterDescriptor: ValueParameterDescriptor,
|
||||||
argumentExpression: JetExpression,
|
argumentExpression: JetExpression,
|
||||||
parameterType: Type,
|
parameterType: Type,
|
||||||
index: Int) {
|
parameterIndex: Int) {
|
||||||
val value = codegen.gen(argumentExpression)
|
val value = codegen.gen(argumentExpression)
|
||||||
value.put(parameterType, codegen.v)
|
value.put(parameterType, codegen.v)
|
||||||
}
|
}
|
||||||
@@ -76,22 +74,23 @@ abstract class CallGenerator {
|
|||||||
value.put(value.type, codegen.v)
|
value.put(value.type, codegen.v)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex>) {
|
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) {
|
||||||
val mark = codegen.myFrameMap.mark()
|
val mark = codegen.myFrameMap.mark()
|
||||||
actualArgsWithDeclIndex.reversed().forEach {
|
val reordered = actualArgsWithDeclIndex.withIndex().dropWhile {
|
||||||
if (it.reorder) {
|
it.value.declIndex == it.index
|
||||||
val type = it.type!!
|
|
||||||
it.tempValue = StackValue.local(codegen.frameMap.enterTemp(type), type)
|
|
||||||
it.tempValue?.store(StackValue.onStack(type), codegen.v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actualArgsWithDeclIndex.sortedBy { it.declIndex }.forEach {
|
reordered.reversed().map {
|
||||||
it.tempValue?.let {
|
val argumentAndDeclIndex = it.value
|
||||||
it.put(it.type, codegen.v)
|
val type = valueParameterTypes.get(argumentAndDeclIndex.declIndex)
|
||||||
}
|
val stackValue = StackValue.local(codegen.frameMap.enterTemp(type), type)
|
||||||
|
stackValue.store(StackValue.onStack(type), codegen.v)
|
||||||
|
Pair(argumentAndDeclIndex.declIndex, stackValue)
|
||||||
|
}.sortedBy {
|
||||||
|
it.first
|
||||||
|
}.forEach {
|
||||||
|
it.second.put(valueParameterTypes.get(it.first), codegen.v)
|
||||||
}
|
}
|
||||||
|
|
||||||
mark.dropTo()
|
mark.dropTo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,5 +133,5 @@ abstract class CallGenerator {
|
|||||||
|
|
||||||
abstract fun putHiddenParams()
|
abstract fun putHiddenParams()
|
||||||
|
|
||||||
abstract fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex>)
|
abstract fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1486,7 +1486,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
ArgumentGenerator argumentGenerator =
|
ArgumentGenerator argumentGenerator =
|
||||||
new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes);
|
new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes);
|
||||||
|
|
||||||
argumentGenerator.generate(valueArguments, valueArguments, ExpressionCodegen.this);
|
argumentGenerator.generate(valueArguments, valueArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
|
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
|
||||||
@@ -2455,7 +2455,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
|
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
|
||||||
|
|
||||||
List<Integer> masks =
|
List<Integer> masks =
|
||||||
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()), this)
|
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()))
|
||||||
.toInts();
|
.toInts();
|
||||||
|
|
||||||
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
|
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
|
||||||
|
|||||||
@@ -1643,35 +1643,30 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
this.offset = firstValueParamOffset;
|
this.offset = firstValueParamOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Type generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
public void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||||
return generateSuperCallArgument(i);
|
generateSuperCallArgument(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Type generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
public void generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||||
Type type = parameters.get(i).getAsmType();
|
Type type = parameters.get(i).getAsmType();
|
||||||
pushDefaultValueOnStack(type, iv);
|
pushDefaultValueOnStack(type, iv);
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Type generateVararg(int i, @NotNull VarargValueArgument argument) {
|
public void generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||||
return generateSuperCallArgument(i);
|
generateSuperCallArgument(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type generateSuperCallArgument(int i) {
|
private void generateSuperCallArgument(int i) {
|
||||||
Type type = parameters.get(i).getAsmType();
|
Type type = parameters.get(i).getAsmType();
|
||||||
iv.load(offset, type);
|
iv.load(offset, type);
|
||||||
offset += type.getSize();
|
offset += type.getSize();
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> args) {
|
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> args) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -769,7 +769,7 @@ public abstract class StackValue {
|
|||||||
ResolvedCall<?> call = isGetter ? resolvedGetCall : resolvedSetCall;
|
ResolvedCall<?> call = isGetter ? resolvedGetCall : resolvedSetCall;
|
||||||
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
|
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
|
||||||
newReceiver.put(newReceiver.type, v);
|
newReceiver.put(newReceiver.type, v);
|
||||||
argumentGenerator.generate(valueArguments, valueArguments, codegen);
|
argumentGenerator.generate(valueArguments, valueArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -520,8 +520,8 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
invocationParamBuilder.markValueParametesStart();
|
invocationParamBuilder.markValueParametesStart();
|
||||||
List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured();
|
List<ParameterInfo> hiddenParameters = invocationParamBuilder.buildParameters().getReal();
|
||||||
recordParameterValueInLocalVal(infos.toArray(new ParameterInfo[infos.size()]));
|
recordParameterValueInLocalVal(hiddenParameters.toArray(new ParameterInfo[hiddenParameters.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void leaveTemps() {
|
public void leaveTemps() {
|
||||||
@@ -772,7 +772,9 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> actualArgsWithDeclIndex) {
|
public void reorderArgumentsIfNeeded(
|
||||||
|
@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex, @NotNull List<? extends Type> valueParameterTypes
|
||||||
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import static org.jetbrains.kotlin.codegen.inline.LocalVarRemapper.RemapStatus.*
|
|||||||
|
|
||||||
public class LocalVarRemapper {
|
public class LocalVarRemapper {
|
||||||
|
|
||||||
private final int allParamsSize;
|
|
||||||
private final Parameters params;
|
private final Parameters params;
|
||||||
private final int actualParamsSize;
|
private final int actualParamsSize;
|
||||||
|
|
||||||
@@ -38,36 +37,19 @@ public class LocalVarRemapper {
|
|||||||
|
|
||||||
public LocalVarRemapper(Parameters params, int additionalShift) {
|
public LocalVarRemapper(Parameters params, int additionalShift) {
|
||||||
this.additionalShift = additionalShift;
|
this.additionalShift = additionalShift;
|
||||||
this.allParamsSize = params.getArgsSizeOnStack();
|
|
||||||
this.params = params;
|
this.params = params;
|
||||||
|
|
||||||
remapValues = new StackValue [params.getArgsSizeOnStack()];
|
remapValues = new StackValue [params.getArgsSizeOnStack()];
|
||||||
Integer [] declIndexesToActual = new Integer [params.getArgsSizeOnStack()];
|
|
||||||
Integer [] actualDeclShifts = new Integer [params.getArgsSizeOnStack()];
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
for (ParameterInfo param : params) {
|
|
||||||
declIndexesToActual[param.declarationIndex] = index;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int realSize = 0;
|
int realSize = 0;
|
||||||
for (int i = 0; i < declIndexesToActual.length; i++) {
|
|
||||||
Integer declIndexToActual = declIndexesToActual[i];
|
|
||||||
if (declIndexToActual != null) {
|
|
||||||
actualDeclShifts[i] = realSize;
|
|
||||||
realSize += params.get(declIndexToActual).getType().getSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
realSize = 0;
|
|
||||||
for (ParameterInfo info : params) {
|
for (ParameterInfo info : params) {
|
||||||
|
Integer shift = params.getDeclarationSlot(info);
|
||||||
if (!info.isSkippedOrRemapped()) {
|
if (!info.isSkippedOrRemapped()) {
|
||||||
remapValues[actualDeclShifts[info.declarationIndex]] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE);
|
remapValues[shift] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE);
|
||||||
realSize += info.getType().getSize();
|
realSize += info.getType().getSize();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
remapValues[actualDeclShifts[info.declarationIndex]] = info.isRemapped() ? info.getRemapValue() : null;
|
remapValues[shift] = info.isRemapped() ? info.getRemapValue() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +59,8 @@ public class LocalVarRemapper {
|
|||||||
public RemapInfo doRemap(int index) {
|
public RemapInfo doRemap(int index) {
|
||||||
int remappedIndex;
|
int remappedIndex;
|
||||||
|
|
||||||
if (index < allParamsSize) {
|
if (index < params.getArgsSizeOnStack()) {
|
||||||
ParameterInfo info = params.getByByteCodeIndex(index);
|
ParameterInfo info = params.getParameterByDeclarationSlot(index);
|
||||||
StackValue remapped = remapValues[index];
|
StackValue remapped = remapValues[index];
|
||||||
if (info.isSkipped || remapped == null) {
|
if (info.isSkipped || remapped == null) {
|
||||||
return new RemapInfo(info);
|
return new RemapInfo(info);
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ public class MethodInliner {
|
|||||||
Type[] types = Type.getArgumentTypes(node.desc);
|
Type[] types = Type.getArgumentTypes(node.desc);
|
||||||
Type returnType = Type.getReturnType(node.desc);
|
Type returnType = Type.getReturnType(node.desc);
|
||||||
|
|
||||||
ArrayList<Type> capturedTypes = parameters.getCapturedTypes();
|
List<Type> capturedTypes = parameters.getCapturedTypes();
|
||||||
Type[] allTypes = ArrayUtil.mergeArrays(types, capturedTypes.toArray(new Type[capturedTypes.size()]));
|
Type[] allTypes = ArrayUtil.mergeArrays(types, capturedTypes.toArray(new Type[capturedTypes.size()]));
|
||||||
|
|
||||||
node.instructions.resetLabels();
|
node.instructions.resetLabels();
|
||||||
@@ -559,7 +559,7 @@ public class MethodInliner {
|
|||||||
|
|
||||||
private LambdaInfo getLambdaIfExists(int varIndex) {
|
private LambdaInfo getLambdaIfExists(int varIndex) {
|
||||||
if (varIndex < parameters.getArgsSizeOnStack()) {
|
if (varIndex < parameters.getArgsSizeOnStack()) {
|
||||||
return parameters.getByByteCodeIndex(varIndex).getLambda();
|
return parameters.getParameterByDeclarationSlot(varIndex).getLambda();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,24 +16,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
import com.google.common.collect.Iterables
|
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
//All parameters with gaps
|
|
||||||
class Parameters(val real: List<ParameterInfo>, val captured: List<CapturedParamInfo>) : Iterable<ParameterInfo> {
|
class Parameters(val real: List<ParameterInfo>, val captured: List<CapturedParamInfo>) : Iterable<ParameterInfo> {
|
||||||
|
|
||||||
private val declIndexesToActual: Array<Int?>
|
|
||||||
private val actualDeclShifts: Array<ParameterInfo?>
|
private val actualDeclShifts: Array<ParameterInfo?>
|
||||||
|
private val paramToDeclByteCodeIndex: HashMap<ParameterInfo, Int> = hashMapOf()
|
||||||
|
|
||||||
public val realArgsSizeOnStack = real.fold(0, { a, v -> a + v.type.size})
|
public val realArgsSizeOnStack = real.sumBy { it.type.size }
|
||||||
public val capturedArgsSizeOnStack = captured.fold(0, { a, v -> a + v.type.size})
|
public val capturedArgsSizeOnStack = captured.sumBy { it.type.size }
|
||||||
|
|
||||||
public val argsSizeOnStack = realArgsSizeOnStack + capturedArgsSizeOnStack
|
public val argsSizeOnStack = realArgsSizeOnStack + capturedArgsSizeOnStack
|
||||||
|
|
||||||
init {
|
init {
|
||||||
declIndexesToActual = arrayOfNulls<Int>(argsSizeOnStack)
|
val declIndexesToActual = arrayOfNulls<Int>(argsSizeOnStack)
|
||||||
withIndex().forEach { it ->
|
withIndex().forEach { it ->
|
||||||
declIndexesToActual[it.value.declarationIndex] = it.index
|
declIndexesToActual[it.value.declarationIndex] = it.index
|
||||||
}
|
}
|
||||||
@@ -41,27 +38,22 @@ class Parameters(val real: List<ParameterInfo>, val captured: List<CapturedParam
|
|||||||
actualDeclShifts = arrayOfNulls<ParameterInfo>(argsSizeOnStack)
|
actualDeclShifts = arrayOfNulls<ParameterInfo>(argsSizeOnStack)
|
||||||
var realSize = 0
|
var realSize = 0
|
||||||
for (i in declIndexesToActual.indices) {
|
for (i in declIndexesToActual.indices) {
|
||||||
val declIndexToActual = declIndexesToActual[i]
|
val byDeclarationIndex = get(declIndexesToActual[i] ?: continue)
|
||||||
if (declIndexToActual != null) {
|
actualDeclShifts[realSize] = byDeclarationIndex
|
||||||
val byDeclarationIndex = getByDeclarationIndex(i)
|
paramToDeclByteCodeIndex.put(byDeclarationIndex, realSize)
|
||||||
actualDeclShifts[realSize] = byDeclarationIndex
|
realSize += byDeclarationIndex.type.size
|
||||||
realSize += byDeclarationIndex.type.size
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getByDeclarationIndex(index: Int): ParameterInfo {
|
fun getDeclarationSlot(info : ParameterInfo): Int {
|
||||||
if (index < realArgsSizeOnStack) {
|
return paramToDeclByteCodeIndex[info]!!
|
||||||
return real.get(declIndexesToActual[index]!!)
|
|
||||||
}
|
|
||||||
return captured.get(declIndexesToActual[index]!! - real.size())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getByByteCodeIndex(index: Int): ParameterInfo {
|
fun getParameterByDeclarationSlot(index: Int): ParameterInfo {
|
||||||
return actualDeclShifts[index]!!
|
return actualDeclShifts[index]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(index: Int): ParameterInfo {
|
private fun get(index: Int): ParameterInfo {
|
||||||
if (index < real.size()) {
|
if (index < real.size()) {
|
||||||
return real.get(index)
|
return real.get(index)
|
||||||
}
|
}
|
||||||
@@ -69,26 +61,17 @@ class Parameters(val real: List<ParameterInfo>, val captured: List<CapturedParam
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun iterator(): Iterator<ParameterInfo> {
|
override fun iterator(): Iterator<ParameterInfo> {
|
||||||
return Iterables.concat(real, captured).iterator()
|
return (real + captured).iterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
val capturedTypes: ArrayList<Type>
|
val capturedTypes: List<Type>
|
||||||
get() {
|
get() = captured.map {
|
||||||
val result = ArrayList<Type>()
|
it.getType()
|
||||||
for (info in captured) {
|
|
||||||
result.add(info.getType())
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun shift(capturedParams: List<CapturedParamInfo>, realSize: Int): List<CapturedParamInfo> {
|
fun shift(capturedParams: List<CapturedParamInfo>, realSize: Int): List<CapturedParamInfo> {
|
||||||
val result = ArrayList<CapturedParamInfo>()
|
return capturedParams.withIndex().map { it.value.newIndex(it.index+ realSize) }
|
||||||
for (capturedParamInfo in capturedParams) {
|
|
||||||
val newInfo = capturedParamInfo.newIndex(result.size() + realSize)
|
|
||||||
result.add(newInfo)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,10 +100,6 @@ class ParametersBuilder private constructor(){
|
|||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
fun listNotCaptured(): List<ParameterInfo> {
|
|
||||||
return Collections.unmodifiableList(valueAndHiddenParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun markValueParametesStart(){
|
fun markValueParametesStart(){
|
||||||
this.valueParamStart = valueAndHiddenParams.size()
|
this.valueParamStart = valueAndHiddenParams.size()
|
||||||
}
|
}
|
||||||
@@ -118,7 +114,7 @@ class ParametersBuilder private constructor(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun buildParameters(): Parameters {
|
fun buildParameters(): Parameters {
|
||||||
return Parameters(listNotCaptured(), Parameters.shift(listCaptured(), nextValueParameterIndex))
|
return Parameters(Collections.unmodifiableList(valueAndHiddenParams), Parameters.shift(listCaptured(), nextValueParameterIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
fun box(): String {
|
||||||
|
var invokeOrder = "";
|
||||||
|
val expectedResult = "0_1_9"
|
||||||
|
val expectedInvokeOrder = "1_0_9"
|
||||||
|
var l = 1L
|
||||||
|
var i = 0
|
||||||
|
val captured = 9L
|
||||||
|
|
||||||
|
var result = test(b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "$captured"; "$captured"})
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = test(b = {invokeOrder += "1_"; l}(), c = {invokeOrder += "$captured"; "$captured"}, a = {invokeOrder+="0_"; i}())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = test(c = {invokeOrder += "$captured"; "$captured"}, b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = test(a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "$captured"; "$captured"}, b = {invokeOrder += "1_"; l}())
|
||||||
|
if (invokeOrder != "0_1_9" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_9 or $result != $expectedResult"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(a: Int, b: Long, c: () -> String): String {
|
||||||
|
return { "${a}_${b}_${c()}"} ()
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
fun box(): String {
|
||||||
|
var invokeOrder = "";
|
||||||
|
val expectedResult = "1.0_0_1_9"
|
||||||
|
val expectedInvokeOrder = "1_0_9"
|
||||||
|
var l = 1L
|
||||||
|
var i = 0
|
||||||
|
val captured = 9L
|
||||||
|
|
||||||
|
var result = 1.0.test(b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "$captured"; "$captured"})
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(b = {invokeOrder += "1_"; l}(), c = {invokeOrder += "${captured}"; "${captured}"}, a = {invokeOrder+="0_"; i}())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(c = {invokeOrder += "${captured}"; "${captured}"}, b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "${captured}"; "${captured}"}, b = {invokeOrder += "1_"; l}())
|
||||||
|
if (invokeOrder != "0_1_9" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_9 or $result != $expectedResult"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Double.test(a: Int, b: Long, c: () -> String): String {
|
||||||
|
return { "${this}_${a}_${b}_${c()}"} ()
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
var invokeOrder: String = ""
|
||||||
|
|
||||||
|
fun test(x: Double = { invokeOrder += "x"; 1.0 }(), a: String, y: Long = { invokeOrder += "y"; 1 }(), b: String): String {
|
||||||
|
return "" + x + a + b + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val funResult = test(b = { invokeOrder += "K"; "K" }(), a = { invokeOrder += "O"; "O" }())
|
||||||
|
|
||||||
|
if (invokeOrder != "KOxy" || funResult != "1.0OK1") return "fail: $invokeOrder != KOxy or $funResult != 1.0OK1"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
fun box(): String {
|
||||||
|
var invokeOrder = "";
|
||||||
|
val expectedResult = "1.0_0_1_L"
|
||||||
|
val expectedInvokeOrder = "1_0_L"
|
||||||
|
var l = 1L
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
var result = 1.0.test(b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "L"; "L"})
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(b = {invokeOrder += "1_"; l}(), c = {invokeOrder += "L"; "L"}, a = {invokeOrder+="0_"; i}())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(c = {invokeOrder += "L"; "L"}, b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "L"; "L"}, b = {invokeOrder += "1_"; l}())
|
||||||
|
if (invokeOrder != "0_1_L" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_L or $result != $expectedResult"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Double.test(a: Int, b: Long, c: () -> String): String {
|
||||||
|
return "${this}_${a}_${b}_${c()}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
fun box(): String {
|
||||||
|
return Z().test()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Z {
|
||||||
|
fun Double.test(a: Int, b: Long, c: () -> String): String {
|
||||||
|
return "${this}_${a}_${b}_${c()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun test(): String {
|
||||||
|
var invokeOrder = "";
|
||||||
|
val expectedResult = "1.0_0_1_L"
|
||||||
|
val expectedInvokeOrder = "1_0_L"
|
||||||
|
var l = 1L
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
var result = 1.0.test(b = { invokeOrder += "1_"; l }(), a = { invokeOrder += "0_"; i }(), c = { invokeOrder += "L"; "L" })
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(b = { invokeOrder += "1_"; l }(), c = { invokeOrder += "L"; "L" }, a = { invokeOrder += "0_"; i }())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(c = { invokeOrder += "L"; "L" }, b = { invokeOrder += "1_"; l }(), a = { invokeOrder += "0_"; i }())
|
||||||
|
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||||
|
|
||||||
|
|
||||||
|
invokeOrder = "";
|
||||||
|
result = 1.0.test(a = { invokeOrder += "0_"; i }(), c = { invokeOrder += "L"; "L" }, b = { invokeOrder += "1_"; l }())
|
||||||
|
if (invokeOrder != "0_1_L" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_L or $result != $expectedResult"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
fun box(): String {
|
||||||
|
var res = "";
|
||||||
|
var call = test(a = {res += "K"; "K"}(), b = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||||
|
if (res != "KOL" || call != "KOL") return "fail 1: $res != KOL or $call != KOL"
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = test(a = {res += "K"; "K"}(), c = {res += "L"; "L"}, b = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "KOL") return "fail 2: $res != KOL or $call != KOL"
|
||||||
|
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = test(c = {res += "L"; "L"}, a = {res += "K"; "K"}(), b = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "KOL") return "fail 3: $res != KOL or $call != KOL"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(a: String, b: String, c: () -> String): String {
|
||||||
|
return a + b + c();
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
fun box(): String {
|
||||||
|
var res = "";
|
||||||
|
var call = Z("Z").test(a = {res += "K"; "K"}(), b = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||||
|
if (res != "KOL" || call != "KOLZ") return "fail 1: $res != KOL or $call != KOLZ"
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = Z("Z").test(a = {res += "K"; "K"}(), c = {res += "L"; "L"}, b = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "KOLZ") return "fail 2: $res != KOL or $call != KOLZ"
|
||||||
|
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = Z("Z").test(c = {res += "L"; "L"}, a = {res += "K"; "K"}(), b = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "KOLZ") return "fail 3: $res != KOL or $call != KOLZ"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Z(val p: String) {
|
||||||
|
|
||||||
|
fun test(a: String, b: String, c: () -> String): String {
|
||||||
|
return a + b + c() + p;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
fun box(): String {
|
||||||
|
var res = "";
|
||||||
|
var call = test(b = {res += "K"; "K"}(), a = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||||
|
if (res != "KOL" || call != "OKL") return "fail 1: $res != KOL or $call != OKL"
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = test(b = {res += "K"; "K"}(), c = {res += "L"; "L"}, a = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "OKL") return "fail 2: $res != KOL or $call != OKL"
|
||||||
|
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = test(c = {res += "L"; "L"}, b = {res += "K"; "K"}(), a = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "OKL") return "fail 3: $res != KOL or $call != OKL"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(a: String, b: String, c: () -> String): String {
|
||||||
|
return a + b + c();
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
fun box(): String {
|
||||||
|
var res = "";
|
||||||
|
var call = Z("Z").test(b = {res += "K"; "K"}(), a = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||||
|
if (res != "KOL" || call != "OKLZ") return "fail 1: $res != KOL or $call != OKLZ"
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = Z("Z").test(b = {res += "K"; "K"}(), c = {res += "L"; "L"}, a = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "OKLZ") return "fail 2: $res != KOL or $call != OKLZ"
|
||||||
|
|
||||||
|
|
||||||
|
res = "";
|
||||||
|
call = Z("Z").test(c = {res += "L"; "L"}, b = {res += "K"; "K"}(), a = {res+="O"; "O"}())
|
||||||
|
if (res != "KOL" || call != "OKLZ") return "fail 3: $res != KOL or $call != OKLZ"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Z(val p: String) {
|
||||||
|
fun test(a: String, b: String, c: () -> String): String {
|
||||||
|
return a + b + c() + p;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
class A {
|
||||||
|
fun test(x: String?, a: String?, b: String?){}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(x = "x", b = "K", a = "O")
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test argument reordering when call site argument order differs from declaration one
|
||||||
|
// 4 LOAD
|
||||||
|
// 2 STORE
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
class A {
|
||||||
|
fun test(x: String? = "x", a: String?, b: String?, y: String? = "y") {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(b = "K", a = "O")
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test argument reordering when call site argument order differs from declaration one
|
||||||
|
// 12 LOAD
|
||||||
|
// 5 STORE
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
class A {
|
||||||
|
fun test(x: String?, a: String?, b: String?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(x = "x", a = "O", b = "K")
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test there is no argument reordering when call site argument order same as declaration one
|
||||||
|
// 2 LOAD
|
||||||
|
// 0 STORE
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
class A {
|
||||||
|
fun test(x: String? = "x", a: String?, b: String?, y: String? = "y") {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(a = "O", b = "K")
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test there is no argument reordering when call site argument order same as declaration one
|
||||||
|
// 9 LOAD
|
||||||
|
// 2 STORE
|
||||||
@@ -251,6 +251,39 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/bytecodeText/argumentOrder")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ArgumentOrder extends AbstractBytecodeTextTest {
|
||||||
|
public void testAllFilesPresentInArgumentOrder() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/argumentOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("argumentReorder.kt")
|
||||||
|
public void testArgumentReorder() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/argumentReorder.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("argumentReorderWithDefault.kt")
|
||||||
|
public void testArgumentReorderWithDefault() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/argumentReorderWithDefault.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sameOrder.kt")
|
||||||
|
public void testSameOrder() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/sameOrder.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sameOrderWithDefault.kt")
|
||||||
|
public void testSameOrderWithDefault() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/sameOrderWithDefault.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+54
@@ -48,6 +48,60 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/arguments.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/arguments.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("captured.kt")
|
||||||
|
public void testCaptured() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/captured.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("capturedInExtension.kt")
|
||||||
|
public void testCapturedInExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/capturedInExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaults.kt")
|
||||||
|
public void testDefaults() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/defaults.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extension.kt")
|
||||||
|
public void testExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/extension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionInClass.kt")
|
||||||
|
public void testExtensionInClass() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/extensionInClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaMigration.kt")
|
||||||
|
public void testLambdaMigration() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/lambdaMigration.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaMigrationInClass.kt")
|
||||||
|
public void testLambdaMigrationInClass() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/lambdaMigrationInClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleInClass.kt")
|
||||||
|
public void testSimpleInClass() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/simpleInClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/arrays")
|
@TestMetadata("compiler/testData/codegen/box/arrays")
|
||||||
|
|||||||
Reference in New Issue
Block a user