diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index ce1a51f0b4f..f4f1b71bcb4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2781,11 +2781,6 @@ public class ExpressionCodegen extends KtVisitor impleme StackValue result = callable.invokeMethodWithArguments(resolvedCall, receiver, this); - if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext)) { - // Suspension points should behave like they leave actual values on stack, while real methods return VOID - return new OperationStackValue(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda()); - } - if (bindingContext.get(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall()) != null) { // Suspend function's calls inside another suspend function should behave like they leave values of correct type, // while real methods return java/lang/Object. @@ -2907,11 +2902,11 @@ public class ExpressionCodegen extends KtVisitor impleme } if (isSuspensionPoint) { - v.tconst(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall)); v.invokestatic( CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER, CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME, - "(Ljava/lang/Class;)V", false); + "()V", false + ); } callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this); @@ -2930,23 +2925,6 @@ public class ExpressionCodegen extends KtVisitor impleme } } - @NotNull - private Type getSuspensionBoxedReturnTypeByResolvedCall(@NotNull ResolvedCall resolvedCall) { - assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor - : "Suspension point resolved call should be built on SimpleFunctionDescriptor"; - - FunctionDescriptor initialSignature = - ((SimpleFunctionDescriptor) resolvedCall.getResultingDescriptor()) - .getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION); - - assert initialSignature != null : "Initial signature must be not null for suspension point"; - - KotlinType returnType = initialSignature.getReturnType(); - - assert returnType != null : "Return type of suspension point should not be null"; - return typeMapper.mapType(TypeUtils.makeNullable(returnType)); - } - @NotNull private CallGenerator getOrCreateCallGenerator( @NotNull CallableDescriptor descriptor, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt index 09f3ca3a8d9..db8f600f3a3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt @@ -162,36 +162,12 @@ class CoroutineTransformerMethodVisitor( } AFTER_SUSPENSION_POINT_MARKER_NAME -> { - assert(beforeSuspensionPointMarkerStack.isNotEmpty()) { "Expected non-empty stack beforeSuspensionPointMarkerStack" } - val beforeSuspensionPointMarker = beforeSuspensionPointMarkerStack.pop() - assert(beforeSuspensionPointMarker.previous is LdcInsnNode) { - "Instruction before BEFORE_SUSPENSION_POINT_MARKER_NAME should be LDC with expected return type, " + - "but ${beforeSuspensionPointMarker.previous} was found" - } - - val fakeReturnValueInsns = mutableListOf() - - val suspensionPoint = SuspensionPoint( - suspensionCallBegin = beforeSuspensionPointMarker, - suspensionCallEnd = methodInsn, - fakeReturnValueInsns = fakeReturnValueInsns, - returnType = (beforeSuspensionPointMarker.previous as LdcInsnNode).cst as Type) - suspensionPoints.add(suspensionPoint) - - // Drop type info from marker - methodNode.instructions.remove(beforeSuspensionPointMarker.previous) - beforeSuspensionPointMarker.desc = "()V" - - assert(suspensionPoint.returnType != Type.VOID_TYPE) { "Suspension point can't be VOID" } - - // Checkcast only is needed to tell analyzer what type exactly should be returned from suspension point - // This type is used when for restoring spilled variables into fields - val checkCast = TypeInsnNode(Opcodes.CHECKCAST, suspensionPoint.returnType.internalName) - methodNode.instructions.insertBefore( - suspensionPoint.suspensionCallEnd, checkCast + suspensionPoints.add( + SuspensionPoint( + suspensionCallBegin = beforeSuspensionPointMarkerStack.pop(), + suspensionCallEnd = methodInsn + ) ) - - fakeReturnValueInsns.add(checkCast) } } } @@ -224,7 +200,7 @@ class CoroutineTransformerMethodVisitor( for (suspension in suspensionPoints) { val suspensionCallBegin = suspension.suspensionCallBegin val suspensionCallEnd = suspension.suspensionCallEnd - assert(frames[suspensionCallEnd.next.index()]?.stackSize == (if (suspension.returnType.sort == Type.VOID) 0 else 1)) { + assert(frames[suspensionCallEnd.next.index()]?.stackSize == 1) { "Stack should be spilled before suspension call" } @@ -338,9 +314,6 @@ class CoroutineTransformerMethodVisitor( ) ) - // Drop default value that purpose was to simulate returned value by suspension method - suspension.fakeReturnValueInsns.forEach { methodNode.instructions.remove(it) } - insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter { dup() load(suspendMarkerVarIndex, AsmTypes.OBJECT_TYPE) @@ -371,7 +344,6 @@ class CoroutineTransformerMethodVisitor( load(1, AsmTypes.OBJECT_TYPE) visitLabel(continuationLabelAfterLoadedResult.label) - StackValue.coerce(AsmTypes.OBJECT_TYPE, suspension.returnType, this) }) } @@ -500,9 +472,7 @@ private class SuspensionPoint( // INVOKESTATIC beforeSuspensionMarker val suspensionCallBegin: AbstractInsnNode, // INVOKESTATIC afterSuspensionMarker - val suspensionCallEnd: AbstractInsnNode, - val fakeReturnValueInsns: List, - val returnType: Type + val suspensionCallEnd: AbstractInsnNode ) { lateinit var tryCatchBlocksContinuationLabel: LabelNode }