From a7b3c70d2144c4dd5075c1e76688a91b49779328 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Thu, 22 Oct 2015 14:14:01 +0300 Subject: [PATCH] Fix for KT-7017: Reified type referenced in object literal crashes at runtime #KT-7017 Fixed --- .../inline/AnonymousObjectTransformer.java | 57 ++++++++++--------- .../codegen/boxInline/reified/kt7017.1.kt | 9 +++ .../codegen/boxInline/reified/kt7017.2.kt | 9 +++ .../BlackBoxInlineCodegenTestGenerated.java | 6 ++ ...otlinAgainstInlineKotlinTestGenerated.java | 6 ++ 5 files changed, 59 insertions(+), 28 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/reified/kt7017.1.kt create mode 100644 compiler/testData/codegen/boxInline/reified/kt7017.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 76519227484..23e9bbf95ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -43,6 +43,8 @@ public class AnonymousObjectTransformer { protected final JetTypeMapper typeMapper; + private final InlineResult transformationResult; + private MethodNode constructor; private String sourceInfo; @@ -80,6 +82,7 @@ public class AnonymousObjectTransformer { reader = InlineCodegenUtil.buildClassReaderByInternalName(state, objectInternalName); typeRemapper = new TypeRemapper(inliningContext.typeMapping); + transformationResult = InlineResult.create(); } @NotNull @@ -87,14 +90,13 @@ public class AnonymousObjectTransformer { ClassBuilder classBuilder = createClassBuilder(); final List methodsToTransform = new ArrayList(); - final InlineResult result = InlineResult.create(); reader.accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) { @Override public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { if (signature != null) { ReifiedTypeInliner.SignatureReificationResult signatureResult = inliningContext.reifedTypeInliner.reifySignature(signature); signature = signatureResult.getNewSignature(); - result.getReifiedTypeParametersUsages().mergeAll(signatureResult.getTypeParametersUsages()); + transformationResult.getReifiedTypeParametersUsages().mergeAll(signatureResult.getTypeParametersUsages()); } super.visit(version, access, name, signature, superName, interfaces); } @@ -182,9 +184,8 @@ public class AnonymousObjectTransformer { for (MethodNode next : methodsToTransform) { MethodVisitor deferringVisitor = newMethod(classBuilder, next); - InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder); - result.addAllClassesToRemove(funResult); - result.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages()); + InlineResult funResult = + inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false); Type returnType = Type.getReturnType(next.desc); if (!AsmUtil.isPrimitive(returnType)) { @@ -201,17 +202,29 @@ public class AnonymousObjectTransformer { method.visitEnd(); } - InlineResult constructorResult = - generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper, additionalFakeParams); - - result.addAllClassesToRemove(constructorResult); + generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper, additionalFakeParams); SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder); classBuilder.done(); anonymousObjectGen.setNewLambdaType(newLambdaType); - return result; + return transformationResult; + } + + @NotNull + private InlineResult inlineMethodAndUpdateGlobalResult( + @NotNull AnonymousObjectGeneration anonymousObjectGen, + @NotNull FieldRemapper parentRemapper, + @NotNull MethodVisitor deferringVisitor, + @NotNull MethodNode next, + @NotNull ParametersBuilder allCapturedParamBuilder, + boolean isConstructor + ) { + InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, isConstructor); + transformationResult.addAllClassesToRemove(funResult); + transformationResult.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages()); + return funResult; } @NotNull @@ -220,15 +233,16 @@ public class AnonymousObjectTransformer { @NotNull FieldRemapper parentRemapper, @NotNull MethodVisitor deferringVisitor, @NotNull MethodNode sourceNode, - @NotNull ParametersBuilder capturedBuilder + @NotNull ParametersBuilder capturedBuilder, + boolean isConstructor ) { ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions); - Parameters parameters = getMethodParametersWithCaptured(capturedBuilder, sourceNode); + Parameters parameters = isConstructor ? capturedBuilder.buildParameters() : getMethodParametersWithCaptured(capturedBuilder, sourceNode); RegeneratedLambdaFieldRemapper remapper = new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(), parameters, anonymousObjectGen.getCapturedLambdasToInline(), - parentRemapper, false); + parentRemapper, isConstructor); MethodInliner inliner = new MethodInliner(sourceNode, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")), remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName(), @@ -240,7 +254,7 @@ public class AnonymousObjectTransformer { return result; } - private InlineResult generateConstructorAndFields( + private void generateConstructorAndFields( @NotNull ClassBuilder classBuilder, @NotNull ParametersBuilder allCapturedBuilder, @NotNull ParametersBuilder constructorInlineBuilder, @@ -311,25 +325,12 @@ public class AnonymousObjectTransformer { } } - Parameters constructorParameters = constructorInlineBuilder.buildParameters(); - - RegeneratedLambdaFieldRemapper remapper = - new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(), - constructorParameters, anonymousObjectGen.getCapturedLambdasToInline(), - parentRemapper, true); - - MethodInliner inliner = new MethodInliner(constructor, constructorParameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")), - remapper, isSameModule, "Transformer for constructor of " + anonymousObjectGen.getOwnerInternalName(), - sourceMapper); - InlineResult result = inliner.doInline(capturedFieldInitializer, new LocalVarRemapper(constructorParameters, 0), false, - LabelOwner.NOT_APPLICABLE); - constructorVisitor.visitMaxs(-1, -1); + inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true); constructorVisitor.visitEnd(); AsmUtil.genClosureFields(capturedFieldsToGenerate, classBuilder); //TODO for inline method make public class anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor); - return result; } @NotNull diff --git a/compiler/testData/codegen/boxInline/reified/kt7017.1.kt b/compiler/testData/codegen/boxInline/reified/kt7017.1.kt new file mode 100644 index 00000000000..9ff07ab1911 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/kt7017.1.kt @@ -0,0 +1,9 @@ +import test.* + +fun box(): String { + if (!test("OK")) return "fail 1" + + if (test("OK")) return "fail 2" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/kt7017.2.kt b/compiler/testData/codegen/boxInline/reified/kt7017.2.kt new file mode 100644 index 00000000000..137047ae9a3 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/kt7017.2.kt @@ -0,0 +1,9 @@ +package test + +inline fun test(x: Any): Boolean { + val x = object { + val y = x is T + } + + return x.y +} \ 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 cf8c010ab71..2cc2314057d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java @@ -1084,6 +1084,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo doTestMultiFileWithInlineCheck(fileName); } + @TestMetadata("kt7017.1.kt") + public void testKt7017() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt7017.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + @TestMetadata("packages.1.kt") public void testPackages() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java index 1c7d030b0d5..eb2225aed0d 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1084,6 +1084,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doBoxTestWithInlineCheck(fileName); } + @TestMetadata("kt7017.1.kt") + public void testKt7017() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt7017.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + @TestMetadata("packages.1.kt") public void testPackages() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");