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:
Denis Zharkov
2017-01-12 15:38:59 +03:00
parent 2286027bed
commit 1f0d0028b2
2 changed files with 13 additions and 38 deletions
@@ -60,6 +60,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JvmAbi;
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.psi.*;
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.myFrameMap = frameMap;
this.context = context;
FunctionDescriptor originalSuspendDescriptor = getOriginalSuspendDescriptor(context);
if (originalSuspendDescriptor != null && originalSuspendDescriptor.getReturnType() != null) {
this.returnType = getBoxedReturnTypeForSuspend(originalSuspendDescriptor);
}
else {
this.returnType = returnType;
}
this.returnType = returnType;
this.parentCodegen = parentCodegen;
this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
}
@NotNull
private static Type getBoxedReturnTypeForSuspend(FunctionDescriptor descriptorForSuspend) {
return AsmTypes.OBJECT_TYPE;
}
@Nullable
private static FunctionDescriptor getOriginalSuspendDescriptor(MethodContext context) {
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
@@ -2236,7 +2225,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor containingFunction =
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
//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 {
//local
return null;
@@ -2248,25 +2237,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
assert element != null : "Expression should be not null " + expression.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;
}
@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) {
boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction;
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
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
Type typeForExpression =
@@ -2796,21 +2778,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall);
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;
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
}
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.binding.CodegenBinding;
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.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
@@ -377,6 +378,12 @@ public class KotlinTypeMapper {
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 (sw != null) {
sw.writeAsmType(Type.VOID_TYPE);