From 58c7c7aea1e4de0b6199b28b04dc643c1c6cb3be Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Sat, 2 Jun 2012 22:41:37 +0200 Subject: [PATCH] don't generate direct increment and similar bytecodes for variables which are captured in closure (KT-1980) --- .../jet/codegen/ExpressionCodegen.java | 3 ++ .../jetbrains/jet/codegen/JetTypeMapper.java | 20 ++++++------- .../testData/codegen/regressions/kt1980.kt | 29 +++++++++++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 5 ++++ 4 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt1980.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index c86efb3f53d..ffcb441b723 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1635,6 +1635,9 @@ public class ExpressionCodegen extends JetVisitor { public int indexOfLocal(JetReferenceExpression lhs) { final DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, lhs); + if (typeMapper.isVarCapturedInClosure(declarationDescriptor)) { + return -1; + } return lookupLocal(declarationDescriptor); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index dc89856b57e..a34c40a16c6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -1033,17 +1033,17 @@ public class JetTypeMapper { else if (descriptor instanceof FunctionDescriptor) { return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE)); } - else if (descriptor instanceof VariableDescriptor) { - VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; - Boolean aBoolean = bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor); - if (aBoolean != null && aBoolean && variableDescriptor.isVar()) { - JetType outType = variableDescriptor.getType(); - return StackValue.sharedTypeForType(mapType(outType, MapTypeMode.VALUE)); - } - else { - return null; - } + else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(descriptor)) { + JetType outType = ((VariableDescriptor) descriptor).getType(); + return StackValue.sharedTypeForType(mapType(outType, MapTypeMode.VALUE)); } return null; } + + public boolean isVarCapturedInClosure(DeclarationDescriptor descriptor) { + if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false; + VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; + Boolean aBoolean = bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor); + return aBoolean != null && aBoolean && variableDescriptor.isVar(); + } } diff --git a/compiler/testData/codegen/regressions/kt1980.kt b/compiler/testData/codegen/regressions/kt1980.kt new file mode 100644 index 00000000000..a69274619ff --- /dev/null +++ b/compiler/testData/codegen/regressions/kt1980.kt @@ -0,0 +1,29 @@ +import java.util.* + +public inline fun Int.times(body : () -> Unit) { + var count = this; + while (count > 0) { + body() + count-- + } +} + +fun calc() : Int { + val a = ArrayList<()->Int>() + 2.times { + var j = 1 + a.add({ j }) + ++j + } + var sum = 0 + for (f in a) { + val g = f as () -> Int + sum += g() + } + return sum +} + +fun box() : String { + val x = calc() + return if (x == 4) "OK" else x.toString() +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index d612376f659..321a62c0c7f 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -391,4 +391,9 @@ public class ClassGenTest extends CodegenTestCase { createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS); blackBoxFile("regressions/kt1918.kt"); } + + public void testKt1980() throws Exception { + createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS); + blackBoxFile("regressions/kt1980.kt"); + } }