From 8baae95531b36273b6e1188bb330f316b9d1346d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 8 Jun 2012 17:58:09 +0200 Subject: [PATCH] if a shared variable is a result of the block, release it only after it has been put #KT-2151 Fixed --- .../jet/codegen/ExpressionCodegen.java | 9 +++++++-- .../org/jetbrains/jet/codegen/StackValue.java | 17 +++++++++++++++-- compiler/testData/codegen/regressions/kt2151.kt | 11 +++++++++++ .../jetbrains/jet/codegen/ClosuresGenTest.java | 4 ++++ 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt2151.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index fe0007114ec..5218d25a1fa 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -917,8 +917,13 @@ public class ExpressionCodegen extends JetVisitor { final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); final Type type = sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType()); if(sharedVarType != null) { - v.aconst(null); - v.store(index, TYPE_OBJECT); + if (answer instanceof StackValue.Shared && index == ((StackValue.Shared) answer).getIndex()) { + ((StackValue.Shared) answer).releaseOnPut(); + } + else { + v.aconst(null); + v.store(index, TYPE_OBJECT); + } } v.visitLocalVariable(var.getName(), type.getDescriptor(), null, blockStart, blockEnd, index); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 0ec3c7b2bf5..8b06d756332 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -924,20 +924,33 @@ public abstract class StackValue { public static class Shared extends StackValue { private final int index; + private boolean isReleaseOnPut = false; public Shared(int index, Type type) { super(type); this.index = index; } + public void releaseOnPut() { + isReleaseOnPut = true; + } + + public int getIndex() { + return index; + } + @Override public void put(Type type, InstructionAdapter v) { v.load(index, JetTypeMapper.TYPE_OBJECT); Type refType = refType(this.type); Type sharedType = sharedTypeForType(this.type); v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor()); - StackValue.onStack(refType).coerce(this.type, v); - StackValue.onStack(this.type).coerce(type, v); + coerce(refType, this.type, v); + coerce(this.type, type, v); + if (isReleaseOnPut) { + v.aconst(null); + v.store(index, JetTypeMapper.TYPE_OBJECT); + } } @Override diff --git a/compiler/testData/codegen/regressions/kt2151.kt b/compiler/testData/codegen/regressions/kt2151.kt new file mode 100644 index 00000000000..5b0da23f6ea --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2151.kt @@ -0,0 +1,11 @@ +fun foo(): String { + return if (true) { + var x = "OK" + fun foo() { x += "fail" } + x + } else "fail" +} + +fun box(): String { + return foo() +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java index f83c43d5fcd..e5591cdc5c3 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java @@ -62,4 +62,8 @@ public class ClosuresGenTest extends CodegenTestCase { public void testEnclosingThis() throws Exception { blackBoxFile("classes/enclosingThis.jet"); } + + public void testKt2151() { + blackBoxFile("regressions/kt2151.kt"); + } }