Minor. Extract several methods in coroutine codegen

This commit is contained in:
Denis Zharkov
2016-11-22 11:49:54 +03:00
parent caf6634fd3
commit c2e6f92aa5
2 changed files with 81 additions and 53 deletions
@@ -64,49 +64,7 @@ class CoroutineCodegen(
typeMapper.mapType(parameter.type).descriptor, null, null) typeMapper.mapType(parameter.type).descriptor, null, null)
} }
val classDescriptor = closureContext.contextDescriptor generateDoResume()
// 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)
}
})
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, funDescriptor, functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, funDescriptor,
object : FunctionGenerationStrategy.CodegenBased(state) { object : FunctionGenerationStrategy.CodegenBased(state) {
@@ -188,17 +146,24 @@ class CoroutineCodegen(
val mappedType = typeMapper.mapType(parameter.type) val mappedType = typeMapper.mapType(parameter.type)
val newIndex = myFrameMap.enter(parameter, mappedType) val newIndex = myFrameMap.enter(parameter, mappedType)
StackValue.field(parameter.getFieldInfoForCoroutineLambdaParameter(), generateThisOrOuter(context.thisDescriptor, false)) generateLoadField(parameter.getFieldInfoForCoroutineLambdaParameter())
.put(mappedType, v)
v.store(newIndex, mappedType) 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() = private fun ValueParameterDescriptor.getFieldInfoForCoroutineLambdaParameter() =
createHiddenFieldInfo(type, COROUTINE_LAMBDA_PARAMETER_PREFIX + index)
private fun createHiddenFieldInfo(type: KotlinType, name: String) =
FieldInfo.createForHiddenField( FieldInfo.createForHiddenField(
typeMapper.mapClass(closureContext.thisDescriptor), typeMapper.mapClass(closureContext.thisDescriptor),
typeMapper.mapType(returnType!!), typeMapper.mapType(type),
COROUTINE_LAMBDA_PARAMETER_PREFIX + index) name
)
private fun generateExceptionHandlingBlock(codegen: ExpressionCodegen) { private fun generateExceptionHandlingBlock(codegen: ExpressionCodegen) {
val handleExceptionFunction = val handleExceptionFunction =
@@ -220,6 +185,52 @@ class CoroutineCodegen(
codegen.v.areturn(Type.VOID_TYPE) 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) { private fun InstructionAdapter.setLabelValue(value: Int) {
load(0, AsmTypes.OBJECT_TYPE) load(0, AsmTypes.OBJECT_TYPE)
iconst(value) iconst(value)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
@@ -120,24 +121,40 @@ fun createResolvedCallForHandleExceptionCall(
val exceptionArgument = CallMaker.makeValueArgument(psiFactory.createExpression("exception")) val exceptionArgument = CallMaker.makeValueArgument(psiFactory.createExpression("exception"))
val continuationThisArgument = CallMaker.makeValueArgument(psiFactory.createExpression("this")) val continuationThisArgument = CallMaker.makeValueArgument(psiFactory.createExpression("this"))
val valueArguments = listOf(exceptionArgument, continuationThisArgument) val resolvedCall =
val call = CallMaker.makeCall(callElement, null, null, null, valueArguments) 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<ValueArgument>
): ResolvedCallImpl<SimpleFunctionDescriptor> {
val call = CallMaker.makeCall(element, null, null, null, valueArguments)
val resolvedCall = ResolvedCallImpl( val resolvedCall = ResolvedCallImpl(
call, call,
handleExceptionFunction, descriptor,
coroutineLambdaDescriptor.extensionReceiverParameter!!.value, null, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, coroutineLambdaDescriptor.extensionReceiverParameter!!.value, null, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
null, DelegatingBindingTrace(BindingTraceContext().bindingContext, "Temporary trace for handleException resolution"), null, DelegatingBindingTrace(BindingTraceContext().bindingContext, "Temporary trace for handleException resolution"),
TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)) TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY))
handleExceptionFunction.valueParameters.zip(valueArguments).forEach { descriptor.valueParameters.zip(valueArguments).forEach {
resolvedCall.recordValueArgument(it.first, ExpressionValueArgument(it.second)) resolvedCall.recordValueArgument(it.first, ExpressionValueArgument(it.second))
} }
resolvedCall.setResultingSubstitutor(TypeSubstitutor.EMPTY) resolvedCall.setResultingSubstitutor(TypeSubstitutor.EMPTY)
return HandleResultCallContext( return resolvedCall
resolvedCall, exceptionArgument.getArgumentExpression()!!, continuationThisArgument.getArgumentExpression()!!)
} }
fun ResolvedCall<*>.isSuspensionPoint() = fun ResolvedCall<*>.isSuspensionPoint() =