Minor. Simplify coroutine related code in ExpressionCodegen
After previous change (treating suspend function as they return j/l/Object) most of existing hacks concerning suspend functions' return type became unnecessary
This commit is contained in:
@@ -60,6 +60,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||||
@@ -156,24 +157,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
this.v = new InstructionAdapter(mv);
|
this.v = new InstructionAdapter(mv);
|
||||||
this.myFrameMap = frameMap;
|
this.myFrameMap = frameMap;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.returnType = returnType;
|
||||||
FunctionDescriptor originalSuspendDescriptor = getOriginalSuspendDescriptor(context);
|
|
||||||
if (originalSuspendDescriptor != null && originalSuspendDescriptor.getReturnType() != null) {
|
|
||||||
this.returnType = getBoxedReturnTypeForSuspend(originalSuspendDescriptor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.returnType = returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.parentCodegen = parentCodegen;
|
this.parentCodegen = parentCodegen;
|
||||||
this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
|
this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static Type getBoxedReturnTypeForSuspend(FunctionDescriptor descriptorForSuspend) {
|
|
||||||
return AsmTypes.OBJECT_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static FunctionDescriptor getOriginalSuspendDescriptor(MethodContext context) {
|
private static FunctionDescriptor getOriginalSuspendDescriptor(MethodContext context) {
|
||||||
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
|
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
|
||||||
@@ -2236,7 +2225,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
FunctionDescriptor containingFunction =
|
FunctionDescriptor containingFunction =
|
||||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
||||||
//FIRST_FUN_LABEL to prevent clashing with existing labels
|
//FIRST_FUN_LABEL to prevent clashing with existing labels
|
||||||
return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL);
|
return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL);
|
||||||
} else {
|
} else {
|
||||||
//local
|
//local
|
||||||
return null;
|
return null;
|
||||||
@@ -2248,25 +2237,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
|
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
|
||||||
assert element != null : "Expression should be not null " + expression.getText();
|
assert element != null : "Expression should be not null " + expression.getText();
|
||||||
assert elementDescriptor != null : "Descriptor should be not null: " + element.getText();
|
assert elementDescriptor != null : "Descriptor should be not null: " + element.getText();
|
||||||
return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(elementDescriptor), expression.getLabelName());
|
return new NonLocalReturnInfo(typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Type getReturnTypeForNonLocalReturn(DeclarationDescriptor elementDescriptor) {
|
|
||||||
return elementDescriptor instanceof FunctionDescriptor && ((FunctionDescriptor) elementDescriptor).isSuspend()
|
|
||||||
? getBoxedReturnTypeForSuspend((FunctionDescriptor) elementDescriptor)
|
|
||||||
: typeMapper.mapReturnType((CallableDescriptor) elementDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void returnExpression(KtExpression expr) {
|
public void returnExpression(KtExpression expr) {
|
||||||
boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction;
|
boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction;
|
||||||
|
|
||||||
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
|
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
|
||||||
boolean isVoidCoroutineLambda =
|
boolean isVoidCoroutineLambda =
|
||||||
originalCoroutineDescriptor != null && typeMapper.mapReturnType(originalCoroutineDescriptor).getSort() == Type.VOID;
|
originalCoroutineDescriptor != null && TypeSignatureMappingKt.hasVoidReturnType(originalCoroutineDescriptor);
|
||||||
|
|
||||||
// If generating body for named block-bodied function or Unit-typed coroutine lambda, generate it as sequence of statements
|
// If generating body for named block-bodied function or Unit-typed coroutine lambda, generate it as sequence of statements
|
||||||
Type typeForExpression =
|
Type typeForExpression =
|
||||||
@@ -2796,21 +2778,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall);
|
Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall);
|
||||||
|
|
||||||
|
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||||
StackValue result = callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
|
||||||
|
|
||||||
if (resolvedCall.getResultingDescriptor() instanceof FunctionDescriptor &&
|
|
||||||
((FunctionDescriptor) resolvedCall.getResultingDescriptor()).isSuspend() &&
|
|
||||||
!CoroutineCodegenUtilKt.isSuspensionPointInStateMachine(resolvedCall, bindingContext)) {
|
|
||||||
// Suspend function's tail calls inside another suspend function should behave like they leave values of correct type,
|
|
||||||
// while real methods return java/lang/Object.
|
|
||||||
// NB: They are always in return position at the moment.
|
|
||||||
// If we didn't do this, StackValue.coerce would add proper CHECKCAST that would've failed in case of callee function
|
|
||||||
// returning SUSPENDED marker, which is instance of java/lang/Object.
|
|
||||||
return new OperationStackValue(returnType, ((OperationStackValue) result).getLambda());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackValue getContinuationParameterFromEnclosingSuspendFunction(@NotNull ResolvedCall<?> resolvedCall) {
|
private StackValue getContinuationParameterFromEnclosingSuspendFunction(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
|
|||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||||
import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory;
|
import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory;
|
||||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||||
@@ -377,6 +378,12 @@ public class KotlinTypeMapper {
|
|||||||
return Type.VOID_TYPE;
|
return Type.VOID_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (descriptor instanceof SimpleFunctionDescriptor && ((SimpleFunctionDescriptor) descriptor).isSuspend() &&
|
||||||
|
((SimpleFunctionDescriptor) descriptor).getUserData(
|
||||||
|
CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) == null) {
|
||||||
|
return mapReturnType(CoroutineCodegenUtilKt.createJvmSuspendFunctionView((SimpleFunctionDescriptor) descriptor), sw);
|
||||||
|
}
|
||||||
|
|
||||||
if (TypeSignatureMappingKt.hasVoidReturnType(descriptor)) {
|
if (TypeSignatureMappingKt.hasVoidReturnType(descriptor)) {
|
||||||
if (sw != null) {
|
if (sw != null) {
|
||||||
sw.writeAsmType(Type.VOID_TYPE);
|
sw.writeAsmType(Type.VOID_TYPE);
|
||||||
|
|||||||
Reference in New Issue
Block a user