Call receiver rewrote in lazy way
This commit is contained in:
@@ -24,7 +24,10 @@ import com.intellij.psi.tree.IElementType;
|
|||||||
import com.intellij.util.ArrayUtil;
|
import com.intellij.util.ArrayUtil;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import com.intellij.util.containers.Stack;
|
import com.intellij.util.containers.Stack;
|
||||||
import kotlin.*;
|
import kotlin.ExtensionFunction0;
|
||||||
|
import kotlin.Function1;
|
||||||
|
import kotlin.KotlinPackage;
|
||||||
|
import kotlin.Unit;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.backend.common.CodegenUtil;
|
import org.jetbrains.jet.backend.common.CodegenUtil;
|
||||||
@@ -2337,6 +2340,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue) {
|
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue) {
|
||||||
if (receiverValue instanceof ClassReceiver) {
|
if (receiverValue instanceof ClassReceiver) {
|
||||||
ClassDescriptor receiverDescriptor = ((ClassReceiver) receiverValue).getDeclarationDescriptor();
|
ClassDescriptor receiverDescriptor = ((ClassReceiver) receiverValue).getDeclarationDescriptor();
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
|||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.annotations.AnnotationsPackage;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
@@ -428,11 +427,32 @@ public abstract class StackValue {
|
|||||||
@Nullable CallableMethod callableMethod
|
@Nullable CallableMethod callableMethod
|
||||||
) {
|
) {
|
||||||
if (resolvedCall.getDispatchReceiver().exists() || resolvedCall.getExtensionReceiver().exists() || isLocalFunCall(callableMethod)) {
|
if (resolvedCall.getDispatchReceiver().exists() || resolvedCall.getExtensionReceiver().exists() || isLocalFunCall(callableMethod)) {
|
||||||
return new CallReceiver(resolvedCall, receiver, codegen, callableMethod, true);
|
boolean hasExtensionReceiver = resolvedCall.getExtensionReceiver().exists();
|
||||||
|
StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, true);
|
||||||
|
StackValue dispatchReceiver = genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, false);
|
||||||
|
return new CallReceiver(dispatchReceiver, extensionReceiver,
|
||||||
|
CallReceiver.calcType(resolvedCall, codegen.typeMapper, callableMethod));
|
||||||
}
|
}
|
||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static StackValue genReceiver(@NotNull StackValue receiver, @NotNull ExpressionCodegen codegen, ResolvedCall resolvedCall, @Nullable CallableMethod callableMethod, boolean isExtension) {
|
||||||
|
ReceiverValue receiverValue = isExtension ? resolvedCall.getExtensionReceiver() : resolvedCall.getDispatchReceiver();
|
||||||
|
if (receiver == none()) {
|
||||||
|
if (receiverValue.exists()) {
|
||||||
|
return codegen.generateReceiverValue(receiverValue);
|
||||||
|
} else if (isLocalFunCall(callableMethod) && !isExtension) {
|
||||||
|
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||||
|
StackValue value = codegen.findLocalOrCapturedValue(descriptor.getOriginal());
|
||||||
|
assert value != null : "Local fun should be found in locals or in captured params: " + resolvedCall;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
} else if (receiverValue.exists()) {
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
return none();
|
||||||
|
}
|
||||||
|
|
||||||
@Contract("null -> false")
|
@Contract("null -> false")
|
||||||
private static boolean isLocalFunCall(@Nullable CallableMethod callableMethod) {
|
private static boolean isLocalFunCall(@Nullable CallableMethod callableMethod) {
|
||||||
return callableMethod != null && callableMethod.getGenerateCalleeType() != null;
|
return callableMethod != null && callableMethod.getGenerateCalleeType() != null;
|
||||||
@@ -441,8 +461,7 @@ public abstract class StackValue {
|
|||||||
public static StackValue receiverWithoutReceiverArgument(StackValue receiverWithParameter) {
|
public static StackValue receiverWithoutReceiverArgument(StackValue receiverWithParameter) {
|
||||||
if (receiverWithParameter instanceof CallReceiver) {
|
if (receiverWithParameter instanceof CallReceiver) {
|
||||||
CallReceiver callReceiver = (CallReceiver) receiverWithParameter;
|
CallReceiver callReceiver = (CallReceiver) receiverWithParameter;
|
||||||
return new CallReceiver(callReceiver.resolvedCall, callReceiver.receiver,
|
return new CallReceiver(callReceiver.dispatchReceiver, none(), callReceiver.type);
|
||||||
callReceiver.codegen, callReceiver.callableMethod, false);
|
|
||||||
}
|
}
|
||||||
return receiverWithParameter;
|
return receiverWithParameter;
|
||||||
}
|
}
|
||||||
@@ -1339,28 +1358,20 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class CallReceiver extends StackValue {
|
public static class CallReceiver extends StackValue {
|
||||||
private final ResolvedCall<?> resolvedCall;
|
private final StackValue dispatchReceiver;
|
||||||
private final StackValue receiver;
|
private final StackValue extensionReceiver;
|
||||||
private final ExpressionCodegen codegen;
|
|
||||||
private final CallableMethod callableMethod;
|
|
||||||
private final boolean putReceiverArgumentOnStack;
|
|
||||||
|
|
||||||
public CallReceiver(
|
public CallReceiver(
|
||||||
@NotNull ResolvedCall<?> resolvedCall,
|
@NotNull StackValue dispatchReceiver,
|
||||||
@NotNull StackValue receiver,
|
@NotNull StackValue extensionReceiver,
|
||||||
@NotNull ExpressionCodegen codegen,
|
@NotNull Type type
|
||||||
@Nullable CallableMethod callableMethod,
|
|
||||||
boolean putReceiverArgumentOnStack
|
|
||||||
) {
|
) {
|
||||||
super(calcType(resolvedCall, codegen.typeMapper, callableMethod));
|
super(type);
|
||||||
this.resolvedCall = resolvedCall;
|
this.dispatchReceiver = dispatchReceiver;
|
||||||
this.receiver = receiver;
|
this.extensionReceiver = extensionReceiver;
|
||||||
this.codegen = codegen;
|
|
||||||
this.callableMethod = callableMethod;
|
|
||||||
this.putReceiverArgumentOnStack = putReceiverArgumentOnStack;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type calcType(
|
public static Type calcType(
|
||||||
@NotNull ResolvedCall<?> resolvedCall,
|
@NotNull ResolvedCall<?> resolvedCall,
|
||||||
@NotNull JetTypeMapper typeMapper,
|
@NotNull JetTypeMapper typeMapper,
|
||||||
@Nullable CallableMethod callableMethod
|
@Nullable CallableMethod callableMethod
|
||||||
@@ -1383,65 +1394,20 @@ public abstract class StackValue {
|
|||||||
return Type.VOID_TYPE;
|
return Type.VOID_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
StackValue currentExtensionReceiver = extensionReceiver;
|
||||||
|
boolean hasExtensionReceiver = extensionReceiver != none();
|
||||||
ReceiverValue dispatchReceiver = resolvedCall.getDispatchReceiver();
|
if (extensionReceiver instanceof StackValue.SafeCall) {
|
||||||
ReceiverValue extensionReceiver = resolvedCall.getExtensionReceiver();
|
currentExtensionReceiver.put(currentExtensionReceiver.type, v);
|
||||||
int depth = 0;
|
currentExtensionReceiver = StackValue.onStack(currentExtensionReceiver.type);
|
||||||
|
|
||||||
StackValue currentReceiver = receiver;
|
|
||||||
if (putReceiverArgumentOnStack && extensionReceiver.exists() && receiver instanceof SafeCall) {
|
|
||||||
currentReceiver.put(currentReceiver.type, v);
|
|
||||||
currentReceiver = StackValue.onStack(currentReceiver.type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dispatchReceiver.exists()) {
|
dispatchReceiver.put(hasExtensionReceiver ? dispatchReceiver.type : type, v);
|
||||||
if (!AnnotationsPackage.isPlatformStaticInObject(descriptor)) {
|
|
||||||
if (extensionReceiver.exists()) {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
Type resultType =
|
|
||||||
callableMethod != null ?
|
|
||||||
callableMethod.getOwner() :
|
|
||||||
codegen.typeMapper.mapType(descriptor.getDispatchReceiverParameter().getType());
|
|
||||||
|
|
||||||
codegen.generateReceiverValue(dispatchReceiver).put(resultType, v);
|
currentExtensionReceiver
|
||||||
}
|
.moveToTopOfStack(hasExtensionReceiver ? type : currentExtensionReceiver.type, v, dispatchReceiver.type.getSize());
|
||||||
else {
|
|
||||||
genReceiver(v, dispatchReceiver, type, 0, receiver);
|
|
||||||
}
|
|
||||||
depth = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (isLocalFunCall(callableMethod)) {
|
|
||||||
assert receiver == none() || extensionReceiver.exists() :
|
|
||||||
"Receiver should be present only for local extension function: " + callableMethod;
|
|
||||||
StackValue value = codegen.findLocalOrCapturedValue(descriptor.getOriginal());
|
|
||||||
assert value != null : "Local fun should be found in locals or in captured params: " + resolvedCall;
|
|
||||||
value.put(callableMethod.getGenerateCalleeType(), v);
|
|
||||||
|
|
||||||
depth = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (putReceiverArgumentOnStack && extensionReceiver.exists()) {
|
|
||||||
genReceiver(v, extensionReceiver, type, depth, currentReceiver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void genReceiver(
|
|
||||||
@NotNull InstructionAdapter v,
|
|
||||||
@NotNull ReceiverValue receiverArgument,
|
|
||||||
@NotNull Type type,
|
|
||||||
int depth,
|
|
||||||
@NotNull StackValue receiver
|
|
||||||
) {
|
|
||||||
if (receiver == StackValue.none()) {
|
|
||||||
codegen.generateReceiverValue(receiverArgument).put(type, v);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
receiver.moveToTopOfStack(type, v, depth);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user