Fix duplicate field error on inlining several lambdas
This commit is contained in:
@@ -449,14 +449,6 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<FieldInfo> transformCapturedParams(List<Pair<String, Type>> allFields, Type owner) {
|
|
||||||
List<FieldInfo> result = new ArrayList<FieldInfo>();
|
|
||||||
for (Pair<String, Type> field : allFields) {
|
|
||||||
result.add(FieldInfo.createForHiddenField(owner, field.second, field.first));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) {
|
public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) {
|
||||||
assert !info.isStatic();
|
assert !info.isStatic();
|
||||||
Type fieldType = info.getFieldType();
|
Type fieldType = info.getFieldType();
|
||||||
|
|||||||
+24
-15
@@ -285,26 +285,23 @@ public class AnonymousObjectTransformer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Pair<String, Type>> capturedFieldsToGenerate = new ArrayList<Pair<String, Type>>();
|
|
||||||
for (CapturedParamInfo capturedParamInfo : allCapturedBuilder.listCaptured()) {
|
|
||||||
if (capturedParamInfo.getLambda() == null) { //not inlined
|
|
||||||
capturedFieldsToGenerate.add(new Pair<String, Type>(capturedParamInfo.getNewFieldName(), capturedParamInfo.getType()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()]));
|
String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()]));
|
||||||
|
|
||||||
MethodVisitor constructorVisitor = classBuilder.newMethod(NO_ORIGIN,
|
MethodVisitor constructorVisitor = classBuilder.newMethod(NO_ORIGIN,
|
||||||
AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
||||||
"<init>", constructorDescriptor,
|
"<init>", constructorDescriptor,
|
||||||
null, ArrayUtil.EMPTY_STRING_ARRAY);
|
null, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||||
|
|
||||||
//initialize captured fields
|
//initialize captured fields
|
||||||
List<FieldInfo> fields = AsmUtil.transformCapturedParams(capturedFieldsToGenerate, newLambdaType);
|
List<NewJavaField> newFieldsWithSkipped = TransformationUtilsKt.getNewFieldsToGenerate(allCapturedBuilder.listCaptured());
|
||||||
|
List<FieldInfo> fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo(newLambdaType, newFieldsWithSkipped);
|
||||||
|
|
||||||
int paramIndex = 0;
|
int paramIndex = 0;
|
||||||
InstructionAdapter capturedFieldInitializer = new InstructionAdapter(constructorVisitor);
|
InstructionAdapter capturedFieldInitializer = new InstructionAdapter(constructorVisitor);
|
||||||
for (FieldInfo fieldInfo : fields) {
|
for (int i = 0; i < fieldInfoWithSkipped.size(); i++) {
|
||||||
AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer);
|
FieldInfo fieldInfo = fieldInfoWithSkipped.get(i);
|
||||||
|
if (!newFieldsWithSkipped.get(i).getSkip()) {
|
||||||
|
AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer);
|
||||||
|
}
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,8 +325,7 @@ public class AnonymousObjectTransformer {
|
|||||||
|
|
||||||
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
|
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
|
||||||
constructorVisitor.visitEnd();
|
constructorVisitor.visitEnd();
|
||||||
|
AsmUtil.genClosureFields(TransformationUtilsKt.toNameTypePair(TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder);
|
||||||
AsmUtil.genClosureFields(capturedFieldsToGenerate, classBuilder);
|
|
||||||
//TODO for inline method make public class
|
//TODO for inline method make public class
|
||||||
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
|
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
|
||||||
}
|
}
|
||||||
@@ -390,7 +386,7 @@ public class AnonymousObjectTransformer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
List<LambdaInfo> capturedLambdas = new ArrayList<LambdaInfo>(); //captured var of inlined parameter
|
Set<LambdaInfo> capturedLambdas = new LinkedHashSet<LambdaInfo>(); //captured var of inlined parameter
|
||||||
List<CapturedParamInfo> constructorAdditionalFakeParams = new ArrayList<CapturedParamInfo>();
|
List<CapturedParamInfo> constructorAdditionalFakeParams = new ArrayList<CapturedParamInfo>();
|
||||||
Map<Integer, LambdaInfo> indexToLambda = anonymousObjectGen.getLambdasToInline();
|
Map<Integer, LambdaInfo> indexToLambda = anonymousObjectGen.getLambdasToInline();
|
||||||
Set<Integer> capturedParams = new HashSet<Integer>();
|
Set<Integer> capturedParams = new HashSet<Integer>();
|
||||||
@@ -459,10 +455,16 @@ public class AnonymousObjectTransformer {
|
|||||||
Map<String, LambdaInfo> capturedLambdasToInline = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
|
Map<String, LambdaInfo> capturedLambdasToInline = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
|
||||||
List<CapturedParamDesc> allRecapturedParameters = new ArrayList<CapturedParamDesc>();
|
List<CapturedParamDesc> allRecapturedParameters = new ArrayList<CapturedParamDesc>();
|
||||||
boolean addCapturedNotAddOuter = parentFieldRemapper.isRoot() || (parentFieldRemapper instanceof InlinedLambdaRemapper && parentFieldRemapper.getParent().isRoot());
|
boolean addCapturedNotAddOuter = parentFieldRemapper.isRoot() || (parentFieldRemapper instanceof InlinedLambdaRemapper && parentFieldRemapper.getParent().isRoot());
|
||||||
|
Map<String, CapturedParamInfo> alreadyAdded = new HashMap<String, CapturedParamInfo>();
|
||||||
for (LambdaInfo info : capturedLambdas) {
|
for (LambdaInfo info : capturedLambdas) {
|
||||||
if (addCapturedNotAddOuter) {
|
if (addCapturedNotAddOuter) {
|
||||||
for (CapturedParamDesc desc : info.getCapturedVars()) {
|
for (CapturedParamDesc desc : info.getCapturedVars()) {
|
||||||
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName(), false));
|
String key = desc.getFieldName() + "$$$" + desc.getType().getClassName();
|
||||||
|
CapturedParamInfo alreadyAddedParam = alreadyAdded.get(key);
|
||||||
|
|
||||||
|
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(
|
||||||
|
desc,
|
||||||
|
alreadyAddedParam != null ? alreadyAddedParam.getNewFieldName() : getNewFieldName(desc.getFieldName(), false));
|
||||||
StackValue composed = StackValue.field(desc.getType(),
|
StackValue composed = StackValue.field(desc.getType(),
|
||||||
oldObjectType, /*TODO owner type*/
|
oldObjectType, /*TODO owner type*/
|
||||||
recapturedParamInfo.getNewFieldName(),
|
recapturedParamInfo.getNewFieldName(),
|
||||||
@@ -472,6 +474,13 @@ public class AnonymousObjectTransformer {
|
|||||||
allRecapturedParameters.add(desc);
|
allRecapturedParameters.add(desc);
|
||||||
|
|
||||||
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
|
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
|
||||||
|
if (alreadyAddedParam != null) {
|
||||||
|
recapturedParamInfo.setSkipInConstructor(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isThis0(desc.getFieldName())) {
|
||||||
|
alreadyAdded.put(key, recapturedParamInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
capturedLambdasToInline.put(info.getLambdaClassType().getInternalName(), info);
|
capturedLambdasToInline.put(info.getLambdaClassType().getInternalName(), info);
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public class CapturedParamInfo extends ParameterInfo {
|
|||||||
|
|
||||||
private final String newFieldName;
|
private final String newFieldName;
|
||||||
|
|
||||||
|
private boolean skipInConstructor;
|
||||||
|
|
||||||
public CapturedParamInfo(@NotNull CapturedParamDesc desc, boolean skipped, int index, int remapIndex) {
|
public CapturedParamInfo(@NotNull CapturedParamDesc desc, boolean skipped, int index, int remapIndex) {
|
||||||
this(desc, desc.getFieldName(), skipped, index, remapIndex);
|
this(desc, desc.getFieldName(), skipped, index, remapIndex);
|
||||||
}
|
}
|
||||||
@@ -68,6 +70,7 @@ public class CapturedParamInfo extends ParameterInfo {
|
|||||||
public CapturedParamInfo clone(int newIndex, StackValue newRamapIndex) {
|
public CapturedParamInfo clone(int newIndex, StackValue newRamapIndex) {
|
||||||
CapturedParamInfo capturedParamInfo = new CapturedParamInfo(desc, newFieldName, isSkipped, newIndex, newRamapIndex);
|
CapturedParamInfo capturedParamInfo = new CapturedParamInfo(desc, newFieldName, isSkipped, newIndex, newRamapIndex);
|
||||||
capturedParamInfo.setLambda(lambda);
|
capturedParamInfo.setLambda(lambda);
|
||||||
|
capturedParamInfo.setSkipInConstructor(skipInConstructor);
|
||||||
return capturedParamInfo;
|
return capturedParamInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,4 +78,12 @@ public class CapturedParamInfo extends ParameterInfo {
|
|||||||
public String getContainingLambdaName() {
|
public String getContainingLambdaName() {
|
||||||
return desc.getContainingLambdaName();
|
return desc.getContainingLambdaName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSkipInConstructor() {
|
||||||
|
return skipInConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkipInConstructor(boolean skipInConstructor) {
|
||||||
|
this.skipInConstructor = skipInConstructor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.inline
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Pair
|
||||||
|
import org.jetbrains.kotlin.codegen.FieldInfo
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
|
class NewJavaField(val name: String, val type: Type, val skip: Boolean)
|
||||||
|
|
||||||
|
fun getNewFieldsToGenerate(params: List<CapturedParamInfo>): List<NewJavaField> {
|
||||||
|
return params.filter {
|
||||||
|
//not inlined
|
||||||
|
it.lambda == null
|
||||||
|
}.map {
|
||||||
|
NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun transformToFieldInfo(lambdaType: Type, newFields: List<NewJavaField>): List<FieldInfo> {
|
||||||
|
return newFields.map { field ->
|
||||||
|
FieldInfo.createForHiddenField(lambdaType, field.type, field.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun filterSkipped(fields: List<NewJavaField>): List<NewJavaField> {
|
||||||
|
return fields.filter { !it.skip }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toNameTypePair(fields: List<NewJavaField>): List<Pair<String, Type>> = fields.map { Pair(it.name, it.type) }
|
||||||
Reference in New Issue
Block a user