From 1076397530a0ac33c552ad4c25efadf94ff5eaec Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Sun, 18 Dec 2016 11:48:57 +0300 Subject: [PATCH] Minor. Simplify suspension point processing Move type coercing logic from transformer to ExpressionCodegen. For suspension points it's always guaranteed that values returned from suspension points are always can be successfully casted to appropriate type, because they cannot return SUSPENDED marker (it gets processed via CoroutineTransformerMethodVisitor). --- .../kotlin/codegen/ExpressionCodegen.java | 26 +---------- .../CoroutineTransformationClassBuilder.kt | 44 +++---------------- 2 files changed, 9 insertions(+), 61 deletions(-) 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 }