First implementation of proper agrument order
This commit is contained in:
@@ -16,14 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
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.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.utils.mapToIndex
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
private class ArgumentAndIndex(val arg: ResolvedValueArgument, val declIndex: Int, var type: Type? = null, var reoder: Boolean = false, var tempValue: StackValue? = null)
|
||||
|
||||
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
|
||||
@@ -34,7 +33,7 @@ abstract class ArgumentGenerator {
|
||||
* *
|
||||
* @param actualArgs
|
||||
*/
|
||||
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallMask {
|
||||
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>, codegen: ExpressionCodegen): DefaultCallMask {
|
||||
//HACK: see tempVariable in ExpressionCodegen
|
||||
val actualArguments = if (actualArgs.isNotEmpty()) actualArgs else valueArgumentsByIndex
|
||||
|
||||
@@ -44,29 +43,61 @@ abstract class ArgumentGenerator {
|
||||
|
||||
val arg2Index = valueArgumentsByIndex.mapToIndex()
|
||||
|
||||
val masks = DefaultCallMask(valueArgumentsByIndex.size())
|
||||
for ((index, argument) in valueArgumentsByIndex.withIndex()) {
|
||||
//var i = arg2Index[argument]!!
|
||||
var i = index
|
||||
val actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex> = ArrayList(actualArguments.filter { it !is DefaultValueArgument }.map {
|
||||
ArgumentAndIndex(it, arg2Index[it]!!)
|
||||
})
|
||||
|
||||
var type = when (argument) {
|
||||
valueArgumentsByIndex.withIndex().forEach {
|
||||
if (it.value is DefaultValueArgument) {
|
||||
actualArgsWithDeclIndex.add(it.index, ArgumentAndIndex(it.value, it.index))
|
||||
}
|
||||
}
|
||||
|
||||
val masks = DefaultCallMask(valueArgumentsByIndex.size())
|
||||
var orderChanged = false
|
||||
|
||||
for ((actualIndex, argumentWithDeclIndex) in actualArgsWithDeclIndex.withIndex()) {
|
||||
val argument = argumentWithDeclIndex.arg
|
||||
val declIndex = argumentWithDeclIndex.declIndex
|
||||
|
||||
argumentWithDeclIndex.type = when (argument) {
|
||||
is ExpressionValueArgument -> {
|
||||
generateExpression(i, argument)
|
||||
generateExpression(declIndex, argument)
|
||||
}
|
||||
is DefaultValueArgument -> {
|
||||
masks.mark(i)
|
||||
generateDefault(i, argument)
|
||||
masks.mark(declIndex)
|
||||
generateDefault(declIndex, argument)
|
||||
}
|
||||
is VarargValueArgument -> {
|
||||
generateVararg(i, argument)
|
||||
generateVararg(declIndex, argument)
|
||||
}
|
||||
else -> {
|
||||
generateOther(i, argument)
|
||||
generateOther(declIndex, argument)
|
||||
}
|
||||
}
|
||||
|
||||
if (actualIndex != declIndex || orderChanged) {
|
||||
orderChanged = true
|
||||
argumentWithDeclIndex.reoder = true
|
||||
}
|
||||
}
|
||||
|
||||
val mark = codegen.myFrameMap.mark()
|
||||
actualArgsWithDeclIndex.reversed().forEach {
|
||||
if (it.reoder) {
|
||||
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 {
|
||||
it.tempValue?.let {
|
||||
it.put(it.type, codegen.v)
|
||||
}
|
||||
}
|
||||
|
||||
mark.dropTo()
|
||||
return masks
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.psi.JetExpression;
|
||||
import org.jetbrains.kotlin.psi.ValueArgument;
|
||||
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.resolve.calls.model.*;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.List;
|
||||
@@ -51,13 +48,18 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
"Value parameters and their types mismatch in sizes: " + valueParameters.size() + " != " + valueParameterTypes.size();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DefaultCallMask generate(@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex, @NotNull List<? extends ResolvedValueArgument> valueArgs) {
|
||||
boolean shouldMarkLineNumbers = codegen.isShouldMarkLineNumbers();
|
||||
codegen.setShouldMarkLineNumbers(false);
|
||||
DefaultCallMask masks = super.generate(valueArgumentsByIndex, valueArgs);
|
||||
codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
|
||||
public DefaultCallMask generate(
|
||||
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
|
||||
@NotNull List<? extends ResolvedValueArgument> valueArgs,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
|
||||
this.codegen.setShouldMarkLineNumbers(false);
|
||||
DefaultCallMask masks = super.generate(valueArgumentsByIndex, valueArgs, codegen);
|
||||
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
|
||||
return masks;
|
||||
}
|
||||
|
||||
|
||||
@@ -1486,7 +1486,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
ArgumentGenerator argumentGenerator =
|
||||
new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes);
|
||||
|
||||
argumentGenerator.generate(valueArguments, valueArguments);
|
||||
argumentGenerator.generate(valueArguments, valueArguments, ExpressionCodegen.this);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
List<Integer> masks =
|
||||
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()))
|
||||
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()), this)
|
||||
.toInts();
|
||||
|
||||
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
|
||||
|
||||
@@ -1643,11 +1643,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
this.offset = firstValueParamOffset;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Type generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||
return generateSuperCallArgument(i);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Type generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
Type type = parameters.get(i).getAsmType();
|
||||
@@ -1655,6 +1657,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Type generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||
return generateSuperCallArgument(i);
|
||||
|
||||
@@ -769,7 +769,7 @@ public abstract class StackValue {
|
||||
ResolvedCall<?> call = isGetter ? resolvedGetCall : resolvedSetCall;
|
||||
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
|
||||
newReceiver.put(newReceiver.type, v);
|
||||
argumentGenerator.generate(valueArguments, valueArguments);
|
||||
argumentGenerator.generate(valueArguments, valueArguments, codegen);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
@@ -84,8 +83,8 @@ public class InlineCodegen extends CallGenerator {
|
||||
private final int initialFrameSize;
|
||||
private final boolean isSameModule;
|
||||
|
||||
protected final ParametersBuilder invocationParamBuilder = ParametersBuilder.newBuilder();
|
||||
protected final Map<Integer, LambdaInfo> expressionMap = new HashMap<Integer, LambdaInfo>();
|
||||
private final ParametersBuilder invocationParamBuilder = ParametersBuilder.newBuilder();
|
||||
private final Map<Integer, LambdaInfo> expressionMap = new HashMap<Integer, LambdaInfo>();
|
||||
|
||||
private final ReifiedTypeInliner reifiedTypeInliner;
|
||||
|
||||
@@ -116,7 +115,6 @@ public class InlineCodegen extends CallGenerator {
|
||||
jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());
|
||||
|
||||
// TODO: implement AS_FUNCTION inline strategy
|
||||
InlineStrategy inlineStrategy = InlineUtil.getInlineStrategy(functionDescriptor);
|
||||
this.asFunctionInline = false;
|
||||
|
||||
isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory());
|
||||
@@ -413,15 +411,17 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
@Override
|
||||
public void afterParameterPut(@NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor) {
|
||||
putCapturedInLocal(type, stackValue, valueParameterDescriptor, -1);
|
||||
putArgumentOrCapturedToLocalVal(type, stackValue, -1);
|
||||
}
|
||||
|
||||
private void putCapturedInLocal(
|
||||
@NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor, int capturedParamIndex
|
||||
private void putArgumentOrCapturedToLocalVal(
|
||||
@NotNull Type type,
|
||||
@Nullable StackValue stackValue,
|
||||
int capturedParamIndex
|
||||
) {
|
||||
if (!asFunctionInline && Type.VOID_TYPE != type) {
|
||||
//TODO remap only inlinable closure => otherwise we could get a lot of problem
|
||||
boolean couldBeRemapped = !shouldPutValue(type, stackValue, valueParameterDescriptor);
|
||||
boolean couldBeRemapped = !shouldPutValue(type, stackValue);
|
||||
StackValue remappedIndex = couldBeRemapped ? stackValue : null;
|
||||
|
||||
ParameterInfo info;
|
||||
@@ -434,15 +434,14 @@ public class InlineCodegen extends CallGenerator {
|
||||
info = invocationParamBuilder.addNextParameter(type, false, remappedIndex);
|
||||
}
|
||||
|
||||
putParameterOnStack(info);
|
||||
recordParameterValueInLocalVal(info);
|
||||
}
|
||||
}
|
||||
|
||||
/*descriptor is null for captured vars*/
|
||||
public boolean shouldPutValue(
|
||||
public static boolean shouldPutValue(
|
||||
@NotNull Type type,
|
||||
@Nullable StackValue stackValue,
|
||||
@Nullable ValueParameterDescriptor descriptor
|
||||
@Nullable StackValue stackValue
|
||||
) {
|
||||
|
||||
if (stackValue == null) {
|
||||
@@ -478,7 +477,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void putParameterOnStack(ParameterInfo... infos) {
|
||||
private void recordParameterValueInLocalVal(ParameterInfo... infos) {
|
||||
int[] index = new int[infos.length];
|
||||
for (int i = 0; i < infos.length; i++) {
|
||||
ParameterInfo info = infos[i];
|
||||
@@ -515,7 +514,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured();
|
||||
putParameterOnStack(infos.toArray(new ParameterInfo[infos.size()]));
|
||||
recordParameterValueInLocalVal(infos.toArray(new ParameterInfo[infos.size()]));
|
||||
}
|
||||
|
||||
public void leaveTemps() {
|
||||
@@ -633,7 +632,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
@Override
|
||||
public void putValueIfNeeded(@Nullable ValueParameterDescriptor valueParameterDescriptor, @NotNull Type parameterType, @NotNull StackValue value) {
|
||||
if (shouldPutValue(parameterType, value, valueParameterDescriptor)) {
|
||||
if (shouldPutValue(parameterType, value)) {
|
||||
value.put(parameterType, codegen.v);
|
||||
}
|
||||
afterParameterPut(parameterType, value, valueParameterDescriptor);
|
||||
@@ -643,10 +642,10 @@ public class InlineCodegen extends CallGenerator {
|
||||
public void putCapturedValueOnStack(
|
||||
@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex
|
||||
) {
|
||||
if (shouldPutValue(stackValue.type, stackValue, null)) {
|
||||
if (shouldPutValue(stackValue.type, stackValue)) {
|
||||
stackValue.put(stackValue.type, codegen.v);
|
||||
}
|
||||
putCapturedInLocal(stackValue.type, stackValue, null, paramIndex);
|
||||
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user