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)
}
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)
@@ -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<ValueArgument>
): ResolvedCallImpl<SimpleFunctionDescriptor> {
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() =