diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt index 0444d89355d..b0333d0d2f4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt @@ -64,49 +64,7 @@ class CoroutineCodegen( typeMapper.mapType(parameter.type).descriptor, null, null) } - val classDescriptor = closureContext.contextDescriptor - - // protected fun doResume(result, throwable) - val doResumeDescriptor = - SimpleFunctionDescriptorImpl.create( - classDescriptor, Annotations.EMPTY, Name.identifier("doResume"), CallableMemberDescriptor.Kind.DECLARATION, - funDescriptor.source - ).apply doResume@{ - initialize( - /* receiverParameterType = */ null, - classDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - listOf( - ValueParameterDescriptorImpl( - this@doResume, null, 0, Annotations.EMPTY, Name.identifier("data"), - module.builtIns.nullableAnyType, - /* isDefault = */ false, /* isCrossinline = */ false, - /* isNoinline = */ false, /* isCoroutine = */ false, - /* varargElementType = */ null, SourceElement.NO_SOURCE - ), - ValueParameterDescriptorImpl( - this@doResume, null, 1, Annotations.EMPTY, Name.identifier("throwable"), - module.builtIns.throwable.defaultType.makeNullable(), - /* isDefault = */ false, /* isCrossinline = */ false, - /* isNoinline = */ false, /* isCoroutine = */ false, - /* varargElementType = */ null, SourceElement.NO_SOURCE - ) - ), - module.builtIns.unitType, - Modality.FINAL, - Visibilities.PROTECTED - ) - } - - functionCodegen.generateMethod(OtherOrigin(element), doResumeDescriptor, - object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) { - override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) { - codegen.v.visitAnnotation(CONTINUATION_METHOD_ANNOTATION_DESC, true).visitEnd() - codegen.initializeCoroutineParameters() - super.doGenerateBody(codegen, signature) - generateExceptionHandlingBlock(codegen) - } - }) + generateDoResume() functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, funDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) { @@ -188,17 +146,24 @@ class CoroutineCodegen( val mappedType = typeMapper.mapType(parameter.type) val newIndex = myFrameMap.enter(parameter, mappedType) - StackValue.field(parameter.getFieldInfoForCoroutineLambdaParameter(), generateThisOrOuter(context.thisDescriptor, false)) - .put(mappedType, v) + generateLoadField(parameter.getFieldInfoForCoroutineLambdaParameter()) v.store(newIndex, mappedType) } } + private fun ExpressionCodegen.generateLoadField(fieldInfo: FieldInfo) { + StackValue.field(fieldInfo, generateThisOrOuter(context.thisDescriptor, false)).put(fieldInfo.fieldType, v) + } + private fun ValueParameterDescriptor.getFieldInfoForCoroutineLambdaParameter() = + createHiddenFieldInfo(type, COROUTINE_LAMBDA_PARAMETER_PREFIX + index) + + private fun createHiddenFieldInfo(type: KotlinType, name: String) = FieldInfo.createForHiddenField( typeMapper.mapClass(closureContext.thisDescriptor), - typeMapper.mapType(returnType!!), - COROUTINE_LAMBDA_PARAMETER_PREFIX + index) + typeMapper.mapType(type), + name + ) private fun generateExceptionHandlingBlock(codegen: ExpressionCodegen) { val handleExceptionFunction = @@ -220,6 +185,52 @@ class CoroutineCodegen( codegen.v.areturn(Type.VOID_TYPE) } + private fun generateDoResume() { + val classDescriptor = closureContext.contextDescriptor + + // protected fun doResume(result, throwable) + val doResumeDescriptor = + SimpleFunctionDescriptorImpl.create( + classDescriptor, Annotations.EMPTY, Name.identifier("doResume"), CallableMemberDescriptor.Kind.DECLARATION, + funDescriptor.source + ).apply doResume@{ + initialize( + /* receiverParameterType = */ null, + classDescriptor.thisAsReceiverParameter, + /* typeParameters = */ emptyList(), + listOf( + ValueParameterDescriptorImpl( + this@doResume, null, 0, Annotations.EMPTY, Name.identifier("data"), + module.builtIns.nullableAnyType, + /* isDefault = */ false, /* isCrossinline = */ false, + /* isNoinline = */ false, /* isCoroutine = */ false, + /* varargElementType = */ null, SourceElement.NO_SOURCE + ), + ValueParameterDescriptorImpl( + this@doResume, null, 1, Annotations.EMPTY, Name.identifier("throwable"), + module.builtIns.throwable.defaultType.makeNullable(), + /* isDefault = */ false, /* isCrossinline = */ false, + /* isNoinline = */ false, /* isCoroutine = */ false, + /* varargElementType = */ null, SourceElement.NO_SOURCE + ) + ), + module.builtIns.unitType, + Modality.FINAL, + Visibilities.PROTECTED + ) + } + + functionCodegen.generateMethod(OtherOrigin(element), doResumeDescriptor, + object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) { + override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) { + codegen.v.visitAnnotation(CONTINUATION_METHOD_ANNOTATION_DESC, true).visitEnd() + codegen.initializeCoroutineParameters() + super.doGenerateBody(codegen, signature) + generateExceptionHandlingBlock(codegen) + } + }) + } + private fun InstructionAdapter.setLabelValue(value: Int) { load(0, AsmTypes.OBJECT_TYPE) iconst(value) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt index 406613d3899..3c54010719a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.DelegatingBindingTrace import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument @@ -120,24 +121,40 @@ fun createResolvedCallForHandleExceptionCall( val exceptionArgument = CallMaker.makeValueArgument(psiFactory.createExpression("exception")) val continuationThisArgument = CallMaker.makeValueArgument(psiFactory.createExpression("this")) - val valueArguments = listOf(exceptionArgument, continuationThisArgument) - val call = CallMaker.makeCall(callElement, null, null, null, valueArguments) + val resolvedCall = + createFakeResolvedCall( + callElement, + coroutineLambdaDescriptor, + handleExceptionFunction, + listOf(exceptionArgument, continuationThisArgument) + ) + + return HandleResultCallContext( + resolvedCall, exceptionArgument.getArgumentExpression()!!, continuationThisArgument.getArgumentExpression()!!) +} + +private fun createFakeResolvedCall( + element: KtElement, + coroutineLambdaDescriptor: FunctionDescriptor, + descriptor: SimpleFunctionDescriptor, + valueArguments: List +): ResolvedCallImpl { + val call = CallMaker.makeCall(element, null, null, null, valueArguments) val resolvedCall = ResolvedCallImpl( call, - handleExceptionFunction, + descriptor, coroutineLambdaDescriptor.extensionReceiverParameter!!.value, null, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null, DelegatingBindingTrace(BindingTraceContext().bindingContext, "Temporary trace for handleException resolution"), TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)) - handleExceptionFunction.valueParameters.zip(valueArguments).forEach { + descriptor.valueParameters.zip(valueArguments).forEach { resolvedCall.recordValueArgument(it.first, ExpressionValueArgument(it.second)) } resolvedCall.setResultingSubstitutor(TypeSubstitutor.EMPTY) - return HandleResultCallContext( - resolvedCall, exceptionArgument.getArgumentExpression()!!, continuationThisArgument.getArgumentExpression()!!) + return resolvedCall } fun ResolvedCall<*>.isSuspensionPoint() =