Don't skip receiver with side effects on static calls
#KT-6278 Fixed
This commit is contained in:
@@ -100,7 +100,7 @@ public abstract class StackValue {
|
|||||||
|
|
||||||
public abstract void putSelector(@NotNull Type type, @NotNull InstructionAdapter v);
|
public abstract void putSelector(@NotNull Type type, @NotNull InstructionAdapter v);
|
||||||
|
|
||||||
public boolean hasReceiver(boolean isRead) {
|
public boolean isNonStaticAccess(boolean isRead) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1073,7 +1073,7 @@ public abstract class StackValue {
|
|||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
public Field(Type type, Type owner, String name, boolean isStatic, StackValue receiver) {
|
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.owner = owner;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
@@ -1464,13 +1464,14 @@ public abstract class StackValue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putReceiver(@NotNull InstructionAdapter v, boolean isRead) {
|
public void putReceiver(@NotNull InstructionAdapter v, boolean isRead) {
|
||||||
if (hasReceiver(isRead)) {
|
boolean hasReceiver = isNonStaticAccess(isRead);
|
||||||
receiver.put(receiver.type, v);
|
if (hasReceiver || receiver.hasSideEffects()) {
|
||||||
|
receiver.put(hasReceiver ? receiver.type : Type.VOID_TYPE, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasReceiver(boolean isRead) {
|
public boolean isNonStaticAccess(boolean isRead) {
|
||||||
return isRead ? !isStaticPut : !isStaticStore;
|
return isRead ? !isStaticPut : !isStaticStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1483,7 +1484,7 @@ public abstract class StackValue {
|
|||||||
if (!withWriteReceiver) {
|
if (!withWriteReceiver) {
|
||||||
super.dup(v, withWriteReceiver);
|
super.dup(v, withWriteReceiver);
|
||||||
} else {
|
} else {
|
||||||
int receiverSize = hasReceiver(false) ? receiverSize() : 0;
|
int receiverSize = isNonStaticAccess(false) ? receiverSize() : 0;
|
||||||
switch (receiverSize) {
|
switch (receiverSize) {
|
||||||
case 0:
|
case 0:
|
||||||
AsmUtil.dup(v, type);
|
AsmUtil.dup(v, type);
|
||||||
@@ -1531,7 +1532,7 @@ public abstract class StackValue {
|
|||||||
private final boolean [] isReadOperations;
|
private final boolean [] isReadOperations;
|
||||||
|
|
||||||
public ComplexReceiver(StackValueWithSimpleReceiver value, boolean [] isReadOperations) {
|
public ComplexReceiver(StackValueWithSimpleReceiver value, boolean [] isReadOperations) {
|
||||||
super(value.type);
|
super(value.type, value.receiver.hasSideEffects());
|
||||||
this.originalValueWithReceiver = value;
|
this.originalValueWithReceiver = value;
|
||||||
this.isReadOperations = isReadOperations;
|
this.isReadOperations = isReadOperations;
|
||||||
}
|
}
|
||||||
@@ -1541,9 +1542,9 @@ public abstract class StackValue {
|
|||||||
@NotNull Type type, @NotNull InstructionAdapter v
|
@NotNull Type type, @NotNull InstructionAdapter v
|
||||||
) {
|
) {
|
||||||
boolean wasPutted = false;
|
boolean wasPutted = false;
|
||||||
|
StackValue receiver = originalValueWithReceiver.receiver;
|
||||||
for (boolean operation : isReadOperations) {
|
for (boolean operation : isReadOperations) {
|
||||||
if (originalValueWithReceiver.hasReceiver(operation)) {
|
if (originalValueWithReceiver.isNonStaticAccess(operation)) {
|
||||||
StackValue receiver = originalValueWithReceiver.receiver;
|
|
||||||
if (!wasPutted) {
|
if (!wasPutted) {
|
||||||
receiver.put(receiver.type, v);
|
receiver.put(receiver.type, v);
|
||||||
wasPutted = true;
|
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) {
|
private static boolean bothReceiverStatic(StackValueWithSimpleReceiver originalValue) {
|
||||||
return !(originalValue.hasReceiver(true) || originalValue.hasReceiver(false));
|
return !(originalValue.isNonStaticAccess(true) || originalValue.isNonStaticAccess(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ class CoercionValue(
|
|||||||
value.condJump(label, jumpIfFalse, v)
|
value.condJump(label, jumpIfFalse, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasReceiver(isRead: Boolean): Boolean {
|
override fun isNonStaticAccess(isRead: Boolean): Boolean {
|
||||||
return value.hasReceiver(isRead)
|
return value.isNonStaticAccess(isRead)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
+24
-6
@@ -1658,21 +1658,39 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
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")
|
@TestMetadata("inline.kt")
|
||||||
public void testInline() throws Exception {
|
public void testInline() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/inline.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/inline.kt");
|
||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("propertyAsDefault.kt")
|
@TestMetadata("postfixInc.kt")
|
||||||
public void testPropertyAsDefault() throws Exception {
|
public void testPostfixInc() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAsDefault.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/postfixInc.kt");
|
||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("propertyInc.kt")
|
@TestMetadata("prefixInc.kt")
|
||||||
public void testPropertyInc() throws Exception {
|
public void testPrefixInc() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/propertyInc.kt");
|
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);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user