From 16b7bece46c99c85a9f1042ccddab78ca5033b27 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 13 Oct 2017 15:14:58 +0300 Subject: [PATCH] Fix constant expression inlining logic Constant expressions are inlined if they do not depend on non-inlineable vals. Java constants are always inlined. Kotlin constants are inlined in LV 1.1+. --- .../kotlin/codegen/ExpressionCodegen.java | 2 -- .../kotlin/codegen/JvmCodegenUtil.java | 2 +- .../kotlin/resolve/jvm/jvmConstants.kt | 14 +++++--------- .../constants/noInlineNonStaticJavaField.kt | 14 ++++++++++++++ .../noInlineNonStaticJavaField_lv10.kt | 15 +++++++++++++++ .../noInlineNonStaticJavaField_lv11.kt | 15 +++++++++++++++ .../codegen/BytecodeTextTestGenerated.java | 18 ++++++++++++++++++ 7 files changed, 68 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField.kt create mode 100644 compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv10.kt create mode 100644 compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv11.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 52a4908f839..40d6e32897b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.util.ArrayUtil; @@ -74,7 +73,6 @@ import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt; import org.jetbrains.kotlin.resolve.constants.*; -import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.inline.InlineUtil; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index 4e067f54f08..d0dce133e4a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -295,7 +295,7 @@ public class JvmCodegenUtil { } public static boolean isInlinedJavaConstProperty(VariableDescriptor descriptor) { - return JvmConstantsKt.isInlinedJavaConstProperty(descriptor); + return descriptor instanceof JavaPropertyDescriptor && descriptor.isConst(); } @Nullable diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/jvmConstants.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/jvmConstants.kt index cfe144921d8..27698eadfe1 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/jvmConstants.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/jvmConstants.kt @@ -42,7 +42,7 @@ fun getCompileTimeConstant( if (!shouldInlineConstVals && !takeUpConstValsAsConst && compileTimeValue.usesVariableAsConstant) { val constantChecker = ConstantsChecker(bindingContext) expression.accept(constantChecker) - if (constantChecker.containsNonInlinedVals) return null + if (constantChecker.containsKotlinConstVals) return null } val expectedType = bindingContext.getType(expression) ?: return null @@ -52,25 +52,21 @@ fun getCompileTimeConstant( private class ConstantsChecker(private val bindingContext: BindingContext) : KtVisitorVoid() { - var containsNonInlinedVals = false + var containsKotlinConstVals = false override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) { val resolvedCall = expression.getResolvedCall(bindingContext) if (resolvedCall != null) { val callableDescriptor = resolvedCall.resultingDescriptor - if (callableDescriptor is PropertyDescriptor && isInlinedJavaConstProperty(callableDescriptor as VariableDescriptor)) { - containsNonInlinedVals = true + if (callableDescriptor is PropertyDescriptor && callableDescriptor !is JavaPropertyDescriptor && callableDescriptor.isConst) { + containsKotlinConstVals = true } } } override fun visitKtElement(element: KtElement) { - if (!containsNonInlinedVals) { + if (!containsKotlinConstVals) { element.acceptChildren(this) } } } - - -fun isInlinedJavaConstProperty(descriptor: VariableDescriptor): Boolean = - (descriptor as? JavaPropertyDescriptor)?.isConst ?: false \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField.kt b/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField.kt new file mode 100644 index 00000000000..778321d40dd --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField.kt @@ -0,0 +1,14 @@ +// FILE: test.kt +fun test1(a: A) = a.X +fun test2(a: A) = 1 + a.X +fun test3(a: A) = 1 < a.X + +// FILE: A.java +public class A { + public final int X = 42; +} + +// @TestKt.class: +// 0 42 +// 0 43 +// 3 GETFIELD A.X \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv10.kt b/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv10.kt new file mode 100644 index 00000000000..6df005840c8 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv10.kt @@ -0,0 +1,15 @@ +// LANGUAGE_VERSION: 1.0 +// FILE: test.kt +fun test1(a: A) = a.X +fun test2(a: A) = 1 + a.X +fun test3(a: A) = 1 < a.X + +// FILE: A.java +public class A { + public final int X = 42; +} + +// @TestKt.class: +// 0 42 +// 0 43 +// 3 GETFIELD A.X \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv11.kt b/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv11.kt new file mode 100644 index 00000000000..b423253b1d7 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv11.kt @@ -0,0 +1,15 @@ +// LANGUAGE_VERSION: 1.1 +// FILE: test.kt +fun test1(a: A) = a.X +fun test2(a: A) = 1 + a.X +fun test3(a: A) = 1 < a.X + +// FILE: A.java +public class A { + public final int X = 42; +} + +// @TestKt.class: +// 0 42 +// 0 43 +// 3 GETFIELD A.X \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 86d8f514ed4..e5ece964034 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -1010,6 +1010,24 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("noInlineNonStaticJavaField.kt") + public void testNoInlineNonStaticJavaField() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField.kt"); + doTest(fileName); + } + + @TestMetadata("noInlineNonStaticJavaField_lv10.kt") + public void testNoInlineNonStaticJavaField_lv10() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv10.kt"); + doTest(fileName); + } + + @TestMetadata("noInlineNonStaticJavaField_lv11.kt") + public void testNoInlineNonStaticJavaField_lv11() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv11.kt"); + doTest(fileName); + } + @TestMetadata("nullableByteAndShort.kt") public void testNullableByteAndShort() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/nullableByteAndShort.kt");