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 =
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(),
@@ -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<AbstractInsnNode> capturedFieldAccess,
@@ -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<AbstractInsnNode> accessChain = getCapturedFieldAccessChain((VarInsnNode) cur);
AbstractInsnNode insnNode = nodeRemapper.foldFieldAccessChainIfNeeded(accessChain, node);
if (insnNode != null) {
@@ -31,19 +31,22 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
private final String newOwnerType;
private final Parameters parameters;
private final Map<String, LambdaInfo> recapturedLambdas;
private final boolean isConstructor;
public RegeneratedLambdaFieldRemapper(
String oldOwnerType,
String newOwnerType,
Parameters parameters,
Map<String, LambdaInfo> 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());
@@ -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");
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")
@@ -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")