[JS IR] Generate suspend function as invoke

[JS IR] Fix type check utils to work with array of arities

[JS IR] Store multiple arities for suspend functional interface implementers

^KT-46204 fixed
This commit is contained in:
Ilya Goncharov
2021-07-26 15:00:24 +03:00
committed by Space
parent 8a812996dd
commit 3c9dcdbbee
6 changed files with 77 additions and 13 deletions
@@ -65,6 +65,8 @@ class JsIrBackendContext(
val fileToInitializationFuns: MutableMap<IrFile, IrSimpleFunction?> = mutableMapOf()
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf()
val suspendArityStore: MutableMap<IrDeclaration, Set<Int>> = mutableMapOf()
val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
override val builtIns = module.builtIns
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.cleanup.CleanupLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.JsSuspendArityStoreLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.JsSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.CopyInlineFunctionBodyLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineDeclarationsWithReifiedTypeParametersLowering
@@ -728,6 +729,12 @@ private val cleanupLoweringPhase = makeBodyLoweringPhase(
description = "Clean up IR before codegen"
)
private val jsSuspendArityStorePhase = makeDeclarationTransformerPhase(
::JsSuspendArityStoreLowering,
name = "JsSuspendArityStoreLowering",
description = "Store arity for suspend functions to not remove it during DCE"
)
private val loweringList = listOf<Lowering>(
scriptRemoveReceiverLowering,
validateIrBeforeLowering,
@@ -818,7 +825,8 @@ private val loweringList = listOf<Lowering>(
captureStackTraceInThrowablesPhase,
callsLoweringPhase,
cleanupLoweringPhase,
validateIrAfterLowering
validateIrAfterLowering,
jsSuspendArityStorePhase
)
// TODO comment? Eliminate ModuleLowering's? Don't filter them here?
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import kotlin.collections.set
class JsSuspendArityStoreLowering(private val context: JsIrBackendContext) : DeclarationTransformer {
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
if (declaration !is IrClass) return null
declaration.declarations
.filterIsInstance<IrSimpleFunction>()
.filter { it.isSuspend }
.map { it.valueParameters.size }
.let {
context.suspendArityStore[declaration] = it.toSet()
}
return null
}
}
@@ -165,7 +165,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
declaration.realOverrideTarget.let {
val implClassDeclaration = it.parent as IrClass
if (implClassDeclaration.shouldCopyFrom()) {
if (implClassDeclaration.shouldCopyFrom() && !implClassDeclaration.defaultType.isFunctionType()) {
val implMethodName = context.getNameForMemberFunction(it)
val implClassName = context.getNameForClass(implClassDeclaration)
@@ -234,9 +234,12 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
private fun isCoroutineClass(): Boolean = irClass.superTypes.any { it.isSuspendFunctionTypeOrSubtype() }
private fun generateSuspendArity(): JsPropertyInitializer {
val arity = irClass.declarations.filterIsInstance<IrSimpleFunction>().first { it.isSuspend }.valueParameters.size
return JsPropertyInitializer(JsNameRef(Namer.METADATA_SUSPEND_ARITY), JsIntLiteral(arity))
private fun generateSuspendArity(): JsPropertyInitializer? {
val arity = context.staticContext.backendContext.suspendArityStore
.getValue(irClass)
.map { JsIntLiteral(it) }
return JsPropertyInitializer(JsNameRef(Namer.METADATA_SUSPEND_ARITY), JsArrayLiteral(arity))
}
private fun generateSuperClasses(): JsPropertyInitializer {
@@ -245,7 +248,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
JsArrayLiteral(
irClass.superTypes.mapNotNull {
val symbol = it.classifierOrFail as IrClassSymbol
val isFunctionType = it.run { isFunctionOrKFunction() || isSuspendFunctionOrKFunction() }
val isFunctionType = it.isFunctionType()
// TODO: make sure that there is a test which breaks when isExternal is used here instead of isEffectivelyExternal
val requireInMetadata = if (context.staticContext.backendContext.baseClassIntoMetadata)
!it.isAny()
@@ -260,6 +263,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
)
}
private fun IrType.isFunctionType() = isFunctionOrKFunction() || isSuspendFunctionOrKFunction()
private fun generateAssociatedKeyProperties(): List<JsPropertyInitializer> {
var result = emptyList<JsPropertyInitializer>()
@@ -90,7 +90,8 @@ private fun isFunctionTypeInvoke(receiver: JsExpression?, call: IrCall): Boolean
if (call.origin === JsStatementOrigins.EXPLICIT_INVOKE) return false
return simpleFunction.name == OperatorNameConventions.INVOKE && receiverType.isFunctionTypeOrSubtype()
return simpleFunction.name == OperatorNameConventions.INVOKE
&& receiverType.isFunctionTypeOrSubtype()
}
fun translateCall(