From a5f7df3ebf8b2df79b7c6bb4e362583aca692d08 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Wed, 9 Sep 2015 14:52:54 +0300 Subject: [PATCH] Fix for KT-9064 #KT-9064 Fixed --- .../inline/AnonymousObjectTransformer.java | 4 ++-- .../kotlin/codegen/inline/FieldRemapper.java | 5 +++++ .../kotlin/codegen/inline/MethodInliner.java | 20 +++++++++--------- .../RegeneratedLambdaFieldRemapper.java | 10 ++++++++- .../boxInline/anonymousObject/kt9064.1.kt | 9 ++++++++ .../boxInline/anonymousObject/kt9064.2.kt | 17 +++++++++++++++ .../boxInline/anonymousObject/kt9064v2.1.kt | 9 ++++++++ .../boxInline/anonymousObject/kt9064v2.2.kt | 21 +++++++++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 12 +++++++++++ ...otlinAgainstInlineKotlinTestGenerated.java | 12 +++++++++++ 10 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/anonymousObject/kt9064.1.kt create mode 100644 compiler/testData/codegen/boxInline/anonymousObject/kt9064.2.kt create mode 100644 compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.1.kt create mode 100644 compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.2.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index 887f5f6f5d1..8fd05f110db 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -237,7 +237,7 @@ public class AnonymousObjectTransformer { RegeneratedLambdaFieldRemapper remapper = new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(), parameters, anonymousObjectGen.getCapturedLambdasToInline(), - parentRemapper); + parentRemapper, false); MethodInliner inliner = new MethodInliner(sourceNode, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")), remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName(), @@ -325,7 +325,7 @@ public class AnonymousObjectTransformer { RegeneratedLambdaFieldRemapper remapper = new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(), constructorParameters, anonymousObjectGen.getCapturedLambdasToInline(), - parentRemapper); + parentRemapper, true); MethodInliner inliner = new MethodInliner(constructor, constructorParameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")), remapper, isSameModule, "Transformer for constructor of " + anonymousObjectGen.getOwnerInternalName(), diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java index e2d21e7554e..087c3878214 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java @@ -60,6 +60,11 @@ public class FieldRemapper { 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 private AbstractInsnNode foldFieldAccessChainIfNeeded( @NotNull List capturedFieldAccess, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java index ca38f47cc41..f6e7c36e2a3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.codegen.inline; import com.google.common.collect.Lists; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; 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.optimization.MandatoryMethodTransformer; 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.MethodVisitor; import org.jetbrains.org.objectweb.asm.Opcodes; @@ -551,9 +545,7 @@ public class MethodInliner { public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) { if (insnNode.getOpcode() == Opcodes.ALOAD) { int varIndex = ((VarInsnNode) insnNode).var; - if (varIndex < parameters.totalSize()) { - return parameters.get(varIndex).getLambda(); - } + return getLambdaIfExists(varIndex); } else if (insnNode instanceof FieldInsnNode) { FieldInsnNode fieldInsnNode = (FieldInsnNode) insnNode; @@ -565,6 +557,13 @@ public class MethodInliner { return null; } + private LambdaInfo getLambdaIfExists(int varIndex) { + if (varIndex < parameters.totalSize()) { + return parameters.get(varIndex).getLambda(); + } + return null; + } + private static void removeClosureAssertions(MethodNode node) { AbstractInsnNode cur = node.instructions.getFirst(); while (cur != null && cur.getNext() != null) { @@ -598,7 +597,8 @@ public class MethodInliner { AbstractInsnNode cur = node.instructions.getFirst(); while (cur != null) { 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 accessChain = getCapturedFieldAccessChain((VarInsnNode) cur); AbstractInsnNode insnNode = nodeRemapper.foldFieldAccessChainIfNeeded(accessChain, node); if (insnNode != null) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java index 85f41d326c6..caf6f789b71 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java @@ -31,19 +31,22 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper { private final String newOwnerType; private final Parameters parameters; private final Map recapturedLambdas; + private final boolean isConstructor; public RegeneratedLambdaFieldRemapper( String oldOwnerType, String newOwnerType, Parameters parameters, Map recapturedLambdas, - FieldRemapper remapper + FieldRemapper remapper, + boolean isConstructor ) { super(oldOwnerType, remapper, parameters); this.oldOwnerType = oldOwnerType; this.newOwnerType = newOwnerType; this.parameters = parameters; this.recapturedLambdas = recapturedLambdas; + this.isConstructor = isConstructor; } @Override @@ -66,6 +69,11 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper { } } + @Override + public boolean processNonAload0FieldAccessChains(boolean isInlinedLambda) { + return isInlinedLambda && isConstructor; + } + @Nullable public CapturedParamInfo findFieldInMyCaptured(@NotNull FieldInsnNode fieldInsnNode) { return super.findField(fieldInsnNode, parameters.getCaptured()); diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt9064.1.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt9064.1.kt new file mode 100644 index 00000000000..7bf9a032dc6 --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt9064.1.kt @@ -0,0 +1,9 @@ +//NO_CHECK_LAMBDA_INLINING +import test.* + +fun box(): String { + + val test = Test("OK") + + return test._parameter.property +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt9064.2.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt9064.2.kt new file mode 100644 index 00000000000..0f46921bff4 --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt9064.2.kt @@ -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() +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.1.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.1.kt new file mode 100644 index 00000000000..98c9969c3d9 --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.1.kt @@ -0,0 +1,9 @@ +//NO_CHECK_LAMBDA_INLINING +import test.* + +fun box(): String { + + val test = Test("OK") + + return test._parameter.property.property +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.2.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.2.kt new file mode 100644 index 00000000000..da24cceacf3 --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt9064v2.2.kt @@ -0,0 +1,21 @@ +package test + +class Test(val _member: String) { + val _parameter: Z> = test { + object : Z> { + override val property = test { + object : Z { + override val property = _member + } + } + } + } +} + +interface Z { + val property: T +} + +inline fun test(s: () -> Z): Z { + return s() +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java index ff9992cc3aa..7abdf1b1648 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java @@ -96,6 +96,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/changingReturnType.1.kt"); 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") diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java index ca11728bd63..674e6a2895f 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -96,6 +96,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/changingReturnType.1.kt"); 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")