Fix for KT-9064

#KT-9064 Fixed
This commit is contained in:
Michael Bogdanov
2015-09-09 14:52:54 +03:00
parent e03e9bb1a3
commit a5f7df3ebf
10 changed files with 106 additions and 13 deletions
@@ -237,7 +237,7 @@ public class AnonymousObjectTransformer {
RegeneratedLambdaFieldRemapper remapper = RegeneratedLambdaFieldRemapper remapper =
new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(), new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(),
parameters, anonymousObjectGen.getCapturedLambdasToInline(), parameters, anonymousObjectGen.getCapturedLambdasToInline(),
parentRemapper); parentRemapper, false);
MethodInliner inliner = new MethodInliner(sourceNode, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")), MethodInliner inliner = new MethodInliner(sourceNode, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName(), remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName(),
@@ -325,7 +325,7 @@ public class AnonymousObjectTransformer {
RegeneratedLambdaFieldRemapper remapper = RegeneratedLambdaFieldRemapper remapper =
new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(), new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(),
constructorParameters, anonymousObjectGen.getCapturedLambdasToInline(), constructorParameters, anonymousObjectGen.getCapturedLambdasToInline(),
parentRemapper); parentRemapper, true);
MethodInliner inliner = new MethodInliner(constructor, constructorParameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")), MethodInliner inliner = new MethodInliner(constructor, constructorParameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
remapper, isSameModule, "Transformer for constructor of " + anonymousObjectGen.getOwnerInternalName(), remapper, isSameModule, "Transformer for constructor of " + anonymousObjectGen.getOwnerInternalName(),
@@ -60,6 +60,11 @@ public class FieldRemapper {
return foldFieldAccessChainIfNeeded(capturedFieldAccess, 1, node); return foldFieldAccessChainIfNeeded(capturedFieldAccess, 1, node);
} }
//TODO: seems that this method is redundant but it added from safety purposes before new milestone
public boolean processNonAload0FieldAccessChains(boolean isInlinedLambda) {
return false;
}
@Nullable @Nullable
private AbstractInsnNode foldFieldAccessChainIfNeeded( private AbstractInsnNode foldFieldAccessChainIfNeeded(
@NotNull List<AbstractInsnNode> capturedFieldAccess, @NotNull List<AbstractInsnNode> capturedFieldAccess,
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen.inline; package org.jetbrains.kotlin.codegen.inline;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.ClosureCodegen; import org.jetbrains.kotlin.codegen.ClosureCodegen;
@@ -25,11 +24,6 @@ import org.jetbrains.kotlin.codegen.StackValue;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer; import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache;
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -551,9 +545,7 @@ public class MethodInliner {
public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) { public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) {
if (insnNode.getOpcode() == Opcodes.ALOAD) { if (insnNode.getOpcode() == Opcodes.ALOAD) {
int varIndex = ((VarInsnNode) insnNode).var; int varIndex = ((VarInsnNode) insnNode).var;
if (varIndex < parameters.totalSize()) { return getLambdaIfExists(varIndex);
return parameters.get(varIndex).getLambda();
}
} }
else if (insnNode instanceof FieldInsnNode) { else if (insnNode instanceof FieldInsnNode) {
FieldInsnNode fieldInsnNode = (FieldInsnNode) insnNode; FieldInsnNode fieldInsnNode = (FieldInsnNode) insnNode;
@@ -565,6 +557,13 @@ public class MethodInliner {
return null; return null;
} }
private LambdaInfo getLambdaIfExists(int varIndex) {
if (varIndex < parameters.totalSize()) {
return parameters.get(varIndex).getLambda();
}
return null;
}
private static void removeClosureAssertions(MethodNode node) { private static void removeClosureAssertions(MethodNode node) {
AbstractInsnNode cur = node.instructions.getFirst(); AbstractInsnNode cur = node.instructions.getFirst();
while (cur != null && cur.getNext() != null) { while (cur != null && cur.getNext() != null) {
@@ -598,7 +597,8 @@ public class MethodInliner {
AbstractInsnNode cur = node.instructions.getFirst(); AbstractInsnNode cur = node.instructions.getFirst();
while (cur != null) { while (cur != null) {
if (cur instanceof VarInsnNode && cur.getOpcode() == Opcodes.ALOAD) { if (cur instanceof VarInsnNode && cur.getOpcode() == Opcodes.ALOAD) {
if (((VarInsnNode) cur).var == 0) { int varIndex = ((VarInsnNode) cur).var;
if (varIndex == 0 || nodeRemapper.processNonAload0FieldAccessChains(getLambdaIfExists(varIndex) != null)) {
List<AbstractInsnNode> accessChain = getCapturedFieldAccessChain((VarInsnNode) cur); List<AbstractInsnNode> accessChain = getCapturedFieldAccessChain((VarInsnNode) cur);
AbstractInsnNode insnNode = nodeRemapper.foldFieldAccessChainIfNeeded(accessChain, node); AbstractInsnNode insnNode = nodeRemapper.foldFieldAccessChainIfNeeded(accessChain, node);
if (insnNode != null) { if (insnNode != null) {
@@ -31,19 +31,22 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
private final String newOwnerType; private final String newOwnerType;
private final Parameters parameters; private final Parameters parameters;
private final Map<String, LambdaInfo> recapturedLambdas; private final Map<String, LambdaInfo> recapturedLambdas;
private final boolean isConstructor;
public RegeneratedLambdaFieldRemapper( public RegeneratedLambdaFieldRemapper(
String oldOwnerType, String oldOwnerType,
String newOwnerType, String newOwnerType,
Parameters parameters, Parameters parameters,
Map<String, LambdaInfo> recapturedLambdas, Map<String, LambdaInfo> recapturedLambdas,
FieldRemapper remapper FieldRemapper remapper,
boolean isConstructor
) { ) {
super(oldOwnerType, remapper, parameters); super(oldOwnerType, remapper, parameters);
this.oldOwnerType = oldOwnerType; this.oldOwnerType = oldOwnerType;
this.newOwnerType = newOwnerType; this.newOwnerType = newOwnerType;
this.parameters = parameters; this.parameters = parameters;
this.recapturedLambdas = recapturedLambdas; this.recapturedLambdas = recapturedLambdas;
this.isConstructor = isConstructor;
} }
@Override @Override
@@ -66,6 +69,11 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
} }
} }
@Override
public boolean processNonAload0FieldAccessChains(boolean isInlinedLambda) {
return isInlinedLambda && isConstructor;
}
@Nullable @Nullable
public CapturedParamInfo findFieldInMyCaptured(@NotNull FieldInsnNode fieldInsnNode) { public CapturedParamInfo findFieldInMyCaptured(@NotNull FieldInsnNode fieldInsnNode) {
return super.findField(fieldInsnNode, parameters.getCaptured()); return super.findField(fieldInsnNode, parameters.getCaptured());
@@ -0,0 +1,9 @@
//NO_CHECK_LAMBDA_INLINING
import test.*
fun box(): String {
val test = Test("OK")
return test._parameter.property
}
@@ -0,0 +1,17 @@
package test
class Test(val _member: String) {
val _parameter: Z = test {
object : Z {
override val property = _member
}
}
}
interface Z {
val property: String
}
inline fun test(s: () -> Z): Z {
return s()
}
@@ -0,0 +1,9 @@
//NO_CHECK_LAMBDA_INLINING
import test.*
fun box(): String {
val test = Test("OK")
return test._parameter.property.property
}
@@ -0,0 +1,21 @@
package test
class Test(val _member: String) {
val _parameter: Z<Z<String>> = test {
object : Z<Z<String>> {
override val property = test {
object : Z<String> {
override val property = _member
}
}
}
}
}
interface Z<T> {
val property: T
}
inline fun <T> test(s: () -> Z<T>): Z<T> {
return s()
}
@@ -96,6 +96,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/changingReturnType.1.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/changingReturnType.1.kt");
doTestMultiFileWithInlineCheck(fileName); doTestMultiFileWithInlineCheck(fileName);
} }
@TestMetadata("kt9064.1.kt")
public void testKt9064() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt9064.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("kt9064v2.1.kt")
public void testKt9064v2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
} }
@TestMetadata("compiler/testData/codegen/boxInline/builders") @TestMetadata("compiler/testData/codegen/boxInline/builders")
@@ -96,6 +96,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/changingReturnType.1.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/changingReturnType.1.kt");
doBoxTestWithInlineCheck(fileName); doBoxTestWithInlineCheck(fileName);
} }
@TestMetadata("kt9064.1.kt")
public void testKt9064() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt9064.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("kt9064v2.1.kt")
public void testKt9064v2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.1.kt");
doBoxTestWithInlineCheck(fileName);
}
} }
@TestMetadata("compiler/testData/codegen/boxInline/builders") @TestMetadata("compiler/testData/codegen/boxInline/builders")