Reformat coroutineContext related code

This commit is contained in:
Ilmir Usmanov
2018-01-25 19:26:27 +03:00
parent 18c03f94f8
commit 8ffb205f1c
3 changed files with 181 additions and 179 deletions
@@ -37,9 +37,9 @@ val SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME = Name.identifier("suspendCor
fun FunctionDescriptor.isBuiltInIntercepted(): Boolean { fun FunctionDescriptor.isBuiltInIntercepted(): Boolean {
if (name != INTERCEPTED_NAME) return false if (name != INTERCEPTED_NAME) return false
val original = val original =
module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope
.getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND)
.singleOrNull() as CallableDescriptor .singleOrNull() as CallableDescriptor
return DescriptorEquivalenceForOverrides.areEquivalent(original, this) return DescriptorEquivalenceForOverrides.areEquivalent(original, this)
} }
@@ -49,14 +49,14 @@ fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturn(): Boolean {
val originalDeclaration = getBuiltInSuspendCoroutineOrReturn() ?: return false val originalDeclaration = getBuiltInSuspendCoroutineOrReturn() ?: return false
return DescriptorEquivalenceForOverrides.areEquivalent( return DescriptorEquivalenceForOverrides.areEquivalent(
originalDeclaration, this originalDeclaration, this
) )
} }
fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn() = fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn() =
module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope
.getContributedFunctions(SUSPEND_COROUTINE_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(SUSPEND_COROUTINE_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND)
.singleOrNull() .singleOrNull()
fun FunctionDescriptor.isBuiltInCoroutineContext(): Boolean { fun FunctionDescriptor.isBuiltInCoroutineContext(): Boolean {
val fqNameSafe = (this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe val fqNameSafe = (this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe
@@ -66,7 +66,7 @@ fun FunctionDescriptor.isBuiltInCoroutineContext(): Boolean {
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean { fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean {
if (name != SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME) return false if (name != SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME) return false
val original = module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope val original = module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope
.getContributedFunctions(SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND)
.singleOrNull() as CallableDescriptor .singleOrNull() as CallableDescriptor
return DescriptorEquivalenceForOverrides.areEquivalent(original, this) return DescriptorEquivalenceForOverrides.areEquivalent(original, this)
} }
@@ -59,13 +59,14 @@ const val EXCEPTION_FIELD_NAME = "exception"
@JvmField @JvmField
val COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME = val COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME =
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("jvm")).child(Name.identifier("internal")) DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("jvm")).child(Name.identifier("internal"))
@JvmField @JvmField
val CONTINUATION_ASM_TYPE = DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.topLevelClassAsmType() val CONTINUATION_ASM_TYPE = DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.topLevelClassAsmType()
@JvmField @JvmField
val COROUTINE_CONTEXT_ASM_TYPE = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineContext")).topLevelClassAsmType() val COROUTINE_CONTEXT_ASM_TYPE =
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
@JvmField @JvmField
val COROUTINE_IMPL_ASM_TYPE = COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImpl")).topLevelClassAsmType() val COROUTINE_IMPL_ASM_TYPE = COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
@@ -74,7 +75,7 @@ private val COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME =
DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType() DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
private val INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME = private val INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME =
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName() COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName()
private val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation" private val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
private val GET_CONTEXT_METHOD_NAME = "getContext" private val GET_CONTEXT_METHOD_NAME = "getContext"
@@ -94,41 +95,42 @@ val INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME = object : FunctionDescriptor.UserD
// So this function returns resolved call with descriptor looking like `fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>): Unit` // So this function returns resolved call with descriptor looking like `fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>): Unit`
// and fake `this` expression that used as argument for second parameter // and fake `this` expression that used as argument for second parameter
fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor( fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
project: Project, project: Project,
bindingContext: BindingContext bindingContext: BindingContext
): ResolvedCallWithRealDescriptor? { ): ResolvedCallWithRealDescriptor? {
if (this is VariableAsFunctionResolvedCall) { if (this is VariableAsFunctionResolvedCall) {
val replacedFunctionCall = val replacedFunctionCall =
functionCall.replaceSuspensionFunctionWithRealDescriptor(project, bindingContext) functionCall.replaceSuspensionFunctionWithRealDescriptor(project, bindingContext)
?: return null ?: return null
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return replacedFunctionCall.copy( return replacedFunctionCall.copy(
VariableAsFunctionResolvedCallImpl( VariableAsFunctionResolvedCallImpl(
replacedFunctionCall.resolvedCall as MutableResolvedCall<FunctionDescriptor>, replacedFunctionCall.resolvedCall as MutableResolvedCall<FunctionDescriptor>,
variableCall.asMutableResolvedCall(bindingContext) variableCall.asMutableResolvedCall(bindingContext)
) )
) )
} }
val function = candidateDescriptor as? FunctionDescriptor ?: return null val function = candidateDescriptor as? FunctionDescriptor ?: return null
if (!function.isSuspend || function.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) return null if (!function.isSuspend || function.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) return null
val newCandidateDescriptor = val newCandidateDescriptor =
when (function) { when (function) {
is FunctionImportedFromObject -> is FunctionImportedFromObject ->
getOrCreateJvmSuspendFunctionView(function.callableFromObject, bindingContext).asImportedFromObject() getOrCreateJvmSuspendFunctionView(function.callableFromObject, bindingContext).asImportedFromObject()
is SimpleFunctionDescriptor -> is SimpleFunctionDescriptor ->
getOrCreateJvmSuspendFunctionView(function, bindingContext) getOrCreateJvmSuspendFunctionView(function, bindingContext)
else -> else ->
throw AssertionError("Unexpected suspend function descriptor: $function") throw AssertionError("Unexpected suspend function descriptor: $function")
} }
val newCall = ResolvedCallImpl( val newCall = ResolvedCallImpl(
call, call,
newCandidateDescriptor, newCandidateDescriptor,
dispatchReceiver, extensionReceiver, explicitReceiverKind, dispatchReceiver, extensionReceiver, explicitReceiverKind,
null, DelegatingBindingTrace(BindingTraceContext().bindingContext, "Temporary trace for unwrapped suspension function"), null, DelegatingBindingTrace(BindingTraceContext().bindingContext, "Temporary trace for unwrapped suspension function"),
TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)) TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
)
this.valueArguments.forEach { this.valueArguments.forEach {
newCall.recordValueArgument(newCandidateDescriptor.valueParameters[it.key.index], it.value) newCall.recordValueArgument(newCandidateDescriptor.valueParameters[it.key.index], it.value)
@@ -138,15 +140,17 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
val arguments = psiFactory.createCallArguments("(this)").arguments.single() val arguments = psiFactory.createCallArguments("(this)").arguments.single()
val thisExpression = arguments.getArgumentExpression()!! val thisExpression = arguments.getArgumentExpression()!!
newCall.recordValueArgument( newCall.recordValueArgument(
newCandidateDescriptor.valueParameters.last(), newCandidateDescriptor.valueParameters.last(),
ExpressionValueArgument(arguments)) ExpressionValueArgument(arguments)
)
val newTypeArguments = newCandidateDescriptor.typeParameters.map { val newTypeArguments = newCandidateDescriptor.typeParameters.map {
Pair(it, typeArguments[candidateDescriptor.typeParameters[it.index]]!!.asTypeProjection()) Pair(it, typeArguments[candidateDescriptor.typeParameters[it.index]]!!.asTypeProjection())
}.toMap() }.toMap()
newCall.setResultingSubstitutor( newCall.setResultingSubstitutor(
TypeConstructorSubstitution.createByParametersMap(newTypeArguments).buildSubstitutor()) TypeConstructorSubstitution.createByParametersMap(newTypeArguments).buildSubstitutor()
)
return ResolvedCallWithRealDescriptor(newCall, thisExpression) return ResolvedCallWithRealDescriptor(newCall, thisExpression)
} }
@@ -161,19 +165,19 @@ private fun ResolvedCall<VariableDescriptor>.asMutableResolvedCall(bindingContex
private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindingContext: BindingContext): ResolvedCallImpl<VariableDescriptor> { private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindingContext: BindingContext): ResolvedCallImpl<VariableDescriptor> {
return ResolvedCallImpl( return ResolvedCallImpl(
call, call,
candidateDescriptor, candidateDescriptor,
dispatchReceiver, extensionReceiver, explicitReceiverKind, dispatchReceiver, extensionReceiver, explicitReceiverKind,
null, DelegatingBindingTrace(bindingContext, "Trace for old call"), null, DelegatingBindingTrace(bindingContext, "Trace for old call"),
TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY) TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
) )
} }
fun ResolvedCall<*>.isSuspendNoInlineCall() = fun ResolvedCall<*>.isSuspendNoInlineCall() =
resultingDescriptor.safeAs<FunctionDescriptor>() resultingDescriptor.safeAs<FunctionDescriptor>()
?.let { ?.let {
it.isSuspend && (!it.isInline || it.isBuiltInSuspendCoroutineOrReturnInJvm() || it.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) it.isSuspend && (!it.isInline || it.isBuiltInSuspendCoroutineOrReturnInJvm() || it.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm())
} == true } == true
fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean { fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean {
if (this !is FunctionDescriptor) return false if (this !is FunctionDescriptor) return false
@@ -193,14 +197,14 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, bind
bindingContext?.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, function)?.let { return it as D } bindingContext?.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, function)?.let { return it as D }
val continuationParameter = ValueParameterDescriptorImpl( val continuationParameter = ValueParameterDescriptorImpl(
function, null, function.valueParameters.size, Annotations.EMPTY, Name.identifier("continuation"), function, null, function.valueParameters.size, Annotations.EMPTY, Name.identifier("continuation"),
// Add j.l.Object to invoke(), because that is the type of parameters we have in FunctionN+1 // Add j.l.Object to invoke(), because that is the type of parameters we have in FunctionN+1
if (function.containingDeclaration.safeAs<ClassDescriptor>()?.defaultType?.isBuiltinFunctionalType == true) if (function.containingDeclaration.safeAs<ClassDescriptor>()?.defaultType?.isBuiltinFunctionalType == true)
function.builtIns.nullableAnyType function.builtIns.nullableAnyType
else else
function.getContinuationParameterTypeOfSuspendFunction(), function.getContinuationParameterTypeOfSuspendFunction(),
/* declaresDefaultValue = */ false, /* isCrossinline = */ false, /* declaresDefaultValue = */ false, /* isCrossinline = */ false,
/* isNoinline = */ false, /* varargElementType = */ null, SourceElement.NO_SOURCE /* isNoinline = */ false, /* varargElementType = */ null, SourceElement.NO_SOURCE
) )
return function.createCustomCopy { return function.createCustomCopy {
@@ -213,18 +217,18 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, bind
} }
typealias FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder = typealias FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder =
FunctionDescriptor.CopyBuilder<out FunctionDescriptor>.(FunctionDescriptor) FunctionDescriptor.CopyBuilder<out FunctionDescriptor>.(FunctionDescriptor)
-> FunctionDescriptor.CopyBuilder<out FunctionDescriptor> -> FunctionDescriptor.CopyBuilder<out FunctionDescriptor>
fun <D : FunctionDescriptor> D.createCustomCopy( fun <D : FunctionDescriptor> D.createCustomCopy(
copySettings: FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder copySettings: FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder
): D { ): D {
val newOriginal = val newOriginal =
if (original !== this) if (original !== this)
original.createCustomCopy(copySettings) original.createCustomCopy(copySettings)
else else
null null
val result = newCopyBuilder().copySettings(this).setOriginal(newOriginal).build()!! val result = newCopyBuilder().copySettings(this).setOriginal(newOriginal).build()!!
@@ -235,52 +239,52 @@ fun <D : FunctionDescriptor> D.createCustomCopy(
} }
private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction() = private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction() =
module.getContinuationOfTypeOrAny(returnType!!) module.getContinuationOfTypeOrAny(returnType!!)
fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType) = fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType) =
module.findContinuationClassDescriptorOrNull(NoLookupLocation.FROM_BACKEND)?.defaultType?.let { module.findContinuationClassDescriptorOrNull(NoLookupLocation.FROM_BACKEND)?.defaultType?.let {
KotlinTypeFactory.simpleType( KotlinTypeFactory.simpleType(
it, it,
arguments = listOf(kotlinType.asTypeProjection()) arguments = listOf(kotlinType.asTypeProjection())
) )
} ?: module.builtIns.nullableAnyType } ?: module.builtIns.nullableAnyType
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() = fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineOrReturn() == true getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineOrReturn() == true
fun createMethodNodeForSuspendCoroutineOrReturn( fun createMethodNodeForSuspendCoroutineOrReturn(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper typeMapper: KotlinTypeMapper
): MethodNode { ): MethodNode {
assert(functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm()) { assert(functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.suspendOrReturn" "functionDescriptor must be kotlin.coroutines.intrinsics.suspendOrReturn"
} }
val node = val node =
MethodNode( MethodNode(
Opcodes.ASM5, Opcodes.ASM5,
Opcodes.ACC_STATIC, Opcodes.ACC_STATIC,
"fake", "fake",
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
) )
node.visitVarInsn(Opcodes.ALOAD, 0) node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitVarInsn(Opcodes.ALOAD, 1) node.visitVarInsn(Opcodes.ALOAD, 1)
node.visitMethodInsn( node.visitMethodInsn(
Opcodes.INVOKESTATIC, Opcodes.INVOKESTATIC,
INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME, INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME,
NORMALIZE_CONTINUATION_METHOD_NAME, NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(CONTINUATION_ASM_TYPE, CONTINUATION_ASM_TYPE), Type.getMethodDescriptor(CONTINUATION_ASM_TYPE, CONTINUATION_ASM_TYPE),
false false
) )
node.visitMethodInsn( node.visitMethodInsn(
Opcodes.INVOKEINTERFACE, Opcodes.INVOKEINTERFACE,
typeMapper.mapType(functionDescriptor.valueParameters[0]).internalName, typeMapper.mapType(functionDescriptor.valueParameters[0]).internalName,
OperatorNameConventions.INVOKE.identifier, OperatorNameConventions.INVOKE.identifier,
"(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}", "(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}",
true true
) )
node.visitInsn(Opcodes.ARETURN) node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(2, 2) node.visitMaxs(2, 2)
@@ -289,32 +293,32 @@ fun createMethodNodeForSuspendCoroutineOrReturn(
} }
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() = fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn() == true getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn() == true
fun createMethodNodeForIntercepted( fun createMethodNodeForIntercepted(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper typeMapper: KotlinTypeMapper
): MethodNode { ): MethodNode {
assert(functionDescriptor.isBuiltInIntercepted()) { assert(functionDescriptor.isBuiltInIntercepted()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.intercepted" "functionDescriptor must be kotlin.coroutines.intrinsics.intercepted"
} }
val node = val node =
MethodNode( MethodNode(
Opcodes.ASM5, Opcodes.ASM5,
Opcodes.ACC_STATIC, Opcodes.ACC_STATIC,
"fake", "fake",
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
) )
node.visitVarInsn(Opcodes.ALOAD, 0) node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitMethodInsn( node.visitMethodInsn(
Opcodes.INVOKESTATIC, Opcodes.INVOKESTATIC,
INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME, INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME,
NORMALIZE_CONTINUATION_METHOD_NAME, NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(CONTINUATION_ASM_TYPE, CONTINUATION_ASM_TYPE), Type.getMethodDescriptor(CONTINUATION_ASM_TYPE, CONTINUATION_ASM_TYPE),
false false
) )
node.visitInsn(Opcodes.ARETURN) node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(1, 1) node.visitMaxs(1, 1)
@@ -328,22 +332,22 @@ fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor):
} }
val node = val node =
MethodNode( MethodNode(
Opcodes.ASM5, Opcodes.ASM5,
Opcodes.ACC_STATIC, Opcodes.ACC_STATIC,
"fake", "fake",
Type.getMethodDescriptor(COROUTINE_CONTEXT_ASM_TYPE, CONTINUATION_ASM_TYPE), Type.getMethodDescriptor(COROUTINE_CONTEXT_ASM_TYPE, CONTINUATION_ASM_TYPE),
null, null null, null
) )
node.visitVarInsn(Opcodes.ALOAD, 0) node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitMethodInsn( node.visitMethodInsn(
Opcodes.INVOKEINTERFACE, Opcodes.INVOKEINTERFACE,
CONTINUATION_ASM_TYPE.internalName, CONTINUATION_ASM_TYPE.internalName,
GET_CONTEXT_METHOD_NAME, GET_CONTEXT_METHOD_NAME,
Type.getMethodDescriptor(COROUTINE_CONTEXT_ASM_TYPE), Type.getMethodDescriptor(COROUTINE_CONTEXT_ASM_TYPE),
true true
) )
node.visitInsn(Opcodes.ARETURN) node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(1, 1) node.visitMaxs(1, 1)
@@ -353,30 +357,30 @@ fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor):
fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn( fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper typeMapper: KotlinTypeMapper
): MethodNode { ): MethodNode {
assert(functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) { assert(functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn" "functionDescriptor must be kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn"
} }
val node = val node =
MethodNode( MethodNode(
Opcodes.ASM5, Opcodes.ASM5,
Opcodes.ACC_STATIC, Opcodes.ACC_STATIC,
"fake", "fake",
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
) )
node.visitVarInsn(Opcodes.ALOAD, 0) node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitVarInsn(Opcodes.ALOAD, 1) node.visitVarInsn(Opcodes.ALOAD, 1)
node.visitMethodInsn( node.visitMethodInsn(
Opcodes.INVOKEINTERFACE, Opcodes.INVOKEINTERFACE,
typeMapper.mapType(functionDescriptor.valueParameters[0]).internalName, typeMapper.mapType(functionDescriptor.valueParameters[0]).internalName,
OperatorNameConventions.INVOKE.identifier, OperatorNameConventions.INVOKE.identifier,
"(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}", "(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}",
true true
) )
node.visitInsn(Opcodes.ARETURN) node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(2, 2) node.visitMaxs(2, 2)
@@ -386,21 +390,21 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D = fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D =
this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext): FunctionDescriptor = fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext): FunctionDescriptor =
if (isSuspend) if (isSuspend)
getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, bindingContext) getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, bindingContext)
else else
this this
fun InstructionAdapter.loadCoroutineSuspendedMarker() { fun InstructionAdapter.loadCoroutineSuspendedMarker() {
invokestatic( invokestatic(
COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME.internalName, COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME.internalName,
"get$COROUTINE_SUSPENDED_NAME", "get$COROUTINE_SUSPENDED_NAME",
Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE), Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE),
false false
) )
} }
@@ -411,12 +415,12 @@ fun InstructionAdapter.invokeDoResumeWithUnit(thisName: String) {
aconst(null) aconst(null)
invokevirtual( invokevirtual(
thisName, thisName,
DO_RESUME_METHOD_NAME, DO_RESUME_METHOD_NAME,
Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE, AsmTypes.OBJECT_TYPE, AsmTypes.JAVA_THROWABLE_TYPE), Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE, AsmTypes.OBJECT_TYPE, AsmTypes.JAVA_THROWABLE_TYPE),
false false
) )
} }
fun Method.getImplForOpenMethod(ownerInternalName: String) = fun Method.getImplForOpenMethod(ownerInternalName: String) =
Method("$name\$suspendImpl", returnType, arrayOf(Type.getObjectType(ownerInternalName)) + argumentTypes) Method("$name\$suspendImpl", returnType, arrayOf(Type.getObjectType(ownerInternalName)) + argumentTypes)
@@ -42,21 +42,20 @@ import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
fun generateDelegateCall( fun generateDelegateCall(
classDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor,
fromDescriptor: FunctionDescriptor, fromDescriptor: FunctionDescriptor,
toDescriptor: FunctionDescriptor, toDescriptor: FunctionDescriptor,
thisObject: JsExpression, thisObject: JsExpression,
context: TranslationContext, context: TranslationContext,
detectDefaultParameters: Boolean, detectDefaultParameters: Boolean,
source: PsiElement? source: PsiElement?
): JsStatement { ): JsStatement {
fun FunctionDescriptor.getNameForFunctionWithPossibleDefaultParam() = fun FunctionDescriptor.getNameForFunctionWithPossibleDefaultParam() =
if (detectDefaultParameters && hasOrInheritsParametersWithDefaultValue()) { if (detectDefaultParameters && hasOrInheritsParametersWithDefaultValue()) {
context.scope().declareName(context.getNameForDescriptor(this).ident + Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX) context.scope().declareName(context.getNameForDescriptor(this).ident + Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX)
} } else {
else { context.getNameForDescriptor(this)
context.getNameForDescriptor(this) }
}
val overriddenMemberFunctionName = toDescriptor.getNameForFunctionWithPossibleDefaultParam() val overriddenMemberFunctionName = toDescriptor.getNameForFunctionWithPossibleDefaultParam()
val overriddenMemberFunctionRef = JsNameRef(overriddenMemberFunctionName, thisObject) val overriddenMemberFunctionRef = JsNameRef(overriddenMemberFunctionName, thisObject)
@@ -80,8 +79,7 @@ fun generateDelegateCall(
val intrinsic = context.intrinsics().getFunctionIntrinsic(toDescriptor) val intrinsic = context.intrinsics().getFunctionIntrinsic(toDescriptor)
val invocation = if (intrinsic.exists() && intrinsic is FunctionIntrinsicWithReceiverComputed) { val invocation = if (intrinsic.exists() && intrinsic is FunctionIntrinsicWithReceiverComputed) {
intrinsic.apply(thisObject, args, context) intrinsic.apply(thisObject, args, context)
} } else {
else {
JsInvocation(overriddenMemberFunctionRef, args) JsInvocation(overriddenMemberFunctionRef, args)
} }
@@ -130,8 +128,8 @@ fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsExpr
context.usageTracker()?.used(classifierDescriptor) context.usageTracker()?.used(classifierDescriptor)
context.captureTypeIfNeedAndGetCapturedName(classifierDescriptor) ?: context.captureTypeIfNeedAndGetCapturedName(classifierDescriptor)
context.getNameForDescriptor(classifierDescriptor).makeRef() ?: context.getNameForDescriptor(classifierDescriptor).makeRef()
} }
else -> { else -> {
throw IllegalStateException("Can't get reference for $type") throw IllegalStateException("Can't get reference for $type")
@@ -140,9 +138,9 @@ fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsExpr
} }
fun TranslationContext.addFunctionToPrototype( fun TranslationContext.addFunctionToPrototype(
classDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor,
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
function: JsExpression function: JsExpression
): JsStatement { ): JsStatement {
val prototypeRef = JsAstUtils.prototypeOf(getInnerReference(classDescriptor)) val prototypeRef = JsAstUtils.prototypeOf(getInnerReference(classDescriptor))
val functionRef = JsNameRef(getNameForDescriptor(descriptor), prototypeRef) val functionRef = JsNameRef(getNameForDescriptor(descriptor), prototypeRef)
@@ -150,9 +148,9 @@ fun TranslationContext.addFunctionToPrototype(
} }
fun TranslationContext.addAccessorsToPrototype( fun TranslationContext.addAccessorsToPrototype(
containingClass: ClassDescriptor, containingClass: ClassDescriptor,
propertyDescriptor: PropertyDescriptor, propertyDescriptor: PropertyDescriptor,
literal: JsObjectLiteral literal: JsObjectLiteral
) { ) {
val prototypeRef = JsAstUtils.prototypeOf(getInnerReference(containingClass)) val prototypeRef = JsAstUtils.prototypeOf(getInnerReference(containingClass))
val propertyName = getNameForDescriptor(propertyDescriptor) val propertyName = getNameForDescriptor(propertyDescriptor)
@@ -161,31 +159,31 @@ fun TranslationContext.addAccessorsToPrototype(
} }
fun JsFunction.fillCoroutineMetadata( fun JsFunction.fillCoroutineMetadata(
context: TranslationContext, context: TranslationContext,
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
hasController: Boolean hasController: Boolean
) { ) {
val suspendPropertyDescriptor = context.currentModule.getPackage(DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME) val suspendPropertyDescriptor = context.currentModule.getPackage(DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME)
.memberScope .memberScope
.getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).first() .getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).first()
val coroutineBaseClassRef = ReferenceTranslator.translateAsTypeReference(TranslationUtils.getCoroutineBaseClass(context), context) val coroutineBaseClassRef = ReferenceTranslator.translateAsTypeReference(TranslationUtils.getCoroutineBaseClass(context), context)
fun getCoroutinePropertyName(id: String) = fun getCoroutinePropertyName(id: String) =
context.getNameForDescriptor(TranslationUtils.getCoroutineProperty(context, id)) context.getNameForDescriptor(TranslationUtils.getCoroutineProperty(context, id))
coroutineMetadata = CoroutineMetadata( coroutineMetadata = CoroutineMetadata(
doResumeName = context.getNameForDescriptor(TranslationUtils.getCoroutineDoResumeFunction(context)), doResumeName = context.getNameForDescriptor(TranslationUtils.getCoroutineDoResumeFunction(context)),
suspendObjectRef = ReferenceTranslator.translateAsValueReference(suspendPropertyDescriptor, context), suspendObjectRef = ReferenceTranslator.translateAsValueReference(suspendPropertyDescriptor, context),
baseClassRef = coroutineBaseClassRef, baseClassRef = coroutineBaseClassRef,
stateName = getCoroutinePropertyName("state"), stateName = getCoroutinePropertyName("state"),
exceptionStateName = getCoroutinePropertyName("exceptionState"), exceptionStateName = getCoroutinePropertyName("exceptionState"),
finallyPathName = getCoroutinePropertyName("finallyPath"), finallyPathName = getCoroutinePropertyName("finallyPath"),
resultName = getCoroutinePropertyName("result"), resultName = getCoroutinePropertyName("result"),
exceptionName = getCoroutinePropertyName("exception"), exceptionName = getCoroutinePropertyName("exception"),
hasController = hasController, hasController = hasController,
hasReceiver = descriptor.dispatchReceiverParameter != null, hasReceiver = descriptor.dispatchReceiverParameter != null,
psiElement = descriptor.source.getPsi() psiElement = descriptor.source.getPsi()
) )
} }
@@ -205,7 +203,7 @@ val PsiElement.finalElement: PsiElement
} }
fun TranslationContext.addFunctionButNotExport(descriptor: FunctionDescriptor, expression: JsExpression): JsName = fun TranslationContext.addFunctionButNotExport(descriptor: FunctionDescriptor, expression: JsExpression): JsName =
addFunctionButNotExport(getInnerNameForDescriptor(descriptor), expression) addFunctionButNotExport(getInnerNameForDescriptor(descriptor), expression)
fun TranslationContext.addFunctionButNotExport(name: JsName, expression: JsExpression): JsName { fun TranslationContext.addFunctionButNotExport(name: JsName, expression: JsExpression): JsName {
when (expression) { when (expression) {