From ec649e83c3349a8e09a143ba25ca69c468ed0e15 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Tue, 18 Nov 2014 15:35:06 +0300 Subject: [PATCH] Don't skip receiver with side effects on static calls #KT-6278 Fixed --- .../org/jetbrains/jet/codegen/StackValue.java | 25 ++++++---- .../org/jetbrains/jet/codegen/StackValue.kt | 4 +- .../boxWithStdlib/platformStatic/funAccess.kt | 18 +++++++ .../platformStatic/postfixInc.kt | 47 +++++++++++++++++++ .../boxWithStdlib/platformStatic/prefixInc.kt | 47 +++++++++++++++++++ .../platformStatic/propertyAccess.kt | 47 +++++++++++++++++++ .../platformStatic/propertyInc.kt | 27 ----------- ...lackBoxWithStdlibCodegenTestGenerated.java | 30 +++++++++--- 8 files changed, 200 insertions(+), 45 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/platformStatic/funAccess.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/platformStatic/postfixInc.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/platformStatic/prefixInc.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAccess.kt delete mode 100644 compiler/testData/codegen/boxWithStdlib/platformStatic/propertyInc.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 4026af413d3..b41ec94256b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -100,7 +100,7 @@ public abstract class StackValue { public abstract void putSelector(@NotNull Type type, @NotNull InstructionAdapter v); - public boolean hasReceiver(boolean isRead) { + public boolean isNonStaticAccess(boolean isRead) { return false; } @@ -1073,7 +1073,7 @@ public abstract class StackValue { public final String name; public Field(Type type, Type owner, String name, boolean isStatic, StackValue receiver) { - super(type, isStatic, isStatic, receiver, false); + super(type, isStatic, isStatic, receiver, receiver.hasSideEffects()); this.owner = owner; this.name = name; } @@ -1464,13 +1464,14 @@ public abstract class StackValue { @Override public void putReceiver(@NotNull InstructionAdapter v, boolean isRead) { - if (hasReceiver(isRead)) { - receiver.put(receiver.type, v); + boolean hasReceiver = isNonStaticAccess(isRead); + if (hasReceiver || receiver.hasSideEffects()) { + receiver.put(hasReceiver ? receiver.type : Type.VOID_TYPE, v); } } @Override - public boolean hasReceiver(boolean isRead) { + public boolean isNonStaticAccess(boolean isRead) { return isRead ? !isStaticPut : !isStaticStore; } @@ -1483,7 +1484,7 @@ public abstract class StackValue { if (!withWriteReceiver) { super.dup(v, withWriteReceiver); } else { - int receiverSize = hasReceiver(false) ? receiverSize() : 0; + int receiverSize = isNonStaticAccess(false) ? receiverSize() : 0; switch (receiverSize) { case 0: AsmUtil.dup(v, type); @@ -1531,7 +1532,7 @@ public abstract class StackValue { private final boolean [] isReadOperations; public ComplexReceiver(StackValueWithSimpleReceiver value, boolean [] isReadOperations) { - super(value.type); + super(value.type, value.receiver.hasSideEffects()); this.originalValueWithReceiver = value; this.isReadOperations = isReadOperations; } @@ -1541,9 +1542,9 @@ public abstract class StackValue { @NotNull Type type, @NotNull InstructionAdapter v ) { boolean wasPutted = false; + StackValue receiver = originalValueWithReceiver.receiver; for (boolean operation : isReadOperations) { - if (originalValueWithReceiver.hasReceiver(operation)) { - StackValue receiver = originalValueWithReceiver.receiver; + if (originalValueWithReceiver.isNonStaticAccess(operation)) { if (!wasPutted) { receiver.put(receiver.type, v); wasPutted = true; @@ -1552,6 +1553,10 @@ public abstract class StackValue { } } } + + if (!wasPutted && receiver.hasSideEffects()) { + receiver.put(Type.VOID_TYPE, v); + } } } @@ -1588,7 +1593,7 @@ public abstract class StackValue { } private static boolean bothReceiverStatic(StackValueWithSimpleReceiver originalValue) { - return !(originalValue.hasReceiver(true) || originalValue.hasReceiver(false)); + return !(originalValue.isNonStaticAccess(true) || originalValue.isNonStaticAccess(false)); } @Override diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.kt b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.kt index 9a5b1540f52..0c1cd909980 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.kt +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.kt @@ -43,8 +43,8 @@ class CoercionValue( value.condJump(label, jumpIfFalse, v) } - override fun hasReceiver(isRead: Boolean): Boolean { - return value.hasReceiver(isRead) + override fun isNonStaticAccess(isRead: Boolean): Boolean { + return value.isNonStaticAccess(isRead) } } diff --git a/compiler/testData/codegen/boxWithStdlib/platformStatic/funAccess.kt b/compiler/testData/codegen/boxWithStdlib/platformStatic/funAccess.kt new file mode 100644 index 00000000000..203aa68e337 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/platformStatic/funAccess.kt @@ -0,0 +1,18 @@ +import kotlin.platform.platformStatic + +var holder = "" + +fun getA(): A { + holder += "OK" + return A +} + +object A { + platformStatic fun a(): String { + return holder + } +} + +fun box(): String { + return getA().a() +} diff --git a/compiler/testData/codegen/boxWithStdlib/platformStatic/postfixInc.kt b/compiler/testData/codegen/boxWithStdlib/platformStatic/postfixInc.kt new file mode 100644 index 00000000000..bbbdcee45a4 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/platformStatic/postfixInc.kt @@ -0,0 +1,47 @@ +import kotlin.platform.platformStatic + +object A { + + platformStatic var a: Int = 1 + + var b: Int = 1 + [platformStatic] get + + var c: Int = 1 + [platformStatic] set + +} + +var holder = "" +fun getA(): A { + holder += "getA()" + return A +} + + +fun box(): String { + + var p = A.a++ + if (p != 1 || A.a != 2) return "fail 1" + + p = A.b++ + if (p != 1 || A.b != 2) return "fail 2" + + p = A.c++ + if (p != 1 || A.c != 2) return "fail 3" + + + p = getA().a++ + if (p != 2 || A.a != 3 || holder != "getA()") return "fail 4: $holder" + holder = "" + + p = getA().b++ + if (p != 2 || A.b != 3 || holder != "getA()") return "fail 5: $holder" + holder = "" + + p = getA().c++ + if (p != 2 || A.c != 3 || holder != "getA()") return "fail 6: $holder" + holder = "" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/platformStatic/prefixInc.kt b/compiler/testData/codegen/boxWithStdlib/platformStatic/prefixInc.kt new file mode 100644 index 00000000000..e42089faab9 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/platformStatic/prefixInc.kt @@ -0,0 +1,47 @@ +import kotlin.platform.platformStatic + +object A { + + platformStatic var a: Int = 1 + + var b: Int = 1 + [platformStatic] get + + var c: Int = 1 + [platformStatic] set + +} + +var holder = "" +fun getA(): A { + holder += "getA()" + return A +} + + +fun box(): String { + + var p = ++A.a + if (p != 2 || A.a != 2) return "fail 1" + + p = ++A.b + if (p != 2 || A.b != 2) return "fail 2" + + p = ++A.c + if (p != 2 || A.c != 2) return "fail 3" + + + p = ++getA().a + if (p != 3 || A.a != 3 || holder != "getA()") return "fail 4: $holder" + holder = "" + + p = ++getA().b + if (p != 3 || A.b != 3 || holder != "getA()") return "fail 5: $holder" + holder = "" + + p = ++getA().c + if (p != 3 || A.c != 3 || holder != "getA()") return "fail 6: $holder" + holder = "" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAccess.kt b/compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAccess.kt new file mode 100644 index 00000000000..03c59143a01 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAccess.kt @@ -0,0 +1,47 @@ +import kotlin.platform.platformStatic + +var holder = "" + +fun getA(): A { + holder += "getA()" + return A +} + +object A { + + platformStatic var a: Int = 1 + + var b: Int = 1 + [platformStatic] get + + var c: Int = 1 + [platformStatic] set + +} + + +fun box(): String { + + if (getA().a != 1 || holder != "getA()") return "fail 1: $holder" + holder = "" + + if (getA().b != 1 || holder != "getA()") return "fail 2: $holder" + holder = "" + + if (getA().c != 1 || holder != "getA()") return "fail 3: $holder" + holder = "" + + getA().a = 2 + if (getA().a != 2 || holder != "getA()getA()") return "fail 1: $holder" + holder = "" + + getA().b = 2 + if (getA().b != 2 || holder != "getA()getA()") return "fail 2: $holder" + holder = "" + + getA().c = 2 + if (getA().c != 2 || holder != "getA()getA()") return "fail 3: $holder" + holder = "" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/platformStatic/propertyInc.kt b/compiler/testData/codegen/boxWithStdlib/platformStatic/propertyInc.kt deleted file mode 100644 index 1a7763f0a1c..00000000000 --- a/compiler/testData/codegen/boxWithStdlib/platformStatic/propertyInc.kt +++ /dev/null @@ -1,27 +0,0 @@ -import kotlin.platform.platformStatic - -object A { - - platformStatic var a: Int = 1 - - var b: Int = 1 - [platformStatic] get - - var c: Int = 1 - [platformStatic] set - -} - -fun box(): String { - - A.a++ - if (A.a != 2) return "fail 1" - - A.b++ - if (A.b != 2) return "fail 2" - - A.c++ - if (A.c != 2) return "fail 3" - - return "OK" -} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 3d6facad017..e6a1a29c4bb 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -1658,21 +1658,39 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("funAccess.kt") + public void testFunAccess() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/funAccess.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("inline.kt") public void testInline() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/inline.kt"); doTestWithStdlib(fileName); } - @TestMetadata("propertyAsDefault.kt") - public void testPropertyAsDefault() throws Exception { - String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAsDefault.kt"); + @TestMetadata("postfixInc.kt") + public void testPostfixInc() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/postfixInc.kt"); doTestWithStdlib(fileName); } - @TestMetadata("propertyInc.kt") - public void testPropertyInc() throws Exception { - String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/propertyInc.kt"); + @TestMetadata("prefixInc.kt") + public void testPrefixInc() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/prefixInc.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("propertyAccess.kt") + public void testPropertyAccess() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAccess.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("propertyAsDefault.kt") + public void testPropertyAsDefault() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAsDefault.kt"); doTestWithStdlib(fileName); }