JS IR: move inliner to common part; inline suspendCoroutineUninterceptedOrReturnJS

This commit is contained in:
Anton Bannykh
2019-06-17 18:57:26 +03:00
parent e3c9134904
commit d6c10d24e1
9 changed files with 76 additions and 60 deletions
@@ -179,6 +179,14 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
abstract val getContinuation: IrSimpleFunctionSymbol
abstract val coroutineContextGetter: IrSimpleFunctionSymbol
abstract val suspendCoroutineUninterceptedOrReturn: IrSimpleFunctionSymbol
abstract val coroutineGetContext: IrSimpleFunctionSymbol
abstract val returnIfSuspended: IrSimpleFunctionSymbol
private val binaryOperatorCache = mutableMapOf<Triple<Name, KotlinType, KotlinType>, IrSimpleFunctionSymbol>()
fun getBinaryOperator(name: Name, lhsType: KotlinType, rhsType: KotlinType): IrSimpleFunctionSymbol {
@@ -1,15 +1,15 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.inline
package org.jetbrains.kotlin.backend.common.lower.inline
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.Name
internal class DeepCopyIrTreeWithSymbolsForInliner(
val context: Context,
val context: CommonBackendContext,
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
val parent: IrDeclarationParent?
) {
@@ -1,24 +1,19 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@file:Suppress("FoldInitializerAndIfToElvis")
package org.jetbrains.kotlin.backend.common.lower.inline
package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.ir.createTemporaryVariableWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.lower.CoroutineIntrinsicLambdaOrigin
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
@@ -30,62 +25,47 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.util.OperatorNameConventions
typealias Context = JsIrBackendContext
class FunctionInlining(val context: CommonBackendContext) : IrElementTransformerVoidWithContext() {
// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
//-------------------------------------------------------------------------//
fun inline(irModule: IrModuleFragment): IrElement {
return irModule.accept(this, data = null)
}
fun inline(irModule: IrModuleFragment) = irModule.accept(this, data = null)
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
expression.transformChildrenVoid(this)
if (!(expression is IrCall || expression is IrConstructorCall) || !expression.symbol.owner.needsInlining)
val callee = when (expression) {
is IrCall -> expression.symbol.owner
is IrConstructorCall -> expression.symbol.owner
else -> return expression
}
if (!callee.needsInlining)
return expression
if (Symbols.isLateinitIsInitializedPropertyGetter(callee.symbol))
return expression
val languageVersionSettings = context.configuration.languageVersionSettings
when {
Symbols.isLateinitIsInitializedPropertyGetter(expression.symbol) ->
return expression
// Handle coroutine intrinsics
// TODO These should actually be inlined.
expression.descriptor.isBuiltInIntercepted(languageVersionSettings) ->
error("Continuation.intercepted is not available with release coroutines")
expression.symbol.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
return irCall(expression, context.coroutineSuspendOrReturn)
expression.symbol == context.intrinsics.jsCoroutineContext ->
return irCall(expression, context.coroutineGetContextJs)
}
val actualCallee = getFunctionDeclaration(callee.symbol)
val callee = getFunctionDeclaration(expression.symbol) // Get declaration of the function to be inlined.
callee.transformChildrenVoid(this) // Process recursive inline.
actualCallee.transformChildrenVoid(this) // Process recursive inline.
val parent = allScopes.map { it.irElement }.filterIsInstance<IrDeclarationParent>().lastOrNull()
val inliner = Inliner(expression, callee, currentScope!!, parent, context)
val inliner = Inliner(expression, actualCallee, currentScope!!, parent, context)
return inliner.inline()
}
private fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
// val descriptor = symbol.descriptor.original
// val languageVersionSettings = context.configuration.languageVersionSettings
// // TODO: Remove these hacks when coroutine intrinsics are fixed.
// return when {
// descriptor.isBuiltInIntercepted(languageVersionSettings) ->
// error("Continuation.intercepted is not available with release coroutines")
//
// descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
// context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.owner
//
// descriptor == context.ir.symbols.coroutineContextGetter ->
// context.ir.symbols.konanCoroutineContextGetter.owner
//
// else -> (symbol.owner as? IrSimpleFunction)?.resolveFakeOverride() ?: symbol.owner
// }
val descriptor = symbol.descriptor.original
val languageVersionSettings = context.configuration.languageVersionSettings
// TODO: Remove these hacks when coroutine intrinsics are fixed.
return when {
descriptor.isBuiltInIntercepted(languageVersionSettings) ->
error("Continuation.intercepted is not available with release coroutines")
return (symbol.owner as? IrSimpleFunction)?.resolveFakeOverride() ?: symbol.owner
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
context.ir.symbols.suspendCoroutineUninterceptedOrReturn.owner
symbol == context.ir.symbols.coroutineContextGetter ->
context.ir.symbols.coroutineGetContext.owner
else -> (symbol.owner as? IrSimpleFunction)?.resolveFakeOverride() ?: symbol.owner
}
}
private val IrFunction.needsInlining get() = (this.isInline && !this.isExternal)
@@ -94,7 +74,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
val callee: IrFunction,
val currentScope: ScopeWithIr,
val parent: IrDeclarationParent?,
val context: Context) {
val context: CommonBackendContext) {
val copyIrElement = run {
val typeParameters =
@@ -159,7 +159,8 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
// Coroutines
val jsCoroutineContext = context.symbolTable.referenceSimpleFunction(context.coroutineContextProperty.getter!!)
val jsCoroutineContext
get() = context.ir.symbols.coroutineContextGetter
val jsGetContinuation = getInternalFunction("getContinuation")
val jsGetKClass = getInternalWithoutPackage("getKClass")
@@ -187,6 +187,14 @@ class JsIrBackendContext(
)
override val getContinuation = symbolTable.referenceSimpleFunction(getJsInternalFunction("getContinuation"))
override val coroutineContextGetter = symbolTable.referenceSimpleFunction(context.coroutineContextProperty.getter!!)
override val suspendCoroutineUninterceptedOrReturn = symbolTable.referenceSimpleFunction(getJsInternalFunction(COROUTINE_SUSPEND_OR_RETURN_JS_NAME))
override val coroutineGetContext = symbolTable.referenceSimpleFunction(getJsInternalFunction(GET_COROUTINE_CONTEXT_NAME))
override val returnIfSuspended = symbolTable.referenceSimpleFunction(getJsInternalFunction("returnIfSuspended"))
}
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
@@ -213,7 +221,7 @@ class JsIrBackendContext(
// Top-level functions forced to be loaded
val coroutineSuspendOrReturn = symbolTable.referenceSimpleFunction(getJsInternalFunction(COROUTINE_SUSPEND_OR_RETURN_JS_NAME))
val coroutineSuspendOrReturn = ir.symbols.suspendCoroutineUninterceptedOrReturn
val coroutineSuspendGetter = ir.symbols.coroutineSuspendedGetter
val coroutineGetContext: IrSimpleFunctionSymbol
get() {
@@ -223,7 +231,9 @@ class JsIrBackendContext(
return contextGetter.symbol
}
val coroutineGetContextJs = symbolTable.referenceSimpleFunction(getJsInternalFunction(GET_COROUTINE_CONTEXT_NAME))
val coroutineGetContextJs
get() = ir.symbols.coroutineGetContext
val coroutineEmptyContinuation = symbolTable.referenceField(getProperty(FqName.fromSegments(listOf("kotlin", "coroutines", "js", "internal", "EmptyContinuation"))))
val coroutineContextProperty: PropertyDescriptor
@@ -7,11 +7,11 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining
import org.jetbrains.kotlin.backend.common.phaser.*
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.coroutines.JsSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.FunctionInlining
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineFunctionsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ReturnableBlockLowering
import org.jetbrains.kotlin.ir.declarations.IrFile
@@ -155,6 +155,11 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
context.continuation
}
add(backendContext.ir.symbols.returnIfSuspended) { call, context ->
val args = translateCallArguments(call, context)
args[0]
}
add(intrinsics.jsCoroutineContext) { _, context: JsGenerationContext ->
val contextGetter = backendContext.coroutineGetContext
val getterName = context.getNameForStaticFunction(contextGetter.owner)
@@ -96,6 +96,18 @@ class JvmSymbols(
override val getContinuation: IrSimpleFunctionSymbol
get() = TODO("not implemented")
override val coroutineContextGetter: IrSimpleFunctionSymbol
get() = TODO("not implemented")
override val suspendCoroutineUninterceptedOrReturn: IrSimpleFunctionSymbol
get() = TODO("not implemented")
override val coroutineGetContext: IrSimpleFunctionSymbol
get() = TODO("not implemented")
override val returnIfSuspended: IrSimpleFunctionSymbol
get() = TODO("not implemented")
val javaLangClass: IrClassSymbol =
if (firMode) createClass(FqName("java.lang.Class")) {}.symbol else context.getTopLevelClass(FqName("java.lang.Class"))