Proper param propagation in inline

This commit is contained in:
Michael Bogdanov
2015-09-30 14:23:38 +03:00
parent 79fce388b3
commit c83a5b8bd5
18 changed files with 409 additions and 193 deletions
@@ -21,7 +21,7 @@ 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)
class ArgumentAndIndex(val arg: ResolvedValueArgument, val declIndex: Int, var type: Type? = null, var reorder: Boolean = false, var tempValue: StackValue? = null)
abstract class ArgumentGenerator {
/**
@@ -78,26 +78,12 @@ abstract class ArgumentGenerator {
if (actualIndex != declIndex || orderChanged) {
orderChanged = true
argumentWithDeclIndex.reoder = true
argumentWithDeclIndex.reorder = 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)
}
}
reorderArgumentsIfNeeded(actualArgsWithDeclIndex)
actualArgsWithDeclIndex.sortedBy { it.declIndex }.forEach {
it.tempValue?.let {
it.put(it.type, codegen.v)
}
}
mark.dropTo()
return masks
}
@@ -116,4 +102,8 @@ abstract class ArgumentGenerator {
protected open fun generateOther(i: Int, argument: ResolvedValueArgument): Type {
throw UnsupportedOperationException("Unsupported value argument #$i: $argument")
}
protected open fun reorderArgumentsIfNeeded(args: ArrayList<ArgumentAndIndex>) {
throw UnsupportedOperationException("Unsupported operation")
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.ValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.pushDefaultValueOnStack;
@@ -72,7 +73,7 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
assert valueArgument != null;
JetExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression != null : valueArgument.asElement().getText();
callGenerator.genValueAndPut(parameter, argumentExpression, type);
callGenerator.genValueAndPut(parameter, argumentExpression, type, i);
return type;
}
@@ -82,7 +83,7 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
ValueParameterDescriptor parameter = valueParameters.get(i);
Type type = valueParameterTypes.get(i);
pushDefaultValueOnStack(type, codegen.v);
callGenerator.afterParameterPut(type, null, parameter);
callGenerator.afterParameterPut(type, null, parameter, i);
return type;
}
@@ -92,7 +93,12 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
ValueParameterDescriptor parameter = valueParameters.get(i);
Type type = valueParameterTypes.get(i);
codegen.genVarargs(argument, parameter.getType());
callGenerator.afterParameterPut(type, null, parameter);
callGenerator.afterParameterPut(type, null, parameter, i);
return type;
}
@Override
protected void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> actualArgsWithDeclIndex) {
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex);
}
}
@@ -1,124 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.psi.JetExpression;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.org.objectweb.asm.Type;
public abstract class CallGenerator {
static class DefaultCallGenerator extends CallGenerator {
private final ExpressionCodegen codegen;
public DefaultCallGenerator(ExpressionCodegen codegen) {
this.codegen = codegen;
}
@Override
public void genCallInner(
@NotNull Callable callableMethod,
ResolvedCall<?> resolvedCall,
boolean callDefault,
@NotNull ExpressionCodegen codegen
) {
if (!callDefault) {
callableMethod.genInvokeInstruction(codegen.v);
}
else {
((CallableMethod)callableMethod).genInvokeDefaultInstruction(codegen.v);
}
}
@Override
public void genCallWithoutAssertions(
@NotNull CallableMethod method, @NotNull ExpressionCodegen codegen
) {
method.genInvokeInstruction(codegen.v);
}
@Override
public void afterParameterPut(@NotNull Type type, StackValue stackValue, @NotNull ValueParameterDescriptor valueParameterDescriptor) {
}
@Override
public void putHiddenParams() {
}
@Override
public void genValueAndPut(
@NotNull ValueParameterDescriptor valueParameterDescriptor,
@NotNull JetExpression argumentExpression,
@NotNull Type parameterType
) {
StackValue value = codegen.gen(argumentExpression);
value.put(parameterType, codegen.v);
}
@Override
public void putCapturedValueOnStack(
@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex
) {
stackValue.put(stackValue.type, codegen.v);
}
@Override
public void putValueIfNeeded(
@Nullable ValueParameterDescriptor valueParameterDescriptor, @NotNull Type parameterType, @NotNull StackValue value
) {
value.put(value.type, codegen.v);
}
}
public void genCall(@NotNull Callable callableMethod, @Nullable ResolvedCall<?> resolvedCall, boolean callDefault, @NotNull ExpressionCodegen codegen) {
if (resolvedCall != null) {
JetExpression calleeExpression = resolvedCall.getCall().getCalleeExpression();
if (calleeExpression != null) {
codegen.markStartLineNumber(calleeExpression);
}
}
genCallInner(callableMethod, resolvedCall, callDefault, codegen);
}
public abstract void genCallInner(@NotNull Callable callableMethod, @Nullable ResolvedCall<?> resolvedCall, boolean callDefault, @NotNull ExpressionCodegen codegen);
public abstract void genCallWithoutAssertions(@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen);
public abstract void afterParameterPut(@NotNull Type type, StackValue stackValue, @NotNull ValueParameterDescriptor valueParameterDescriptor);
public abstract void genValueAndPut(
@NotNull ValueParameterDescriptor valueParameterDescriptor,
@NotNull JetExpression argumentExpression,
@NotNull Type parameterType
);
public abstract void putValueIfNeeded(@Nullable ValueParameterDescriptor valueParameterDescriptor, @NotNull Type parameterType, @NotNull StackValue value);
public abstract void putCapturedValueOnStack(
@NotNull StackValue stackValue,
@NotNull Type valueType, int paramIndex
);
public abstract void putHiddenParams();
}
@@ -0,0 +1,138 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Type
import java.util.ArrayList
abstract class CallGenerator {
internal class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator() {
override fun genCallInner(
callableMethod: Callable,
resolvedCall: ResolvedCall<*>?,
callDefault: Boolean,
codegen: ExpressionCodegen) {
if (!callDefault) {
callableMethod.genInvokeInstruction(codegen.v)
}
else {
(callableMethod as CallableMethod).genInvokeDefaultInstruction(codegen.v)
}
}
override fun genCallWithoutAssertions(
method: CallableMethod, codegen: ExpressionCodegen) {
method.genInvokeInstruction(codegen.v)
}
override fun afterParameterPut(
type: Type,
stackValue: StackValue?,
valueParameterDescriptor: ValueParameterDescriptor,
parameterIndex: Int) {
}
override fun putHiddenParams() {
}
override fun genValueAndPut(
valueParameterDescriptor: ValueParameterDescriptor,
argumentExpression: JetExpression,
parameterType: Type,
index: Int) {
val value = codegen.gen(argumentExpression)
value.put(parameterType, codegen.v)
}
override fun putCapturedValueOnStack(
stackValue: StackValue, valueType: Type, paramIndex: Int) {
stackValue.put(stackValue.type, codegen.v)
}
override fun putValueIfNeeded(
valueParameterDescriptor: ValueParameterDescriptor?, parameterType: Type, value: StackValue) {
value.put(value.type, codegen.v)
}
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex>) {
val mark = codegen.myFrameMap.mark()
actualArgsWithDeclIndex.reversed().forEach {
if (it.reorder) {
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()
}
}
fun genCall(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
if (resolvedCall != null) {
val calleeExpression = resolvedCall.call.calleeExpression
if (calleeExpression != null) {
codegen.markStartLineNumber(calleeExpression)
}
}
genCallInner(callableMethod, resolvedCall, callDefault, codegen)
}
abstract fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen)
abstract fun genCallWithoutAssertions(callableMethod: CallableMethod, codegen: ExpressionCodegen)
abstract fun afterParameterPut(
type: Type,
stackValue: StackValue?,
valueParameterDescriptor: ValueParameterDescriptor,
parameterIndex: Int)
abstract fun genValueAndPut(
valueParameterDescriptor: ValueParameterDescriptor,
argumentExpression: JetExpression,
parameterType: Type,
parameterIndex: Int)
abstract fun putValueIfNeeded(
valueParameterDescriptor: ValueParameterDescriptor?,
parameterType: Type,
value: StackValue)
abstract fun putCapturedValueOnStack(
stackValue: StackValue,
valueType: Type, paramIndex: Int)
abstract fun putHiddenParams()
abstract fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex>)
}
@@ -1669,6 +1669,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
offset += type.getSize();
return type;
}
@Override
protected void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> args) {
}
}
private void generateEnumEntries() {
@@ -38,13 +38,13 @@ public class CapturedParamInfo extends ParameterInfo {
}
public CapturedParamInfo(@NotNull CapturedParamDesc desc, @NotNull String newFieldName, boolean skipped, int index, int remapIndex) {
super(desc.getType(), skipped, index, remapIndex);
super(desc.getType(), skipped, index, remapIndex, index);
this.desc = desc;
this.newFieldName = newFieldName;
}
public CapturedParamInfo(@NotNull CapturedParamDesc desc, @NotNull String newFieldName, boolean skipped, int index, StackValue remapIndex) {
super(desc.getType(), skipped, index, remapIndex);
super(desc.getType(), skipped, index, remapIndex, index);
this.desc = desc;
this.newFieldName = newFieldName;
}
@@ -410,14 +410,20 @@ public class InlineCodegen extends CallGenerator {
}
@Override
public void afterParameterPut(@NotNull Type type, @Nullable StackValue stackValue, @Nullable ValueParameterDescriptor valueParameterDescriptor) {
putArgumentOrCapturedToLocalVal(type, stackValue, -1);
public void afterParameterPut(
@NotNull Type type,
@Nullable StackValue stackValue,
@Nullable ValueParameterDescriptor valueParameterDescriptor,
int parameterIndex
) {
putArgumentOrCapturedToLocalVal(type, stackValue, -1, parameterIndex);
}
private void putArgumentOrCapturedToLocalVal(
@NotNull Type type,
@Nullable StackValue stackValue,
int capturedParamIndex
int capturedParamIndex,
int parameterIndex
) {
if (!asFunctionInline && Type.VOID_TYPE != type) {
//TODO remap only inlinable closure => otherwise we could get a lot of problem
@@ -431,7 +437,7 @@ public class InlineCodegen extends CallGenerator {
info.setRemapValue(remappedIndex);
}
else {
info = invocationParamBuilder.addNextParameter(type, false, remappedIndex);
info = invocationParamBuilder.addNextValueParameter(type, false, remappedIndex, parameterIndex);
}
recordParameterValueInLocalVal(info);
@@ -513,6 +519,7 @@ public class InlineCodegen extends CallGenerator {
invocationParamBuilder.addNextParameter(param.getAsmType(), false, null);
}
invocationParamBuilder.markValueParametesStart();
List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured();
recordParameterValueInLocalVal(infos.toArray(new ParameterInfo[infos.size()]));
}
@@ -542,13 +549,13 @@ public class InlineCodegen extends CallGenerator {
deparenthesized instanceof JetCallableReferenceExpression;
}
public void rememberClosure(JetExpression expression, Type type) {
public void rememberClosure(JetExpression expression, Type type, int parameterIndex) {
JetExpression lambda = JetPsiUtil.deparenthesize(expression);
assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
LambdaInfo info = new LambdaInfo(lambda, typeMapper);
ParameterInfo closureInfo = invocationParamBuilder.addNextParameter(type, true, null);
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameterIndex);
closureInfo.setLambda(info);
expressionMap.put(closureInfo.getIndex(), info);
}
@@ -619,23 +626,37 @@ public class InlineCodegen extends CallGenerator {
public void genValueAndPut(
@NotNull ValueParameterDescriptor valueParameterDescriptor,
@NotNull JetExpression argumentExpression,
@NotNull Type parameterType
@NotNull Type parameterType,
int parameterIndex
) {
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
rememberClosure(argumentExpression, parameterType);
rememberClosure(argumentExpression, parameterType, valueParameterDescriptor.getIndex());
}
else {
StackValue value = codegen.gen(argumentExpression);
putValueIfNeeded(valueParameterDescriptor, parameterType, value);
putValueIfNeeded(valueParameterDescriptor, parameterType, value, valueParameterDescriptor.getIndex());
}
}
@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
) {
putValueIfNeeded(valueParameterDescriptor, parameterType, value, -1);
}
private void putValueIfNeeded(
@Nullable ValueParameterDescriptor valueParameterDescriptor,
@NotNull Type parameterType,
@NotNull StackValue value,
int index
) {
if (shouldPutValue(parameterType, value)) {
value.put(parameterType, codegen.v);
}
afterParameterPut(parameterType, value, valueParameterDescriptor);
afterParameterPut(parameterType, value, valueParameterDescriptor, index);
}
@Override
@@ -645,7 +666,7 @@ public class InlineCodegen extends CallGenerator {
if (shouldPutValue(stackValue.type, stackValue)) {
stackValue.put(stackValue.type, codegen.v);
}
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex);
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex);
}
@@ -749,4 +770,9 @@ public class InlineCodegen extends CallGenerator {
String targetFile = getSourceFilePath(targetDescriptor);
incrementalCache.registerInline(sourceFile, jvmSignature.toString(), targetFile);
}
@Override
public void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> actualArgsWithDeclIndex) {
}
}
@@ -34,7 +34,6 @@ public class LocalVarRemapper {
private final int actualParamsSize;
private final StackValue[] remapValues;
private final int additionalShift;
public LocalVarRemapper(Parameters params, int additionalShift) {
@@ -42,20 +41,40 @@ public class LocalVarRemapper {
this.allParamsSize = params.totalSize();
this.params = params;
int realSize = 0;
remapValues = new StackValue [params.totalSize()];
Integer [] declIndexesToActual = new Integer [params.totalSize()];
Integer [] actualDeclShifts = new Integer [params.totalSize()];
int index = 0;
for (ParameterInfo info : params) {
if (!info.isSkippedOrRemapped()) {
remapValues[index] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE);
realSize += info.getType().getSize();
} else {
remapValues[index] = info.isRemapped() ? info.getRemapValue() : null;
for (ParameterInfo param : params) {
if (param != ParameterInfo.STUB && param != CapturedParamInfo.STUB) {
declIndexesToActual[param.declarationIndex] = index;
}
index++;
}
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) {
if (info != ParameterInfo.STUB && info != CapturedParamInfo.STUB) {
if (!info.isSkippedOrRemapped()) {
remapValues[actualDeclShifts[info.declarationIndex]] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE);
realSize += info.getType().getSize();
}
else {
remapValues[actualDeclShifts[info.declarationIndex]] = info.isRemapped() ? info.getRemapValue() : null;
}
}
}
actualParamsSize = realSize;
}
@@ -63,7 +82,7 @@ public class LocalVarRemapper {
int remappedIndex;
if (index < allParamsSize) {
ParameterInfo info = params.get(index);
ParameterInfo info = params.getByByteCodeIndex(index);
StackValue remapped = remapValues[index];
if (info.isSkipped || remapped == null) {
return new RemapInfo(info);
@@ -559,7 +559,7 @@ public class MethodInliner {
private LambdaInfo getLambdaIfExists(int varIndex) {
if (varIndex < parameters.totalSize()) {
return parameters.get(varIndex).getLambda();
return parameters.getByByteCodeIndex(varIndex).getLambda();
}
return null;
}
@@ -24,31 +24,34 @@ import org.jetbrains.org.objectweb.asm.Type;
class ParameterInfo {
public static final ParameterInfo STUB = new ParameterInfo(AsmTypes.OBJECT_TYPE, true, -1, -1);
public static final ParameterInfo STUB = new ParameterInfo(AsmTypes.OBJECT_TYPE, true, -1, -1, -1);
protected final int index;
protected final int declarationIndex;
private boolean isCaptured;
public final Type type;
//for skipped parameter: e.g. inlined lambda
public final boolean isSkipped;
public boolean isSkipped;
//in case when parameter could be extracted from outer context (e.g. from local var)
private StackValue remapValue;
public LambdaInfo lambda;
ParameterInfo(Type type, boolean skipped, int index, int remapValue) {
this(type, skipped, index, remapValue == -1 ? null : StackValue.local(remapValue, type));
ParameterInfo(Type type, boolean skipped, int index, int remapValue, int declarationIndex) {
this(type, skipped, index, remapValue == -1 ? null : StackValue.local(remapValue, type), declarationIndex);
}
ParameterInfo(@NotNull Type type, boolean skipped, int index, @Nullable StackValue remapValue) {
ParameterInfo(@NotNull Type type, boolean skipped, int index, @Nullable StackValue remapValue, int declarationIndex) {
this.type = type;
this.isSkipped = skipped;
this.remapValue = remapValue;
this.index = index;
this.declarationIndex = declarationIndex;
}
public boolean isSkippedOrRemapped() {
@@ -82,19 +85,27 @@ class ParameterInfo {
return lambda;
}
public void setLambda(@Nullable LambdaInfo lambda) {
public ParameterInfo setLambda(@Nullable LambdaInfo lambda) {
this.lambda = lambda;
return this;
}
public void setRemapValue(StackValue remapValue) {
public ParameterInfo setRemapValue(StackValue remapValue) {
this.remapValue = remapValue;
return this;
}
public boolean isCaptured() {
return isCaptured;
}
public ParameterInfo setSkipped(boolean skipped) {
isSkipped = skipped;
return this;
}
public void setCaptured(boolean isCaptured) {
this.isCaptured = isCaptured;
}
}
@@ -29,9 +29,32 @@ public class Parameters implements Iterable<ParameterInfo> {
private final List<ParameterInfo> real;
private final List<CapturedParamInfo> captured;
private final Integer [] declIndexesToActual;
private final ParameterInfo [] actualDeclShifts;
public Parameters(List<ParameterInfo> real, List<CapturedParamInfo> captured) {
this.real = real;
this.captured = captured;
declIndexesToActual = new Integer [totalSize()];
int index = 0;
for (ParameterInfo param : this) {
if (param != ParameterInfo.STUB && param != CapturedParamInfo.STUB) {
declIndexesToActual[param.declarationIndex] = index;
}
index++;
}
actualDeclShifts = new ParameterInfo [totalSize()];
int realSize = 0;
for (int i = 0; i < declIndexesToActual.length; i++) {
Integer declIndexToActual = declIndexesToActual[i];
if (declIndexToActual != null) {
actualDeclShifts[realSize] = getByDeclarationIndex(i);
realSize += get(declIndexToActual).getType().getSize();
}
}
}
public List<ParameterInfo> getReal() {
@@ -46,6 +69,17 @@ public class Parameters implements Iterable<ParameterInfo> {
return real.size() + captured.size();
}
public ParameterInfo getByDeclarationIndex(int index) {
if (index < real.size()) {
return real.get(declIndexesToActual[index]);
}
return captured.get(index - real.size());
}
public ParameterInfo getByByteCodeIndex(int index) {
return actualDeclShifts[index];
}
public ParameterInfo get(int index) {
if (index < real.size()) {
return real.get(index);
@@ -22,43 +22,54 @@ import org.jetbrains.org.objectweb.asm.Type
import java.util.ArrayList
import java.util.Collections
class ParametersBuilder {
class ParametersBuilder private constructor(){
private val params = ArrayList<ParameterInfo>()
private val capturedParams = ArrayList<CapturedParamInfo>()
private val valueAndHiddenParams = arrayListOf<ParameterInfo>()
private val capturedParams = arrayListOf<CapturedParamInfo>()
private var valueParamStart = 0
var nextValueParameterIndex = 0
private set
private var nextCaptured = 0
fun addThis(type: Type, skipped: Boolean): ParameterInfo {
val info = ParameterInfo(type, skipped, nextValueParameterIndex, -1)
val info = ParameterInfo(type, skipped, nextValueParameterIndex, -1, valueAndHiddenParams.size())
addParameter(info)
return info
}
fun addNextParameter(type: Type, skipped: Boolean, remapValue: StackValue?): ParameterInfo {
return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue))
return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue, valueAndHiddenParams.size()))
}
fun addNextValueParameter(type: Type, skipped: Boolean, remapValue: StackValue?, parameterIndex: Int): ParameterInfo {
return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue,
if (parameterIndex == -1) valueAndHiddenParams.size() else { parameterIndex + valueParamStart }))
}
fun addCapturedParam(
original: CapturedParamInfo,
newFieldName: String): CapturedParamInfo {
val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextCaptured, original.getIndex())
val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextCapturedIndex(), original.getIndex())
info.setLambda(original.getLambda())
return addCapturedParameter(info)
}
private fun nextCapturedIndex(): Int {
return nextCaptured
}
fun addCapturedParam(
desc: CapturedParamDesc,
newFieldName: String): CapturedParamInfo {
val info = CapturedParamInfo(desc, newFieldName, false, nextCaptured, null)
val info = CapturedParamInfo(desc, newFieldName, false, nextCapturedIndex(), null)
return addCapturedParameter(info)
}
fun addCapturedParamCopy(
copyFrom: CapturedParamInfo): CapturedParamInfo {
val info = copyFrom.newIndex(nextCaptured)
val info = copyFrom.newIndex(nextCapturedIndex())
return addCapturedParameter(info)
}
@@ -68,7 +79,7 @@ class ParametersBuilder {
type: Type,
skipped: Boolean,
original: ParameterInfo?): CapturedParamInfo {
val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCaptured,
val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCapturedIndex(),
if (original != null) original.getIndex() else -1)
if (original != null) {
info.setLambda(original.getLambda())
@@ -77,7 +88,7 @@ class ParametersBuilder {
}
private fun addParameter(info: ParameterInfo): ParameterInfo {
params.add(info)
valueAndHiddenParams.add(info)
nextValueParameterIndex += info.getType().size
return info
}
@@ -89,7 +100,11 @@ class ParametersBuilder {
}
fun listNotCaptured(): List<ParameterInfo> {
return Collections.unmodifiableList(params)
return Collections.unmodifiableList(valueAndHiddenParams)
}
fun markValueParametesStart(){
this.valueParamStart = valueAndHiddenParams.size()
}
fun listCaptured(): List<CapturedParamInfo> {
@@ -97,9 +112,7 @@ class ParametersBuilder {
}
fun listAllParams(): List<ParameterInfo> {
val list = ArrayList(params)
list.addAll(capturedParams)
return list
return valueAndHiddenParams + capturedParams
}
private fun buildWithStubs(): List<ParameterInfo> {
@@ -114,16 +127,24 @@ class ParametersBuilder {
return Parameters(buildWithStubs(), buildCapturedWithStubs())
}
// public fun getValueParameter(index: Int): ParameterInfo {
// return valueAndHiddenParams[index + valueParamStart]
// }
companion object {
@JvmStatic fun newBuilder(): ParametersBuilder {
@JvmStatic
fun newBuilder(): ParametersBuilder {
return ParametersBuilder()
}
@JvmOverloads @JvmStatic fun initializeBuilderFrom(objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null): ParametersBuilder {
@JvmOverloads @JvmStatic
fun initializeBuilderFrom(objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null, addThis: Boolean = true): ParametersBuilder {
val builder = newBuilder()
//skipped this for inlined lambda cause it will be removed
builder.addThis(objectType, inlineLambda != null).setLambda(inlineLambda)
if (addThis) {
//skipped this for inlined lambda cause it will be removed
builder.addThis(objectType, inlineLambda != null).setLambda(inlineLambda)
}
val types = Type.getArgumentTypes(descriptor)
for (type in types) {
@@ -0,0 +1,19 @@
import test.*
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"
}
@@ -0,0 +1,5 @@
package test
inline fun test(a: String, b: String, c: () -> String): String {
return a + b + c();
}
@@ -0,0 +1,19 @@
import test.*
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"
}
@@ -0,0 +1,5 @@
package test
inline fun test(a: String, b: String, c: () -> String): String {
return a + b + c();
}
@@ -116,6 +116,27 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
}
}
@TestMetadata("compiler/testData/codegen/boxInline/argumentOrder")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ArgumentOrder extends AbstractBlackBoxInlineCodegenTest {
public void testAllFilesPresentInArgumentOrder() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/argumentOrder"), Pattern.compile("^(.+)\\.1.kt$"), true);
}
@TestMetadata("justLambda.1.kt")
public void testJustLambda() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/justLambda.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("simple.1.kt")
public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/simple.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxInline/builders")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -116,6 +116,27 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
}
}
@TestMetadata("compiler/testData/codegen/boxInline/argumentOrder")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ArgumentOrder extends AbstractCompileKotlinAgainstInlineKotlinTest {
public void testAllFilesPresentInArgumentOrder() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/argumentOrder"), Pattern.compile("^(.+)\\.1.kt$"), true);
}
@TestMetadata("justLambda.1.kt")
public void testJustLambda() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/justLambda.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("simple.1.kt")
public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/simple.1.kt");
doBoxTestWithInlineCheck(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxInline/builders")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)