First implementation of proper agrument order

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