[Wasm] Fix inliner issues (KT-56584)

* Fix objects in inline functions and lambdas:
  * Add common lowerings used in K/JS and K/Native
* Fix inline lambda call detection logic in presence of additional casts


Merge-request: KT-MR-8791
Merged-by: Svyatoslav Kuzmich <svyatoslav.kuzmich@jetbrains.com>
This commit is contained in:
Svyatoslav Kuzmich
2023-02-13 13:14:43 +00:00
committed by Space Team
parent 1b5210b870
commit 26c1098a4f
21 changed files with 64 additions and 34 deletions
@@ -258,7 +258,7 @@ class FunctionInlining(
if (!isLambdaCall(expression))
return super.visitCall(expression)
val dispatchReceiver = expression.dispatchReceiver as IrGetValue
val dispatchReceiver = expression.dispatchReceiver?.unwrapAdditionalImplicitCastsIfNeeded() as IrGetValue
val functionArgument = substituteMap[dispatchReceiver.symbol.owner] ?: return super.visitCall(expression)
if ((dispatchReceiver.symbol.owner as? IrValueParameter)?.isNoinline == true)
return super.visitCall(expression)
@@ -414,6 +414,16 @@ class FunctionInlining(
else
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.IMPLICIT_CAST, type, this)
// With `insertAdditionalImplicitCasts` flag we sometimes insert
// casts to inline lambda parameters before calling `invoke` on them.
// Unwrapping these casts helps us satisfy inline lambda call detection logic.
private fun IrExpression.unwrapAdditionalImplicitCastsIfNeeded(): IrExpression {
if (insertAdditionalImplicitCasts && this is IrTypeOperatorCall && this.operator == IrTypeOperator.IMPLICIT_CAST) {
return this.argument.unwrapAdditionalImplicitCastsIfNeeded()
}
return this
}
private fun isLambdaCall(irCall: IrCall): Boolean {
val callee = irCall.symbol.owner
val dispatchReceiver = callee.dispatchReceiverParameter ?: return false
@@ -421,7 +431,7 @@ class FunctionInlining(
return (dispatchReceiver.type.isFunction() || dispatchReceiver.type.isSuspendFunction())
&& callee.name == OperatorNameConventions.INVOKE
&& irCall.dispatchReceiver is IrGetValue
&& irCall.dispatchReceiver?.unwrapAdditionalImplicitCastsIfNeeded() is IrGetValue
}
private inner class ParameterToArgument(
@@ -10,6 +10,9 @@ import org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.coroutines.AddContinuationToNonLocalSuspendFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesExtractionFromInlineFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering
import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering
import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering
import org.jetbrains.kotlin.backend.common.phaser.*
@@ -110,6 +113,36 @@ private val lateinitUsageLoweringPhase = makeWasmModulePhase(
description = "Insert checks for lateinit field references"
)
private val sharedVariablesLoweringPhase = makeWasmModulePhase(
::SharedVariablesLowering,
name = "SharedVariablesLowering",
description = "Box captured mutable variables",
prerequisite = setOf(
lateinitDeclarationLoweringPhase,
lateinitUsageLoweringPhase
)
)
private val localClassesInInlineLambdasPhase = makeWasmModulePhase(
::LocalClassesInInlineLambdasLowering,
name = "LocalClassesInInlineLambdasPhase",
description = "Extract local classes from inline lambdas",
)
private val localClassesInInlineFunctionsPhase = makeWasmModulePhase(
::LocalClassesInInlineFunctionsLowering,
name = "LocalClassesInInlineFunctionsPhase",
description = "Extract local classes from inline functions",
)
private val localClassesExtractionFromInlineFunctionsPhase = makeWasmModulePhase(
{ context -> LocalClassesExtractionFromInlineFunctionsLowering(context) },
name = "localClassesExtractionFromInlineFunctionsPhase",
description = "Move local classes from inline functions into nearest declaration container",
prerequisite = setOf(localClassesInInlineFunctionsPhase)
)
private val wrapInlineDeclarationsWithReifiedTypeParametersPhase = makeWasmModulePhase(
::WrapInlineDeclarationsWithReifiedTypeParametersLowering,
name = "WrapInlineDeclarationsWithReifiedTypeParametersPhase",
@@ -118,14 +151,20 @@ private val wrapInlineDeclarationsWithReifiedTypeParametersPhase = makeWasmModul
private val functionInliningPhase = makeCustomWasmModulePhase(
{ context, module ->
FunctionInlining(context, null, true).inline(module)
FunctionInlining(
context = context,
innerClassesSupport = context.innerClassesSupport,
insertAdditionalImplicitCasts = true,
).inline(module)
module.patchDeclarationParents()
},
name = "FunctionInliningPhase",
description = "Perform function inlining",
prerequisite = setOf(
expectDeclarationsRemovingPhase,
wrapInlineDeclarationsWithReifiedTypeParametersPhase
wrapInlineDeclarationsWithReifiedTypeParametersPhase,
localClassesInInlineLambdasPhase,
localClassesInInlineFunctionsPhase,
)
)
@@ -238,12 +277,6 @@ private val enumEntryRemovalLoweringPhase = makeWasmModulePhase(
)
private val sharedVariablesLoweringPhase = makeWasmModulePhase(
::SharedVariablesLowering,
name = "SharedVariablesLowering",
description = "Box captured mutable variables"
)
private val propertyReferenceLowering = makeWasmModulePhase(
::WasmPropertyReferenceLowering,
name = "WasmPropertyReferenceLowering",
@@ -563,6 +596,14 @@ val wasmPhases = SameTypeNamedCompilerPhase(
excludeDeclarationsFromCodegenPhase then
expectDeclarationsRemovingPhase then
lateinitNullableFieldsPhase then
lateinitDeclarationLoweringPhase then
lateinitUsageLoweringPhase then
sharedVariablesLoweringPhase then
localClassesInInlineLambdasPhase then
localClassesInInlineFunctionsPhase then
localClassesExtractionFromInlineFunctionsPhase then
// TODO: Need some helpers from stdlib
// arrayConstructorPhase then
wrapInlineDeclarationsWithReifiedTypeParametersPhase then
@@ -570,9 +611,6 @@ val wasmPhases = SameTypeNamedCompilerPhase(
functionInliningPhase then
removeInlineDeclarationsWithReifiedTypeParametersLoweringPhase then
lateinitNullableFieldsPhase then
lateinitDeclarationLoweringPhase then
lateinitUsageLoweringPhase then
tailrecLoweringPhase then
enumClassConstructorLoweringPhase then
@@ -583,7 +621,6 @@ val wasmPhases = SameTypeNamedCompilerPhase(
enumEntryCreateGetInstancesFunsLoweringPhase then
enumSyntheticFunsLoweringPhase then
sharedVariablesLoweringPhase then
propertyReferenceLowering then
callableReferencePhase then
singleAbstractMethodPhase then
-2
View File
@@ -1,6 +1,4 @@
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: UNKNOWN
// WITH_STDLIB
interface Runnable {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// MODULE: lib
// FILE: lib.kt
interface I {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// KT-33992
class P<T>(val a: T, val b: T)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// NO_CHECK_LAMBDA_INLINING
// FILE: utils.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR
// NO_CHECK_LAMBDA_INLINING
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR
// NO_CHECK_LAMBDA_INLINING
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt
@@ -1,5 +1,5 @@
// NO_CHECK_LAMBDA_INLINING
// IGNORE_BACKEND: JVM, WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR
import kotlin.IllegalStateException
@@ -1,5 +1,5 @@
// NO_CHECK_LAMBDA_INLINING
// IGNORE_BACKEND: JVM, WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR
import kotlin.IllegalStateException
@@ -1,5 +1,5 @@
// NO_CHECK_LAMBDA_INLINING
// IGNORE_BACKEND: JVM, WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR
import kotlin.IllegalStateException
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// NO_CHECK_LAMBDA_INLINING
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// FILE: 1.kt
class E(val x: String) {
inner class Inner {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// FILE: 1.kt
class O(val a: String) {
inner class I1(val b: String) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// FILE: 1.kt
class E(val x: String) {
fun bar() = x
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// FILE: 1.kt
class E<T>(val x: T) {
inner class Inner {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_IR_AGAINST_OLD
// FILE: a.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt