diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index d4cb79c672f..aa0ae1ac7cd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license * that can be found in the license/LICENSE.txt file. */ @@ -4041,7 +4041,7 @@ public class ExpressionCodegen extends KtVisitor impleme else if (property.hasModifier(KtTokens.LATEINIT_KEYWORD)) { initializeLocalVariable(property, null); } - else if (!property.isVar()) { + else { initializeLocalVariableWithFakeDefaultValue(property); } @@ -4194,10 +4194,10 @@ public class ExpressionCodegen extends KtVisitor impleme private void initializeLocalVariableWithFakeDefaultValue(@NotNull KtProperty variableDeclaration) { LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) getVariableDescriptorNotNull(variableDeclaration); - // For this kind of variables we generate boxes, i.e. we regard them as - if (isCapturedInClosureWithExactlyOnceEffect(bindingContext, variableDescriptor)) return; + // Boxed variables already have a value + if (isBoxedLocalCapturedInClosure(bindingContext, variableDescriptor)) return; - assert !variableDeclaration.isVar() && !variableDeclaration.hasDelegateExpressionOrInitializer() && + assert !variableDeclaration.hasDelegateExpressionOrInitializer() && !variableDescriptor.isLateInit() : variableDeclaration.getText() + " in not variable declaration without initializer"; KotlinType kotlinType = variableDescriptor.getType(); diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/boxingVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/boxingVar.kt new file mode 100644 index 00000000000..feffd901d03 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/boxingVar.kt @@ -0,0 +1,12 @@ +// IGNORE_BACKEND: JVM_IR + +fun test(): java.lang.Integer { + var c: java.lang.Integer + run { + c = java.lang.Integer(1) + } + return c +} + +// 1 ASTORE 0 +// 1 LOCALVARIABLE c Lkotlin/jvm/internal/Ref\$ObjectRef; L1 L11 0 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/contractVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/contractVar.kt new file mode 100644 index 00000000000..528bc393c6b --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/contractVar.kt @@ -0,0 +1,25 @@ +// IGNORE_BACKEND: JVM_IR + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +@ExperimentalContracts +fun test(): Char { + var c: Char + doIt { + c = ' ' + } + return c +} + +@ExperimentalContracts +fun doIt(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +// 0 ISTORE 0 +// 1 LOCALVARIABLE c Lkotlin/jvm/internal/Ref\$CharRef; L1 L3 0 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/genericsVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/genericsVar.kt new file mode 100644 index 00000000000..711caf60550 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/genericsVar.kt @@ -0,0 +1,18 @@ +// IGNORE_BACKEND: JVM_IR + +inline fun foo(default: T): T { + var t: T + run { + t = default + } + return t +} + +fun test() { + foo(0.0f) +} + +// two in foo and two in test + +// 2 ASTORE 2 +// 1 LOCALVARIABLE t\$iv Lkotlin/jvm/internal/Ref\$ObjectRef; L3 L13 2 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementVar.kt new file mode 100644 index 00000000000..e718f6fcf16 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementVar.kt @@ -0,0 +1,16 @@ +// IGNORE_BACKEND: JVM_IR + +import kotlin.random.Random + +fun test(): Char { + var c: Char + if (Random.nextBoolean()) { + c = '1' + } else { + c = '2' + } + return c +} + +// 3 ISTORE 0 +// 1 LOCALVARIABLE c C L1 L7 0 diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementWithoutBlockVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementWithoutBlockVar.kt new file mode 100644 index 00000000000..e9f964995e6 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementWithoutBlockVar.kt @@ -0,0 +1,16 @@ +// IGNORE_BACKEND: JVM_IR + +import kotlin.random.Random + +fun test(): Char { + var c: Char + if (Random.nextBoolean()) + c = '1' + else + c = '2' + + return c +} + +// 3 ISTORE 0 +// 1 LOCALVARIABLE c C L1 L5 0 diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/inlineClassVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/inlineClassVar.kt new file mode 100644 index 00000000000..9664a162f40 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/inlineClassVar.kt @@ -0,0 +1,12 @@ +// IGNORE_BACKEND: JVM_IR + +fun test(): UInt { + var c: UInt + run { + c = 1u + } + return c +} + +// 1 ASTORE 0 +// 1 LOCALVARIABLE c Lkotlin/jvm/internal/Ref\$IntRef; L1 L11 0 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/var.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/runVar.kt similarity index 100% rename from compiler/testData/codegen/bytecodeText/localInitializationLVT/var.kt rename to compiler/testData/codegen/bytecodeText/localInitializationLVT/runVar.kt diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/singleBlockVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/singleBlockVar.kt new file mode 100644 index 00000000000..d97dd063053 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/singleBlockVar.kt @@ -0,0 +1,23 @@ +// IGNORE_BACKEND: JVM_IR + +fun test(): Char { + var c: Char + val l = Any() + val l1 = Any() + val l2 = Any() + val l3 = Any() + val l4 = Any() + val l5 = Any() + val l6 = Any() + val l7 = Any() + val l8 = Any() + val l11 = Any() + val l12 = Any() + val l13 = Any() + val l14 = Any() + c = '1' + return c +} + +// 2 ISTORE 0 +// 1 LOCALVARIABLE c C L1 L16 0 diff --git a/compiler/testData/codegen/bytecodeText/localInitializationLVT/whenStatementVar.kt b/compiler/testData/codegen/bytecodeText/localInitializationLVT/whenStatementVar.kt new file mode 100644 index 00000000000..4aedae6d4fd --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/localInitializationLVT/whenStatementVar.kt @@ -0,0 +1,22 @@ +// IGNORE_BACKEND: JVM_IR + +fun test(i: Int): Char { + var c: Char + when (i) { + 1 -> c = '1' + 2 -> c = '2' + 3 -> c = '3' + 4 -> c = '4' + 5 -> c = '5' + 6 -> c = '6' + 7 -> c = '7' + 8 -> c = '8' + 9 -> c = '9' + 0 -> c = '0' + else -> c = ' ' + } + return c +} + +// 12 ISTORE 1 +// 1 LOCALVARIABLE c C L1 L16 1 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 6555314a5fd..1dc515746b7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -2612,31 +2612,61 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/boxing.kt"); } + @TestMetadata("boxingVar.kt") + public void testBoxingVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/boxingVar.kt"); + } + @TestMetadata("contract.kt") public void testContract() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/contract.kt"); } + @TestMetadata("contractVar.kt") + public void testContractVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/contractVar.kt"); + } + @TestMetadata("generics.kt") public void testGenerics() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/generics.kt"); } + @TestMetadata("genericsVar.kt") + public void testGenericsVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/genericsVar.kt"); + } + @TestMetadata("ifStatement.kt") public void testIfStatement() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatement.kt"); } + @TestMetadata("ifStatementVar.kt") + public void testIfStatementVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementVar.kt"); + } + @TestMetadata("ifStatementWithoutBlock.kt") public void testIfStatementWithoutBlock() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementWithoutBlock.kt"); } + @TestMetadata("ifStatementWithoutBlockVar.kt") + public void testIfStatementWithoutBlockVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementWithoutBlockVar.kt"); + } + @TestMetadata("inlineClass.kt") public void testInlineClass() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/inlineClass.kt"); } + @TestMetadata("inlineClassVar.kt") + public void testInlineClassVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/inlineClassVar.kt"); + } + @TestMetadata("lateinit.kt") public void testLateinit() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/lateinit.kt"); @@ -2647,20 +2677,30 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/run.kt"); } + @TestMetadata("runVar.kt") + public void testRunVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/runVar.kt"); + } + @TestMetadata("singleBlock.kt") public void testSingleBlock() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/singleBlock.kt"); } - @TestMetadata("var.kt") - public void testVar() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/var.kt"); + @TestMetadata("singleBlockVar.kt") + public void testSingleBlockVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/singleBlockVar.kt"); } @TestMetadata("whenStatement.kt") public void testWhenStatement() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/whenStatement.kt"); } + + @TestMetadata("whenStatementVar.kt") + public void testWhenStatementVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/whenStatementVar.kt"); + } } @TestMetadata("compiler/testData/codegen/bytecodeText/multifileClasses") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/IrBytecodeTextTestGenerated.java index c89d2f8face..699c4eb0528 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/IrBytecodeTextTestGenerated.java @@ -2612,31 +2612,61 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/boxing.kt"); } + @TestMetadata("boxingVar.kt") + public void testBoxingVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/boxingVar.kt"); + } + @TestMetadata("contract.kt") public void testContract() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/contract.kt"); } + @TestMetadata("contractVar.kt") + public void testContractVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/contractVar.kt"); + } + @TestMetadata("generics.kt") public void testGenerics() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/generics.kt"); } + @TestMetadata("genericsVar.kt") + public void testGenericsVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/genericsVar.kt"); + } + @TestMetadata("ifStatement.kt") public void testIfStatement() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatement.kt"); } + @TestMetadata("ifStatementVar.kt") + public void testIfStatementVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementVar.kt"); + } + @TestMetadata("ifStatementWithoutBlock.kt") public void testIfStatementWithoutBlock() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementWithoutBlock.kt"); } + @TestMetadata("ifStatementWithoutBlockVar.kt") + public void testIfStatementWithoutBlockVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/ifStatementWithoutBlockVar.kt"); + } + @TestMetadata("inlineClass.kt") public void testInlineClass() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/inlineClass.kt"); } + @TestMetadata("inlineClassVar.kt") + public void testInlineClassVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/inlineClassVar.kt"); + } + @TestMetadata("lateinit.kt") public void testLateinit() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/lateinit.kt"); @@ -2647,20 +2677,30 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/run.kt"); } + @TestMetadata("runVar.kt") + public void testRunVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/runVar.kt"); + } + @TestMetadata("singleBlock.kt") public void testSingleBlock() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/singleBlock.kt"); } - @TestMetadata("var.kt") - public void testVar() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/var.kt"); + @TestMetadata("singleBlockVar.kt") + public void testSingleBlockVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/singleBlockVar.kt"); } @TestMetadata("whenStatement.kt") public void testWhenStatement() throws Exception { runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/whenStatement.kt"); } + + @TestMetadata("whenStatementVar.kt") + public void testWhenStatementVar() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/localInitializationLVT/whenStatementVar.kt"); + } } @TestMetadata("compiler/testData/codegen/bytecodeText/multifileClasses")