[JS IR] Fix offsets and add new test

[JS IR] Use TypeSubstitutor for full substitution of types

- adding new tests

[JS IR] Commonize context and use in wasm

[JS IR] Add test with receiver with callable reference

[JS IR] Add prerequisites around inlining and callable references

[JS IR] Review fixes

- Add test with bounded type parameter
- Remove redundant casts
- Use offsets for synth function
- Correct traversing

[JS IR] Not use origin for not inlined function reference

[JS IR] Move util into common place

[JS IR] Fix offsets

[JS IR] Add type parameter argument and using value in test

[JS IR] Wrap inlined callable references with reified parameters

[JS IR] Add test on callable reference inlined fun

Merge-request: KT-MR-4722
This commit is contained in:
Ilya Goncharov
2021-10-11 09:02:08 +00:00
committed by Space
parent c9510af2c7
commit b0aefd543a
14 changed files with 267 additions and 10 deletions
@@ -21,10 +21,7 @@ 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
import org.jetbrains.kotlin.ir.backend.js.lower.inline.SyntheticAccessorLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.jsRecordExtractedLocalClasses
import org.jetbrains.kotlin.ir.backend.js.lower.inline.*
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -245,6 +242,12 @@ private val syntheticAccessorLoweringPhase = makeBodyLoweringPhase(
description = "Wrap top level inline function to access through them from inline functions"
)
private val wrapInlineDeclarationsWithReifiedTypeParametersLowering = makeBodyLoweringPhase(
::WrapInlineDeclarationsWithReifiedTypeParametersLowering,
name = "WrapInlineDeclarationsWithReifiedTypeParametersLowering",
description = "Wrap inline declarations with reified type parameters"
)
private val functionInliningPhase = makeBodyLoweringPhase(
::FunctionInlining,
name = "FunctionInliningPhase",
@@ -252,7 +255,7 @@ private val functionInliningPhase = makeBodyLoweringPhase(
prerequisite = setOf(
expectDeclarationsRemovingPhase, sharedVariablesLoweringPhase,
localClassesInInlineLambdasPhase, localClassesExtractionFromInlineFunctionsPhase,
syntheticAccessorLoweringPhase
syntheticAccessorLoweringPhase, wrapInlineDeclarationsWithReifiedTypeParametersLowering
)
)
@@ -359,7 +362,8 @@ private val enumEntryRemovalLoweringPhase = makeDeclarationTransformerPhase(
private val callableReferenceLowering = makeBodyLoweringPhase(
::CallableReferenceLowering,
name = "CallableReferenceLowering",
description = "Build a lambda/callable reference class"
description = "Build a lambda/callable reference class",
prerequisite = setOf(functionInliningPhase, wrapInlineDeclarationsWithReifiedTypeParametersLowering)
)
private val returnableBlockLoweringPhase = makeBodyLoweringPhase(
@@ -767,6 +771,7 @@ private val loweringList = listOf<Lowering>(
localClassesInInlineFunctionsPhase,
localClassesExtractionFromInlineFunctionsPhase,
syntheticAccessorLoweringPhase,
wrapInlineDeclarationsWithReifiedTypeParametersLowering,
functionInliningPhase,
copyInlineFunctionBodyLoweringPhase,
removeInlineDeclarationsWithReifiedTypeParametersLoweringPhase,
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
@@ -17,8 +18,6 @@ import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
class RemoveInlineDeclarationsWithReifiedTypeParametersLowering: DeclarationTransformer {
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
fun IrFunction.isInlineFunWithReifiedParameter() = isInline && typeParameters.any { it.isReified }
if (declaration is IrFunction && declaration.isInlineFunWithReifiedParameter() ||
declaration is IrProperty && declaration.getter?.isInlineFunWithReifiedParameter() == true
) {
@@ -0,0 +1,107 @@
/*
* Copyright 2010-2021 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.
*/
/*
* Copyright 2010-2021 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.inline
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.IrTypeSubstitutor
import org.jetbrains.kotlin.ir.util.typeSubstitutionMap
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
// Replace callable reference on inline function with reified parameter
// with callable reference on new non inline function with substituted types
class WrapInlineDeclarationsWithReifiedTypeParametersLowering(val context: BackendContext) : BodyLoweringPass {
private val irFactory
get() = context.irFactory
override fun lower(irBody: IrBody, container: IrDeclaration) {
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
expression.transformChildrenVoid()
val owner = expression.symbol.owner as? IrSimpleFunction
?: return expression
if (!owner.isInlineFunWithReifiedParameter()) {
return expression
}
val substitutionMap = expression.typeSubstitutionMap
.entries
.map { (key, value) ->
key to (value as IrTypeArgument)
}
val typeSubstitutor = IrTypeSubstitutor(
substitutionMap.map { it.first },
substitutionMap.map { it.second },
context.irBuiltIns
)
val function = irFactory.addFunction(container.parent as IrDeclarationContainer) {
name = Name.identifier("${owner.name}${"$"}wrap")
returnType = owner.returnType
visibility = DescriptorVisibilities.PRIVATE
origin = JsIrBuilder.SYNTHESIZED_DECLARATION
}.also { function ->
owner.valueParameters.forEach { valueParameter ->
function.addValueParameter(
valueParameter.name,
typeSubstitutor.substitute(valueParameter.type)
)
}
function.body = irFactory.createBlockBody(
expression.startOffset,
expression.endOffset
) {
statements.add(
JsIrBuilder.buildReturn(
function.symbol,
JsIrBuilder.buildCall(owner.symbol).also { call ->
call.dispatchReceiver = expression.dispatchReceiver
call.extensionReceiver = expression.extensionReceiver
function.valueParameters.forEachIndexed { index, valueParameter ->
call.putValueArgument(index, JsIrBuilder.buildGetValue(valueParameter.symbol))
}
for (i in 0 until expression.typeArgumentsCount) {
call.putTypeArgument(i, expression.getTypeArgument(i))
}
},
owner.returnType
)
)
}
}
return IrFunctionReferenceImpl.fromSymbolOwner(
expression.startOffset,
expression.endOffset,
expression.type,
function.symbol,
function.typeParameters.size,
expression.reflectionTarget
)
}
})
}
}
@@ -129,4 +129,6 @@ fun invokeFunForLambda(call: IrCall) =
.getClass()!!
.declarations
.filterIsInstance<IrSimpleFunction>()
.single { it.name.asString() == "invoke" }
.single { it.name.asString() == "invoke" }
fun IrFunction.isInlineFunWithReifiedParameter() = isInline && typeParameters.any { it.isReified }
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.wasm.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineDeclarationsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.WrapInlineDeclarationsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
@@ -87,6 +88,12 @@ private val provisionalFunctionExpressionPhase = makeWasmModulePhase(
description = "Transform IrFunctionExpression to a local function reference"
)
private val wrapInlineDeclarationsWithReifiedTypeParametersPhase = makeWasmModulePhase(
::WrapInlineDeclarationsWithReifiedTypeParametersLowering,
name = "WrapInlineDeclarationsWithReifiedTypeParametersPhase",
description = "Wrap inline declarations with reified type parameters"
)
private val functionInliningPhase = makeCustomWasmModulePhase(
{ context, module ->
FunctionInlining(context).inline(module)
@@ -94,7 +101,10 @@ private val functionInliningPhase = makeCustomWasmModulePhase(
},
name = "FunctionInliningPhase",
description = "Perform function inlining",
prerequisite = setOf(expectDeclarationsRemovingPhase)
prerequisite = setOf(
expectDeclarationsRemovingPhase,
wrapInlineDeclarationsWithReifiedTypeParametersPhase
)
)
private val removeInlineDeclarationsWithReifiedTypeParametersLoweringPhase = makeWasmModulePhase(
@@ -448,6 +458,7 @@ val wasmPhases = NamedCompilerPhase(
// TODO: Need some helpers from stdlib
// arrayConstructorPhase then
wrapInlineDeclarationsWithReifiedTypeParametersPhase then
functionInliningPhase then
provisionalFunctionExpressionPhase then