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.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);