Fix codegen problem with safe-call on suspension point with two receivers

#KT-16145 Fixed
This commit is contained in:
Denis Zharkov
2017-02-03 16:42:19 +03:00
parent a10c6f00f9
commit cc7f0e2d83
9 changed files with 249 additions and 4 deletions
@@ -2943,13 +2943,35 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// The solution is to spill stack just after receiver is loaded (after IFNULL) in case of safe call.
// But the problem is that we should leave the receiver itself on the stack, so we store it in a temporary variable.
if (isSuspensionPoint && isSafeCallOrOnStack) {
int tmpVar = myFrameMap.enterTemp(receiver.type);
boolean bothReceivers =
receiver instanceof StackValue.CallReceiver
&& ((StackValue.CallReceiver) receiver).getDispatchReceiver() != null
&& ((StackValue.CallReceiver) receiver).getExtensionReceiver() != null;
Type firstReceiverType =
bothReceivers
? ((StackValue.CallReceiver) receiver).getDispatchReceiver().type
: receiver.type;
Type secondReceiverType = bothReceivers ? receiver.type : null;
int tmpVarForFirstReceiver = myFrameMap.enterTemp(firstReceiverType);
int tmpVarForSecondReceiver = -1;
if (secondReceiverType != null) {
tmpVarForSecondReceiver = myFrameMap.enterTemp(secondReceiverType);
v.store(tmpVarForSecondReceiver, secondReceiverType);
}
v.store(tmpVarForFirstReceiver, firstReceiverType);
v.store(tmpVar, receiver.type);
addInlineMarker(v, true);
v.load(tmpVar, receiver.type);
myFrameMap.leaveTemp(receiver.type);
v.load(tmpVarForFirstReceiver, firstReceiverType);
if (secondReceiverType != null) {
v.load(tmpVarForSecondReceiver, secondReceiverType);
myFrameMap.leaveTemp(secondReceiverType);
}
myFrameMap.leaveTemp(firstReceiverType);
}
callableMethod.afterReceiverGeneration(v);
@@ -1596,6 +1596,14 @@ public abstract class StackValue {
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
AsmUtil.dup(v, extensionReceiver.type, dispatchReceiver.type);
}
public StackValue getDispatchReceiver() {
return dispatchReceiver;
}
public StackValue getExtensionReceiver() {
return extensionReceiver;
}
}
public abstract static class StackValueWithSimpleReceiver extends StackValue {